add verification on additional satscard, tapsigner and satschip operations
What changed, and why it matters
This commit adds extra verification steps when Sparrow Wallet talks to certain physical Bitcoin cards (Satscard, Tapsigner, Satschip). It makes the wallet check the card's authenticity before performing sensitive operations like reading an address or loading the keystore. The change looks like a defensive hardening patch, but the commit message gives no details about what specific attack or failure it prevents.
Treat as a security hardening improvement. Users relying on Satscard/Tapsigner/Satschip should upgrade to a version containing this commit. Developers should review whether `verify()` is also needed on other card operations not touched by this patch, and confirm the verification failure path surfaces a clear error to the user rather than silently continuing.
Security signals we found
Adds authentication/verification call before sensitive card operations
Targets hardware/NFC card workflows (Satscard, Tapsigner, Satschip)
Defensive hardening with no functional behavior change visible in diff
No explicit vulnerability description or CVE referenced in commit
Evidence from the diff
The patch adds a new verify() wrapper in CkCardApi that delegates to cardProtocol.verify(), and calls it in two places: (1) CkCardApi.getAddress() before dumping/reading a card slot, and (2) Tapsigner.getKeystore() after waiting for card authentication and before comparing/setting derivation paths. The verification likely checks a cryptographic proof from the card (e.g., certificate chain or signature) to ensure the device is genuine and has not been swapped or tampered with during the operation.
Changed components
src/main/java/com/sparrowwallet/sparrow/io/ckcard/CkCardApi.javasrc/main/java/com/sparrowwallet/sparrow/io/ckcard/Tapsigner.javaSatscard/Tapsigner/Satschip card integrationInspect captured patch +8 / −0
### src/main/java/com/sparrowwallet/sparrow/io/ckcard/CkCardApi.java
@@ -76,6 +76,10 @@ CardStatus getStatus() throws CardException {
return cardStatus;
}
+ void verify() throws CardException {
+ cardProtocol.verify();
+ }
+
void checkWait(CardStatus cardStatus, IntegerProperty delayProperty, StringProperty messageProperty) throws CardException {
if(cardStatus.auth_delay != null) {
int delay = cardStatus.auth_delay.intValue();
@@ -295,6 +299,8 @@ public Service<Address> getAddressService(StringProperty messageProperty) {
}
Address getAddress(int currentSlot, int lastSlot, String addr) throws CardException {
+ cardProtocol.verify();
+
if(currentSlot == lastSlot) {
CardDump cardDump = cardProtocol.dump(currentSlot);
if(!cardDump.sealed) {
### src/main/java/com/sparrowwallet/sparrow/io/ckcard/Tapsigner.java
@@ -75,6 +75,8 @@ public Keystore getKeystore(PolicyType policyType, String pin, List<ChildNumber>
}
cardApi.checkWait(cardStatus, new SimpleIntegerProperty(), messageProperty);
+ cardApi.verify();
+
if(!derivation.equals(cardStatus.getDerivation())) {
cardApi.setDerivation(derivation);
}Why this scored 46/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.