VYPR
High severity7.5GHSA Advisory· Published May 15, 2026

CVE-2026-44714

CVE-2026-44714

Description

The bitcoinj library is a Java implementation of the Bitcoin protocol. Prior to 0.17.1, ScriptExecution.correctlySpends() contains two fast-path verification bugs for standard P2PKH and native P2WPKH spends in core/src/main/java/org/bitcoinj/script/ScriptExecution.java. In both branches, bitcoinj verifies an attacker-controlled signature/public-key pair but fails to verify that the public key is the one committed to by the output being spent. As a result, any attacker keypair can satisfy bitcoinj's local verification for arbitrary P2PKH and P2WPKH outputs. This vulnerability is fixed in 0.17.1.

Affected products

1

Patches

2
b575a682acf6

ScriptExecution: add HASH160 checking to correctlySpends()

https://github.com/bitcoinj/bitcoinjSean GilliganApr 17, 2026via ghsa
1 file changed · +11 1
  • core/src/main/java/org/bitcoinj/script/ScriptExecution.java+11 1 modified
    @@ -1033,7 +1033,12 @@ public static void correctlySpends(Script script, Transaction txContainingThis,
                     throw new ScriptException(ScriptError.SCRIPT_ERR_SIG_DER, "Cannot decode", x);
                 }
                 ECKey pubkey = ECKey.fromPublicOnly(witness.getPush(1));
    -            Script scriptCode = ScriptBuilder.createP2PKHOutputScript(pubkey);
    +            byte[] requiredHash160 = ScriptPattern.extractHashFromP2WH(scriptPubKey);
    +            byte[] providedHash160 = CryptoUtils.sha256hash160(pubkey.getPubKey());
    +            if (!Arrays.equals(requiredHash160, providedHash160)) {
    +                throw new ScriptException(ScriptError.SCRIPT_ERR_EQUALVERIFY, "Invalid pubkey hash");
    +            }
    +            Script scriptCode = ScriptBuilder.createP2PKHOutputScript(requiredHash160);
                 Sha256Hash sigHash = txContainingThis.hashForWitnessSignature(scriptSigIndex, scriptCode, value,
                         signature.sigHashMode(), false);
                 boolean validSig = pubkey.verify(sigHash, signature);
    @@ -1050,6 +1055,11 @@ public static void correctlySpends(Script script, Transaction txContainingThis,
                     throw new ScriptException(ScriptError.SCRIPT_ERR_SIG_DER, "Cannot decode", x);
                 }
                 ECKey pubkey = ECKey.fromPublicOnly(Objects.requireNonNull(chunks.get(1).data));
    +            byte[] requiredHash160 = ScriptPattern.extractHashFromP2PKH(scriptPubKey);
    +            byte[] providedHash160 = CryptoUtils.sha256hash160(pubkey.getPubKey());
    +            if (!Arrays.equals(requiredHash160, providedHash160)) {
    +                throw new ScriptException(ScriptError.SCRIPT_ERR_EQUALVERIFY, "Invalid pubkey hash");
    +            }
                 Sha256Hash sigHash = txContainingThis.hashForSignature(scriptSigIndex, scriptPubKey,
                         signature.sigHashMode(), false);
                 boolean validSig = pubkey.verify(sigHash, signature);
    
2bc5653c41d2

Script: add some extra hashing

https://github.com/bitcoinj/bitcoinjSean GilliganApr 4, 2026via ghsa
1 file changed · +4 0
  • core/src/main/java/org/bitcoinj/script/Script.java+4 0 modified
    @@ -1727,6 +1727,8 @@ public void correctlySpends(Transaction txContainingThis, int scriptSigIndex, @N
                     throw new ScriptException(ScriptError.SCRIPT_ERR_SIG_DER, "Cannot decode", x);
                 }
                 ECKey pubkey = ECKey.fromPublicOnly(witness.getPush(1));
    +            if (!Arrays.equals(CryptoUtils.sha256hash160(pubkey.getPubKey()), ScriptPattern.extractHashFromP2WH(scriptPubKey)))
    +                throw new ScriptException(ScriptError.SCRIPT_ERR_EQUALVERIFY, "");
                 Script scriptCode = ScriptBuilder.createP2PKHOutputScript(pubkey);
                 Sha256Hash sigHash = txContainingThis.hashForWitnessSignature(scriptSigIndex, scriptCode, value,
                         signature.sigHashMode(), false);
    @@ -1743,6 +1745,8 @@ public void correctlySpends(Transaction txContainingThis, int scriptSigIndex, @N
                     throw new ScriptException(ScriptError.SCRIPT_ERR_SIG_DER, "Cannot decode", x);
                 }
                 ECKey pubkey = ECKey.fromPublicOnly(chunks.get(1).data);
    +            if (!Arrays.equals(CryptoUtils.sha256hash160(pubkey.getPubKey()), ScriptPattern.extractHashFromP2PKH(scriptPubKey)))
    +                throw new ScriptException(ScriptError.SCRIPT_ERR_EQUALVERIFY, "");
                 Sha256Hash sigHash = txContainingThis.hashForSignature(scriptSigIndex, scriptPubKey,
                         signature.sigHashMode(), false);
                 boolean validSig = pubkey.verify(sigHash, signature);
    

Vulnerability mechanics

AI mechanics synthesis has not run for this CVE yet.

References

6

News mentions

0

No linked articles in our index yet.