CVE-2026-44714 Overview
CVE-2026-44714 is a signature verification flaw in the bitcoinj library, a Java implementation of the Bitcoin protocol. Versions prior to 0.17.1 contain two fast-path verification bugs in ScriptExecution.correctlySpends() for standard Pay-to-Public-Key-Hash (P2PKH) and native Pay-to-Witness-Public-Key-Hash (P2WPKH) spends. The library verifies an attacker-supplied signature against an attacker-supplied public key without confirming the public key matches the hash committed by the spent output. Any attacker keypair satisfies bitcoinj's local verification for arbitrary P2PKH and P2WPKH outputs. The flaw is tracked under [CWE-347] Improper Verification of Cryptographic Signature.
Critical Impact
Applications relying on bitcoinj for transaction validation can accept forged spends of standard outputs, undermining integrity of on-chain state observed by the library.
Affected Products
- bitcoinj library versions prior to 0.17.1
- Java applications consuming bitcoinj for P2PKH transaction validation
- Java applications consuming bitcoinj for native P2WPKH (SegWit v0) transaction validation
Discovery Timeline
- 2026-05-15 - CVE-2026-44714 published to NVD
- 2026-05-18 - Last updated in NVD database
Technical Details for CVE-2026-44714
Vulnerability Analysis
The bitcoinj library validates spends by executing the Bitcoin script associated with a transaction input. For common output types, the library uses optimized fast paths in core/src/main/java/org/bitcoinj/script/ScriptExecution.java that bypass full script interpretation. These fast paths handle P2PKH and native P2WPKH spends.
In both fast paths, bitcoinj parses the public key supplied by the spender and verifies the supplied signature against that public key over the transaction sighash. The check confirms the spender holds a valid keypair, but does not confirm the keypair is the one authorized by the output. The result is that any attacker-controlled keypair produces a signature that the library treats as valid for any P2PKH or P2WPKH UTXO.
Root Cause
P2PKH and P2WPKH outputs commit to a HASH160 (RIPEMD160(SHA256(pubkey))) of the authorized public key, not the public key itself. Correct verification requires comparing HASH160(providedPubkey) against the hash embedded in scriptPubKey before accepting the signature. The pre-patch code constructed an internal scriptCode directly from the attacker-supplied public key, skipping the equality check that the standard Bitcoin script OP_EQUALVERIFY opcode would have enforced.
Attack Vector
An attacker generates an arbitrary keypair, crafts a transaction that spends a victim P2PKH or P2WPKH output, and includes their own public key and a signature over their crafted transaction. A bitcoinj-based wallet, SPV client, or block validator processing this transaction passes correctlySpends() and treats the spend as valid. Consensus-level Bitcoin nodes reject the transaction, but bitcoinj clients diverge from network state until the canonical chain corrects them.
// Patched code from core/src/main/java/org/bitcoinj/script/ScriptExecution.java
// Adds HASH160 verification against the scriptPubKey commitment
throw new ScriptException(ScriptError.SCRIPT_ERR_SIG_DER, "Cannot decode", x);
}
ECKey pubkey = ECKey.fromPublicOnly(witness.getPush(1));
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);
Source: bitcoinj commit b575a682
Detection Methods for CVE-2026-44714
Indicators of Compromise
- bitcoinj JAR artifacts with version metadata earlier than 0.17.1 present in application dependencies or pom.xml/build.gradle lockfiles.
- Divergence between bitcoinj-reported transaction state and authoritative Bitcoin Core or third-party block explorer state for the same UTXOs.
- Application logs accepting transactions later marked invalid or absent on the canonical chain.
Detection Strategies
- Run dependency inventory scans across Java build manifests for org.bitcoinj:bitcoinj-core versions below 0.17.1.
- Cross-validate bitcoinj correctlySpends() outcomes against an authoritative full node for any transaction handling business logic.
- Inspect runtime classpaths of deployed Java services to identify shaded or repackaged bitcoinj copies missing the patched ScriptExecution.java.
Monitoring Recommendations
- Alert on transactions accepted locally but unconfirmed beyond a defined threshold against an independent Bitcoin node.
- Log every ScriptException thrown by bitcoinj after patching to detect attempted exploitation against upgraded clients.
- Track outbound network connections from wallet services to unexpected peers that may relay forged spends.
How to Mitigate CVE-2026-44714
Immediate Actions Required
- Upgrade bitcoinj to version 0.17.1 or later across all Java services, SDKs, and embedded clients.
- Audit any business logic that treats ScriptExecution.correctlySpends() as authoritative without confirmation from a full node.
- Rebuild and redeploy any application that statically links or shades bitcoinj to ensure the patched classes are loaded.
Patch Information
The vulnerability is fixed in bitcoinj 0.17.1. The remediation adds a HASH160 equality check between the spender-supplied public key and the hash committed in scriptPubKey before signature verification. Details are published in the bitcoinj GitHub Security Advisory GHSA-hfcf-v2f8-x9pc and applied across commit 2bc5653c and commit b575a682.
Workarounds
- Require independent confirmation of every spend from a non-bitcoinj full node before honoring application state changes.
- Disable use of bitcoinj's fast-path validation in critical financial flows and rely on external validation services until the upgrade is deployed.
- Restrict bitcoinj clients to monitoring roles only, removing any authority to release funds, settle invoices, or mark obligations satisfied.
# Maven: pin bitcoinj-core to the patched release
mvn versions:use-dep-version -Dincludes=org.bitcoinj:bitcoinj-core -DdepVersion=0.17.1 -DforceVersion=true
# Gradle: update the dependency declaration
# build.gradle
# implementation 'org.bitcoinj:bitcoinj-core:0.17.1'
# Verify resolved version on the runtime classpath
mvn dependency:tree | grep bitcoinj-core
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


