RustSec logo

History ⋅ Edit ⋅ JSON (OSV)

RUSTSEC-2026-0498

Transaction readers accept trailing bytes, so a parsed transaction can carry another transaction id

Reported
Issued
Package
bsv-rs (crates.io)
Type
Vulnerability
Categories
Keywords
#bitcoin #transaction #txid #parsing #trailing-data
Aliases
References
CVSS Score
5.3 MEDIUM
CVSS Details
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality Impact
None
Integrity Impact
Low
Availability Impact
None
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Patched
  • >=0.8.5, <0.9.0-beta.1
  • >0.9.0-beta.7
Affected Functions
Version
bsv_rs::transaction::Transaction::from_binary
  • <0.8.5
  • >=0.9.0-beta.1, <=0.9.0-beta.7
bsv_rs::transaction::Transaction::from_ef
  • <0.8.5
  • >=0.9.0-beta.1, <=0.9.0-beta.7
bsv_rs::transaction::Transaction::from_hex
  • <0.8.5
  • >=0.9.0-beta.1, <=0.9.0-beta.7
bsv_rs::transaction::Transaction::from_hex_ef
  • <0.8.5
  • >=0.9.0-beta.1, <=0.9.0-beta.7
bsv_rs::transaction::Transaction::from_json
  • <0.8.5
  • >=0.9.0-beta.1, <=0.9.0-beta.7
bsv_rs::transaction::Transaction::parse_script_offsets
  • <0.8.5
  • >=0.9.0-beta.1, <=0.9.0-beta.7

Description

Transaction::from_binary and Transaction::from_hex read one transaction from the front of their input, did not check that the input ended there, and kept the whole input as the transaction's cached serialization: to_binary, to_hex and id() then answered for bytes that are not the transaction's. Transaction::from_json, given a hex field, reads it through from_hex and answers the same. from_ef, from_hex_ef and parse_script_offsets also read a prefix.

An application that takes bytes or hex from outside, parses them with these readers and then uses id() or the serialization could be given one transaction under another identity: the same parsed fields, a different id. An application that passes them only bytes it produced or has already checked is not affected.

0.8.5 refuses a byte after the transaction; Transaction::from_reader reads from the front of a longer buffer. Where upgrading is not possible, parse with Transaction::from_binary, call tx.invalidate_caches() (public from 0.3.16) and require tx.to_binary() == bytes.

Advisory available under CC0-1.0 license.