Finding
MessageBuilder::position_with_config converts caller-supplied f64 lat/lon directly to i32 via an as cast without validating that the values are finite or within the valid geographic range [-90, 90] / [-180, 180]. The inline // SAFETY comment asserts the ranges hold, but no runtime guard enforces them.
Evidence
crates/kerykeion/src/message.rs:73
latitude_i: (lat * 1e7) as i32, // SAFETY: lat ∈ [-90, 90] so lat*1e7 ∈ [-9e8, 9e8] which fits i32 (±2.1e9)
crates/kerykeion/src/message.rs:74
longitude_i: (lon * 1e7) as i32, // SAFETY: lon ∈ [-180, 180] so lon*1e7 ∈ [-1.8e9, 1.8e9] which fits i32
No assert / ensure / guard precedes these lines. Rust 1.45+ saturates an out-of-range f64 as i32 (NaN→0, ±Inf→i32 extremes), so the cast never panics but the result is garbage coordinate data.
Why this matters
An agent calling MessageBuilder::position with a NaN or Inf from a failed GPS read silently broadcasts position (0, 0) or extreme sentinel values over the mesh, corrupting every recipient's location database. In the SIGINT/tracking context this is an undetectable data-integrity failure on outbound traffic, and the // SAFETY comment misclassifies a missing runtime contract as a proven invariant.
Desired correction
Add a finiteness + range check before the casts, e.g. if !lat.is_finite() || !(-90.0..=90.0).contains(&lat) || !lon.is_finite() || !(-180.0..=180.0).contains(&lon) { return Err(Error::InvalidPosition { lat, lon }); }, and change the position constructors to return Result<Self, Error>. Done when: passing f64::NAN as lat returns an Err from the position builder rather than producing a packet.
Finding
MessageBuilder::position_with_configconverts caller-suppliedf64lat/lon directly toi32via anascast without validating that the values are finite or within the valid geographic range[-90, 90]/[-180, 180]. The inline// SAFETYcomment asserts the ranges hold, but no runtime guard enforces them.Evidence
crates/kerykeion/src/message.rs:73crates/kerykeion/src/message.rs:74No
assert/ensure/ guard precedes these lines. Rust 1.45+ saturates an out-of-rangef64 as i32(NaN→0, ±Inf→i32 extremes), so the cast never panics but the result is garbage coordinate data.Why this matters
An agent calling
MessageBuilder::positionwith a NaN or Inf from a failed GPS read silently broadcasts position(0, 0)or extreme sentinel values over the mesh, corrupting every recipient's location database. In the SIGINT/tracking context this is an undetectable data-integrity failure on outbound traffic, and the// SAFETYcomment misclassifies a missing runtime contract as a proven invariant.Desired correction
Add a finiteness + range check before the casts, e.g.
if !lat.is_finite() || !(-90.0..=90.0).contains(&lat) || !lon.is_finite() || !(-180.0..=180.0).contains(&lon) { return Err(Error::InvalidPosition { lat, lon }); }, and change the position constructors to returnResult<Self, Error>. Done when: passingf64::NANas lat returns anErrfrom the position builder rather than producing a packet.