Skip to content

MessageBuilder::position builds with unvalidated lat/lon — NaN/Inf/out-of-range silently corrupts wire coordinates #247

Description

@forkwright

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions