Skip to main content

bitcoinj-core EUVDEUVD-2026-30571

| CVE-2026-44714 HIGH
Improper Verification of Cryptographic Signature (CWE-347)
2026-05-08 https://github.com/bitcoinj/bitcoinj GHSA-hfcf-v2f8-x9pc
7.5
CVSS 3.1 · GitHub Advisory
Share

Severity by source

GitHub Advisory PRIMARY
7.5 HIGH
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N

Primary rating from GitHub Advisory · only source for this CVE.

CVSS VectorGitHub Advisory

Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
High
Availability
None

Lifecycle Timeline

3
Source Code Evidence Fetched
May 08, 2026 - 18:01 vuln.today
Analysis Generated
May 08, 2026 - 18:01 vuln.today
CVE Published
May 08, 2026 - 17:43 nvd
HIGH 7.5

DescriptionGitHub Advisory

Summary

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 doesn't affect the SPV (simple payment verification) trust model, as this model follows PoW and doesn't verify input signatures at all.

Details

The issue is in the optimized branches of ScriptExecution.correctlySpends(...).

In the P2PKH fast path at core/src/main/java/org/bitcoinj/script/ScriptExecution.java:1042, the code:

  • parses the attacker-supplied signature from scriptSig
  • parses the attacker-supplied public key from scriptSig
  • computes the sighash against the victim output's scriptPubKey
  • checks only pubkey.verify(sigHash, signature)

It never enforces the missing P2PKH binding:

  • HASH160(pubkey) == ScriptPattern.extractHashFromP2PKH(scriptPubKey)

That means the OP_DUP OP_HASH160 <hash> OP_EQUALVERIFY OP_CHECKSIG semantics are not actually enforced in this fast path.

Relevant code:

java
} else if (ScriptPattern.isP2PKH(scriptPubKey)) {
    if (chunks.size() != 2)
        throw new ScriptException(...);
    TransactionSignature signature;
    try {
        byte[] data = Objects.requireNonNull(chunks.get(0).data);
        signature = TransactionSignature.decodeFromBitcoin(data, true, true);
    } catch (SignatureDecodeException x) {
        throw new ScriptException(...);
    }
    ECKey pubkey = ECKey.fromPublicOnly(Objects.requireNonNull(chunks.get(1).data));
    Sha256Hash sigHash = txContainingThis.hashForSignature(scriptSigIndex, scriptPubKey,
            signature.sigHashMode(), false);
    boolean validSig = pubkey.verify(sigHash, signature);
    if (!validSig)
        throw new ScriptException(...);
}

In the native P2WPKH fast path at core/src/main/java/org/bitcoinj/script/ScriptExecution.java:1023, the bug is similar. The code:

  • reads the attacker-supplied pubkey from witness
  • builds scriptCode from that attacker pubkey with ScriptBuilder.createP2PKHOutputScript(pubkey)
  • computes the BIP143 sighash using that attacker-derived scriptCode
  • verifies the signature against the attacker pubkey

It never enforces:

  • HASH160(pubkey) == ScriptPattern.extractHashFromP2WH(scriptPubKey)

So for P2WPKH, the attacker controls both the pubkey and the scriptCode used for signing.

Relevant code:

java
if (ScriptPattern.isP2WPKH(scriptPubKey)) {
    Objects.requireNonNull(witness);
    if (witness.getPushCount() < 2)
        throw new ScriptException(...);
    TransactionSignature signature;
    try {
        signature = TransactionSignature.decodeFromBitcoin(witness.getPush(0), true, true);
    } catch (SignatureDecodeException x) {
        throw new ScriptException(...);
    }
    ECKey pubkey = ECKey.fromPublicOnly(witness.getPush(1));
    Script scriptCode = ScriptBuilder.createP2PKHOutputScript(pubkey);
    Sha256Hash sigHash = txContainingThis.hashForWitnessSignature(scriptSigIndex, scriptCode, value,
            signature.sigHashMode(), false);
    boolean validSig = pubkey.verify(sigHash, signature);
    if (!validSig)
        throw new ScriptException(...);
}

Affected call sites include:

  • core/src/main/java/org/bitcoinj/core/TransactionInput.java:546
  • core/src/main/java/org/bitcoinj/wallet/Wallet.java:4520
  • core/src/main/java/org/bitcoinj/signers/LocalTransactionSigner.java:84
  • core/src/main/java/org/bitcoinj/signers/CustomTransactionSigner.java:77

These call sites use correctlySpends() for transaction/input validation and pre-signing checks. Any application that treats a successful result from this path as proof that a spend is valid is affected.

Fix

The issue is fixed on the release-0.17 branch via 2bc5653c41d260d840692bc554690d4d79208f9c, and on master via b575a682acf614b9ff95cacbdeb48f86c3ababe0. A 0.17.1 maintenance release has been made available on Maven Central.

AnalysisAI

Signature verification bypass in bitcoinj-core library allows attackers to forge Bitcoin transaction validations by exploiting fast-path optimization flaws in P2PKH and P2WPKH script execution. Versions 0.15 through 0.17.0 fail to verify that attacker-supplied public keys match the hash committed to in transaction outputs, enabling arbitrary keypairs to satisfy local transaction validation checks. While this does not affect SPV (Simple Payment Verification) nodes that follow proof-of-work without signature verification, applications using the correctlySpends() method for transaction validation or pre-signing checks are vulnerable to accepting fraudulent transactions. Vendor-released patch available in version 0.17.1, fixes confirmed in GitHub commits 2bc5653c and b575a682. No active exploitation confirmed (not in CISA KEV); EPSS data unavailable.

Technical ContextAI

bitcoinj is a Java implementation of the Bitcoin protocol used by wallets and applications to interact with Bitcoin networks. The vulnerability resides in the ScriptExecution.correctlySpends() method's optimized fast-paths for two standard Bitcoin transaction types: Pay-to-PubKey-Hash (P2PKH) and native Pay-to-Witness-PubKey-Hash (P2WPKH). These fast-paths were designed to bypass full Bitcoin Script interpreter execution for performance, but introduced a critical logic error. In Bitcoin's UTXO model, outputs lock funds to a specific public key hash - the spender must provide a public key that hashes to that committed value. The vulnerable code verifies ECDSA signatures against attacker-supplied public keys but skips the crucial HASH160(pubkey) == committed_hash check mandated by Bitcoin's OP_EQUALVERIFY opcode semantics. For P2WPKH, the flaw is compounded because the attacker-controlled pubkey is used to construct the scriptCode for BIP143 signature hashing, allowing complete control over the verification context. This is classified as CWE-347 (Improper Verification of Cryptographic Signature) because the cryptographic operation succeeds but lacks binding to the claimed identity. The affected CPE is pkg:maven/org.bitcoinj:bitcoinj-core covering versions ≥0.15 and <0.17.1.

RemediationAI

Upgrade org.bitcoinj:bitcoinj-core to version 0.17.1 or later, which contains fixes in commits 2bc5653c41d260d840692bc554690d4d79208f9c (release-0.17 branch) and b575a682acf614b9ff95cacbdeb48f86c3ababe0 (master branch). Update your Maven or Gradle dependency to 'org.bitcoinj:bitcoinj-core:0.17.1' - the patched version is available on Maven Central. For applications that cannot immediately upgrade, implement compensating controls by avoiding reliance on correctlySpends() return values for security-critical validation decisions in non-SPV contexts. Specifically, for any transaction acceptance or authorization logic outside standard SPV operation, add explicit verification that HASH160(extracted_pubkey) matches the committed hash in scriptPubKey for both P2PKH and P2WPKH spends before trusting correctlySpends() results. Note this workaround requires reimplementing the missing hash verification logic and has maintenance overhead risk. For applications using SPV trust model exclusively (following longest proof-of-work chain without local signature verification), no immediate action is required beyond normal upgrade cycles, as SPV operation is unaffected by this flaw. Vendor advisory and technical details: https://github.com/bitcoinj/bitcoinj/security/advisories/GHSA-hfcf-v2f8-x9pc. Release information: https://github.com/bitcoinj/bitcoinj/releases/tag/v0.17.1.

More in Java

View all
CVE-2012-4681 CRITICAL POC
9.8 Aug 28

Oracle Java SE 7 Update 6 and earlier contains multiple sandbox bypass vulnerabilities via the ClassFinder and forName m

CVE-2015-7450 CRITICAL POC
9.8 Jan 02

Remote code execution in IBM Sterling B2B Integrator, Sterling Integrator, and Tivoli Common Reporting allows unauthenti

CVE-2013-2465 CRITICAL POC
9.8 Jun 18

Java Runtime Environment sandbox bypass via incorrect image channel verification in 2D component allows remote unauthent

CVE-2011-3544 CRITICAL POC
9.8 Oct 19

Oracle Java SE JDK/JRE 7 and 6 Update 27 and earlier allows remote code execution with complete system compromise throug

CVE-2010-1871 HIGH POC
8.8 Aug 05

JBoss Seam 2 in Red Hat JBoss EAP 4.3.0 fails to sanitize JBoss Expression Language inputs, allowing remote attackers to

CVE-2012-1723 CRITICAL POC
9.8 Jun 16

Unspecified vulnerability in the Java Runtime Environment (JRE) component in Oracle Java SE 7 update 4 and earlier, 6 up

CVE-2013-0422 CRITICAL POC
9.8 Jan 10

Multiple vulnerabilities in Oracle Java 7 before Update 11 allow remote attackers to execute arbitrary code by (1) using

CVE-2012-0507 CRITICAL POC
9.8 Jun 07

Unspecified vulnerability in the Java Runtime Environment (JRE) component in Oracle Java SE 7 Update 2 and earlier, 6 Up

CVE-2015-4852 CRITICAL POC
9.8 Nov 18

The WLS Security component in Oracle WebLogic Server 10.3.6.0, 12.1.2.0, 12.1.3.0, and 12.2.1.0 allows remote attackers

CVE-2012-5076 CRITICAL POC
9.8 Oct 16

Unspecified vulnerability in the Java Runtime Environment (JRE) component in Oracle Java SE 7 Update 7 and earlier allow

CVE-2017-3066 CRITICAL POC
9.8 Apr 27

Remote unauthenticated attackers can execute arbitrary code on Adobe ColdFusion servers through Java deserialization fla

CVE-2012-0391 CRITICAL POC
9.8 Jan 08

The ExceptionDelegator component in Apache Struts before 2.2.3.1 interprets parameter values as OGNL expressions during

Share

EUVD-2026-30571 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy