Static read-through audit of crates/dpp-rules. One verified finding; everything else (CAS check-digit, SVHC/surfactant/fibre validators, JWS payload decoding) is fail-closed and sound.
1. content_hash() panics instead of erroring on non-finite floats in unauthenticated content
Location: src/bundle/verify.rs:34
Issue: serde_jcs::to_vec(content).expect("JCS canonicalisation is infallible") — the "infallible" claim is false. RFC 8785 JCS returns Err for non-finite (NaN/Infinity) floats. content_hash() runs on bundle.content, a serde_json::Value deserialized straight off the wire, before it has been authenticated (the EdDSA signature only covers manifest_jws, not raw content).
Failure scenario: A bundle whose content contains a JSON number with a huge exponent (e.g. 1e400) parses to f64::INFINITY (workspace serde_json = "1", no arbitrary_precision). serde_jcs::to_vec then correctly returns Err — but the .expect() panics instead of the function returning RulesetError. This turns a module explicitly documented as "fail-closed on ... malformed input" into a reachable panic/crash on the verification path itself, triggered by attacker-controlled data. No existing test exercises this path.
#![forbid(unsafe_code)] is enforced; no other issues found.
Static read-through audit of
crates/dpp-rules. One verified finding; everything else (CAS check-digit, SVHC/surfactant/fibre validators, JWS payload decoding) is fail-closed and sound.1.
content_hash()panics instead of erroring on non-finite floats in unauthenticated contentLocation:
src/bundle/verify.rs:34Issue:
serde_jcs::to_vec(content).expect("JCS canonicalisation is infallible")— the "infallible" claim is false. RFC 8785 JCS returnsErrfor non-finite (NaN/Infinity) floats.content_hash()runs onbundle.content, aserde_json::Valuedeserialized straight off the wire, before it has been authenticated (the EdDSA signature only coversmanifest_jws, not raw content).Failure scenario: A bundle whose
contentcontains a JSON number with a huge exponent (e.g.1e400) parses tof64::INFINITY(workspaceserde_json = "1", noarbitrary_precision).serde_jcs::to_vecthen correctly returnsErr— but the.expect()panics instead of the function returningRulesetError. This turns a module explicitly documented as "fail-closed on ... malformed input" into a reachable panic/crash on the verification path itself, triggered by attacker-controlled data. No existing test exercises this path.#![forbid(unsafe_code)]is enforced; no other issues found.