Skip to content

Detect the takeover moment, not just its consequences - #28

Open
Ray-Rose wants to merge 1 commit into
mainfrom
feat/constellation-shift-lane
Open

Detect the takeover moment, not just its consequences#28
Ray-Rose wants to merge 1 commit into
mainfrom
feat/constellation-shift-lane

Conversation

@Ray-Rose

Copy link
Copy Markdown
Owner

The gap

Every detector in this crate is residual-based — each needs the spoofer to have already moved us. docs/threats.md already states the consequence, as the velocity-aiding lane's accepted bounds:

(1) a walk-off below ~0.5 m/s sits at/under the free-inertial velocity-bias floor — undetected; (3) a spoofer who ramps the bias on over many minutes can be tracked by the adaptive floor

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.rs watches 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 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 for its noise floor — so it can't chase the step and erase the very signal being looked for.
  • Warmup, single-fix-glitch rejection, and absent-quality handling are all explicit (a receiver that goes terse is not hostile).

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::ConstellationSwap isolates the case — metadata steps, position and velocity stay honest. tests/scenario_constellation_shift.rs asserts all three properties at system level:

Assertion Why it matters
Exactly one ConstellationShift A sustained firing is precisely what would let this lane sever GPS alone
Zero Jump/Drift events Proves orthogonality rather than redundancy — nothing else could have seen this
Zero sever / RTL The safety bound, enforced end-to-end

Plus 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

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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant