Fix string slicing in TXT record validation
What changed, and why it matters
This commit fixes a crash bug in how rust-lightning checks DNS text records embedded in private onion messages. The old code used string slicing that could panic if a TXT record contained multi-byte characters and the prefix length landed in the middle of a character. The fix compares raw bytes instead, avoiding the panic. A malicious or malformed onion message could have triggered a denial-of-service crash in the node processing it.
Upgrade to a release containing this commit. Nodes that process onion-message DNSSEC queries for BIP 353 human-readable names are exposed to a remote crash; prioritise updating public or well-connected nodes that may receive such messages.
Security signals we found
panic due to non-character-boundary string slicing
denial-of-service vector via crafted onion message TXT record
BIP 353 DNSSEC resolution input validation
third-party security report from Block's Security Team
Evidence from the diff
In lightning/src/onion_message/dns_resolution.rs, the code validates TXT records in BIP 353 DNSSEC-over-onion-message resolution by checking whether each record starts with the URI prefix ‘bitcoin:’. The original code used data_string[..URI_PREFIX.len()] on a Rust String. Because Rust string slicing requires byte indices to fall on UTF-8 character boundaries, a TXT record whose bytes are valid UTF-8 but where URI_PREFIX.len() (8 bytes) is not a character boundary causes a panic. The patch replaces the slice with a byte-slice comparison: data_string.as_bytes()[..URI_PREFIX.len()].eq_ignore_ascii_case(URI_PREFIX.as_bytes()). This removes the character-boundary requirement and prevents the panic. URI_PREFIX is ASCII and 8 bytes long, so the byte slice is always well-defined for any string of length > 8 bytes.
Changed components
lightning/src/onion_message/dns_resolution.rsOMNameResolver TXT record validationBIP 353 DNSSEC-over-onion-message name resolutionInspect captured patch +2 / −1
diff --git a/lightning/src/onion_message/dns_resolution.rs b/lightning/src/onion_message/dns_resolution.rs
index 5f68fa7..67d91bc 100644
--- a/lightning/src/onion_message/dns_resolution.rs
+++ b/lightning/src/onion_message/dns_resolution.rs
@@ -537,7 +537,8 @@ impl OMNameResolver {
.filter_map(|data| String::from_utf8(data).ok())
.filter(|data_string| data_string.len() > URI_PREFIX.len())
.filter(|data_string| {
- data_string[..URI_PREFIX.len()].eq_ignore_ascii_case(URI_PREFIX)
+ let pfx = &data_string.as_bytes()[..URI_PREFIX.len()];
+ pfx.eq_ignore_ascii_case(URI_PREFIX.as_bytes())
});
// Check that there is exactly one TXT record that begins with
// bitcoin: as required by BIP 353 (and is valid UTF-8).
Why this scored 62/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.