Fix panic when deserializing `Duration`
What changed, and why it matters
This commit fixes a bug where a specially crafted network message could cause the Lightning Dev Kit software to crash. The crash happens while reading a time duration from the message. The fix rejects obviously invalid duration values before they can trigger the crash. The bug was discovered by an automated fuzz tester, not a reported real-world attack.
Apply the patch. Ensure all `Duration` deserialization paths use the validated `Readable` implementation. Consider adding regression tests or corpus entries from the `onion_message` fuzzer. No immediate incident-response action is indicated absent evidence of active exploitation.
Security signals we found
Remote denial-of-service (panic/crash) via deserialization of untrusted input
Integer overflow-like panic in standard-library wrapper (`Duration::new`)
Missing input validation before constructing `Duration`
Network-message parsing path affected (onion/blinded path context)
Fuzzer-discovered, not a reported in-the-wild exploit
Evidence from the diff
The patch changes Duration deserialization in lightning/src/util/ser.rs. Previously it called Duration::new(secs, nanos), which panics when nanoseconds in excess of a second overflow the seconds field. The fix validates that nanos < 1_000_000_000 and returns DecodeError::InvalidValue otherwise. The commit message states this is remotely triggerable via a malicious blinded path context and was found by the onion_message fuzzer.
Changed components
lightning/src/util/ser.rsDuration deserialization (`Readable for Duration`)Onion message / blinded path handlingInspect captured patch +8 / −1
diff --git a/lightning/src/util/ser.rs b/lightning/src/util/ser.rs
index e88e1eb..d78b3e9 100644
--- a/lightning/src/util/ser.rs
+++ b/lightning/src/util/ser.rs
@@ -1688,7 +1688,14 @@ impl Readable for Duration {
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
let secs = Readable::read(r)?;
let nanos = Readable::read(r)?;
- Ok(Duration::new(secs, nanos))
+ // Duration::new panics if the nanosecond part in excess of a second, added to the second
+ // part, overflows. To ensure this won't happen, we simply reject any case where there are
+ // nanoseconds in excess of a second, which is invalid anyway.
+ if nanos >= 1_000_000_000 {
+ Err(DecodeError::InvalidValue)
+ } else {
+ Ok(Duration::new(secs, nanos))
+ }
}
}
Why this scored 79/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.