Detect the takeover moment, not just its consequences - #28
Open
Ray-Rose wants to merge 1 commit into
Open
Conversation
Every existing lane is residual-based, so each needs the spoofer to have already moved us. `docs/threats.md` states the consequence as the velocity-aiding lane's accepted bounds: a walk-off under ~0.5 m/s sits below the free-inertial floor, and a slow enough ramp-on gets tracked by the adaptive floor. Both bounds describe the same window — a competent spoofer captures the receiver ALIGNED and only then walks off, and while it is aligned the residual is ~0. There is nothing there to see. The takeover itself is not free, though. Capturing a receiver means out-powering the live signals and handing it a SIMULATED constellation, and that is rarely a byte-perfect continuation of the real sky: the satellite count steps and the DOP steps with it — often DOWNWARD, because synthesized geometry is cleaner than anything a real sky with real obstructions produces. So this lane watches the metadata instead of the position. EWMA baselines of sat count and HDOP track the sky we have been flying under; a step away from it (>=4 sats or >=0.8 HDOP), persisting >=2 fixes, fires `ConstellationShift`. An abrupt HDOP IMPROVEMENT counts as much as a degradation. The baseline learner freezes while a deviation is in progress — the same idiom the drift lane uses on its noise floor — so it cannot chase the step and erase the signal. Two things this is NOT, both load-bearing: It is not coverage. These are fields the attacker's own signal generator produces, so an adversary who holds them steady across the handover is invisible here. What it buys is cost: a clean takeover now needs the victim's current constellation modelled well enough to fake continuity into it, not just more power. It is corroboration, and the threat model says so. It cannot sever GPS. The FSM counts an external anomaly as a detector firing, so anything that fires CONTINUOUSLY across the spoofed dwell can reach Spoofed and cut the GPS. A metadata step is corroboration on data that is, at that instant, still good — severing there would be a self-inflicted DoS. So the detector is one-shot per step: it re-baselines onto the new level the moment it reports, and a 30 s refractory bounds what an oscillating receiver (or attacker) can contribute. It raises Suspicious; a residual lane has to confirm before anything is cut. `ConstellationSwap` sim pattern added to isolate the case: metadata steps, position and velocity stay honest. The e2e test asserts all three properties — the shift is seen exactly once, the residual lanes stay silent (proving orthogonality rather than redundancy), and sever/RTL counts are zero. 10 unit tests + 2 e2e. 192 lib tests, all 15 suites green, including the 8 false-positive characterizations. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The gap
Every detector in this crate is residual-based — each needs the spoofer to have already moved us.
docs/threats.mdalready states the consequence, as the velocity-aiding lane's accepted bounds:Both bounds describe the same window. A competent spoofer captures the receiver aligned — its first spoofed fix matches truth — and only then begins to walk off. While it is aligned the residual is ~0, and the residual family isn't failing to see it: there is genuinely nothing there.
But the takeover itself is not free. Capturing a receiver means out-powering the live signals and handing it a simulated constellation, which is rarely a byte-perfect continuation of the real sky. The satellite count steps, and the DOP steps with it — frequently downward, because synthesized geometry is cleaner than anything a real sky with real obstructions produces.
The lane
src/detect/quality.rswatches the metadata instead of the position. EWMA baselines of satellite count and HDOP track "the sky we have been flying under"; a step away from it (≥4 sats or ≥0.8 HDOP) persisting ≥2 fixes firesConstellationShift.Two things it deliberately is not
It is not coverage. These are fields the attacker's own signal generator produces. An adversary who holds sat count and HDOP steady across the handover is invisible to this lane. What it buys is cost: a clean takeover now requires modelling the victim's current constellation well enough to fake continuity into it, not merely out-powering the sky. It's corroboration, and the threat-model row says exactly that. It's also blind to meaconing by construction.
It cannot sever GPS. This one is a real safety constraint, not a caveat. The FSM counts an external anomaly as "a detector fired", so anything firing continuously across the suspicious→spoofed dwell reaches Spoofed and cuts the GPS. A metadata step is corroboration on position data that is, at that instant, still perfectly good — severing there would be a self-inflicted denial of service. So the detector is one-shot per step: it re-baselines onto the new level the moment it reports, and a 30 s refractory bounds what an oscillating receiver (or a deliberately flapping attacker) can contribute toward the dwell. It raises Suspicious; a residual lane must confirm before anything is cut.
Proof
New
SpoofPattern::ConstellationSwapisolates the case — metadata steps, position and velocity stay honest.tests/scenario_constellation_shift.rsasserts all three properties at system level:ConstellationShiftPlus 10 unit tests covering steady sky, warmup, one-shot behaviour, glitch rejection, perfect-geometry detection, oscillation bounding, absent data, slow natural constellation drift, and the disable switch.
Verified
cargo fmt --check,clippy --all-targets --all-features -D warnings, 192 lib tests (182 → 192), all 15 integration suites run individually — including the 8 false-positive characterizations, which stay clean because the sim's steady 12-sat / 0.9-HDOP sky never trips the lane.🤖 Generated with Claude Code