Skip to content

[29.x] Backport fixes for CVE-2025-46598#33788

Merged
glozow merged 11 commits intobitcoin:29.xfrom
luke-jr:cve2025_46598_pt3-29.1
Jan 12, 2026
Merged

[29.x] Backport fixes for CVE-2025-46598#33788
glozow merged 11 commits intobitcoin:29.xfrom
luke-jr:cve2025_46598_pt3-29.1

Conversation

@luke-jr
Copy link
Member

@luke-jr luke-jr commented Nov 5, 2025

No description provided.

darosior and others added 11 commits November 3, 2025 21:50
A stripped witness is detected as a special case in mempool acceptance to make sure we do not add
the wtxid (which is =txid since witness is stripped) to the reject filter. This is because it may
interfere with 1p1c parent relay which currently uses orphan reconciliation (and originally it was
until wtxid-relay was widely adopted on the network.

This commit adds a test for this special case in the p2p_segwit function test, both when spending
a native segwit output and when spending a p2sh-wrapped segwit output.

Thanks to Eugene Siegel for pointing out the p2sh-wrapped detection did not have test coverage by
finding a bug in a related patch of mine.

Github-Pull: bitcoin#33105
Rebased-From: eb07320
…wit outputs

We will use this helper in later commits to detect witness stripping without having
to execute every input Script three times in a row.

Github-Pull: bitcoin#33105
Rebased-From: 2907b58
Since it was introduced in 4eb5155 (bitcoin#18044), the detection of a
stripped witness relies on running the Script checks 3 times. In the worst case, this consists in
running Script validation 3 times for every single input.

Detection of a stripped witness is necessary because in this case wtxid==txid, and the transaction's
wtxid must not be added to the reject filter or it could allow a malicious peer to interfere with
txid-based orphan resolution as used in 1p1c package relay.

However it is not necessary to run Script validation to detect a stripped witness (much less so
doing it 3 times in a row). There are 3 types of witness program: defined program types (Taproot,
P2WPKH, P2WSH), undefined types, and the Pay-to-anchor carve-out.

For defined program types, Script validation with an empty witness will always fail (by consensus).
For undefined program types, Script validation is always going to fail regardless of the witness (by
standardness). For P2A, an empty witness is never going to lead to a failure.

Therefore it holds that we can always detect a stripped witness without re-running Script validation.
However this might lead to more "false positives" (cases where we return witness stripping for an
otherwise invalid transaction) than the existing implementation. For instance a transaction with one
P2PKH input with an invalid signature and one P2WPKH input with its witness stripped. The existing
implementation would treat it as consensus invalid while the implementation in this commit would
always consider it witness stripped.

Github-Pull: bitcoin#33105
Rebased-From: 27aefac
Do not discourage nodes even when they send us consensus invalid
transactions.

Because we do not discourage nodes for transactions we consider
non-standard, we don't get any DoS protection from this check in
adversarial scenarios, so remove the check entirely both to simplify the
code and reduce the risk of splitting the network due to changes in tx
relay policy.

NOTE: Backport required additional adjustment in test/functional/p2p_invalid_tx

Github-Pull: bitcoin#33050
Rebased-From: 266dd0e
Previously, we would check failing input scripts twice when considering
a transaction for the mempool, in order to distinguish policy failures
from consensus failures. This allowed us both to provide a different
error message and to discourage peers for consensus failures. Because we
are no longer discouraging peers for consensus failures during tx relay,
and because checking a script can be expensive, only do this once.

Also renames non-mandatory-script-verify-flag error to
mempool-script-verify-flag-failed.

NOTE: Backport required additional adjustment in test/functional/feature_block

Github-Pull: bitcoin#33050
Rebased-From: b29ae9e
@DrahtBot
Copy link
Contributor

DrahtBot commented Nov 5, 2025

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Code Coverage & Benchmarks

For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/33788.

Reviews

See the guideline for information on the review process.

Type Reviewers
ACK sipa, darosior, glozow
Concept ACK bensig

If your review is incorrectly listed, please copy-paste <!--meta-tag:bot-skip--> into the comment that the bot should ignore.

Comment on lines -168 to +162
with node.assert_debug_log(['Erased 100 orphan transaction(s) from peer=26']):
with node.assert_debug_log(['Erased 100 orphan transaction(s) from peer=']):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: Not in master commit (another approach is used for this test)

badtx.rehash()
badblock = self.update_block(blockname, [badtx])
reject_reason = (template.block_reject_reason or template.reject_reason)
if reject_reason and reject_reason.startswith("mempool-script-verify-flag-failed"):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: reject_reason could be None here, so a check was added (not in master commit)

@luke-jr luke-jr changed the title [29.x] Backport fixes for CVE-2025 46598 [29.x] Backport fixes for CVE-2025-46598 Nov 5, 2025
@bensig
Copy link
Contributor

bensig commented Jan 5, 2026

Useful to anyone who wants to continue to run core v29... not confident enough to ACK consensus-adjacent code as a newer contributor, but the backport mechanics look clean.

What I checked:

cc: @glozow @sipa in case you have bandwidth to look at this since you reviewed the original PRs.

@sipa
Copy link
Member

sipa commented Jan 7, 2026

Concept ACK, will review in some more detail soon.

Copy link
Member

@darosior darosior left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept ACK. Backport looks good, the functional test adaptation are fine. Been running the sighash_cache fuzz target and now doing a full sync on this branch for good measure, although there has been virtually no change to the interpreter between 29 and 30.

@sipa
Copy link
Member

sipa commented Jan 8, 2026

Code review ACK 6f136cd

I have done the rebase myself, and hit the exact same necessary modifications as @luke-jr commented on above.

@DrahtBot DrahtBot requested a review from darosior January 8, 2026 20:44
Copy link
Member

@darosior darosior left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 6f136cd

@fanquake fanquake added this to the 29.3 milestone Jan 9, 2026
@glozow glozow mentioned this pull request Jan 12, 2026
7 tasks
@glozow
Copy link
Member

glozow commented Jan 12, 2026

ACK 6f136cd, looks correct

@glozow glozow merged commit 6e7ea3c into bitcoin:29.x Jan 12, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants