mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-06-21 19:41:13 +00:00
c19c76481c
Enhanced the SKILL.md file to enforce conciseness rules for the state file, specifying acceptable content and file size limits. Updated the autodev state to reflect the transition to the planning phase, including changes to the current step and sub-step details. Revised acceptance criteria to clarify validation requirements and external dependencies, ensuring alignment with the latest research findings. Added a new overlay for Mode B revisions to track changes and decisions made during the assessment process.
98 lines
6.1 KiB
Markdown
98 lines
6.1 KiB
Markdown
# Security Tests
|
||
|
||
These tests cover the security-relevant AC and the Mode B revisions that introduced explicit security gates: D-CROSS-CVE-1 (OpenCV CVE pin), D-C8-9 (MAVLink 2.0 message signing), AC-NEW-7 (cache poisoning), and RESTRICT-SAT-1 / AC-8.1 (no in-flight Service calls).
|
||
|
||
### NFT-SEC-01: Cache-poisoning safety budget
|
||
|
||
**Summary**: Validates AC-NEW-7 — across all onboard tiles written, `P(geo-misalign > 30 m) < 1%` and `P(> 100 m) < 0.1%`. Multi-flight statistics constrained — PARTIAL with current single-flight fixture (see traceability matrix).
|
||
**Traces to**: AC-NEW-7, Mode B Fact #105 (Service voting layer external dependency), D-PROJ-2
|
||
|
||
**Steps**:
|
||
|
||
| Step | Consumer Action | Expected Response |
|
||
|------|----------------|------------------|
|
||
| 1 | Run 3 trial flights against `derkachi-fixture` with synthetic over-confidence injection (deflate covariance ×1.5, ×2, ×3) | Each flight produces mid-flight tiles uploaded to `mock-suite-sat-service` |
|
||
| 2 | After each flight, the mock service records each received tile's quality metadata + onboard-asserted geo-alignment vs the GT-derived geo-alignment | Per-tile mis-alignment captured |
|
||
| 3 | Across all uploaded tiles, compute `P(misalign > 30 m)` and `P(misalign > 100 m)` | Statistic computed |
|
||
| 4 | Independently observe Suite Sat Service voting-layer behavior (mock) — verify mock-side gate refuses `trusted basemap` promotion when ingest votes don't agree | Voting contract assertion (per D-PROJ-2) |
|
||
|
||
**Pass criteria** (PARTIAL):
|
||
- `P(misalign > 30 m) < 1%`, `P(misalign > 100 m) < 0.1%` across the available trial flights.
|
||
- PARTIAL annotation: AC text expects ≥100 flights — escalates D-PROJ-3 fixture acquisition + D-PROJ-2 contract verification.
|
||
|
||
---
|
||
|
||
### NFT-SEC-02: No in-flight Service calls (network egress isolation)
|
||
|
||
**Summary**: Validates RESTRICT-SAT-1 / AC-8.1 — the SUT MUST NOT reach an external satellite provider during a flight. All cache reads come from the local cache.
|
||
**Traces to**: RESTRICT-SAT-1, AC-8.1
|
||
|
||
**Steps**:
|
||
|
||
| Step | Consumer Action | Expected Response |
|
||
|------|----------------|------------------|
|
||
| 1 | Start the SUT with `e2e-net` configured `internal: true` (no external connectivity at the network layer) | SUT comes up; tile cache reads succeed |
|
||
| 2 | Run 5 min of Derkachi replay | All tile lookups served from local cache |
|
||
| 3 | Read SUT egress counter (Docker network stats) | 0 packets out to non-`e2e-net` destinations |
|
||
| 4 | Inspect SUT log for any "external Service call attempted" event | 0 events (proving the SUT didn't even try) |
|
||
| 5 | Defense-in-depth: temporarily flip `internal: false` AND blackhole DNS, re-run | Same — 0 egress attempts; no failed-DNS errors |
|
||
|
||
**Pass criteria**: 0 packets to non-`e2e-net` destinations; no "Service call attempted" log entry.
|
||
|
||
---
|
||
|
||
### NFT-SEC-03: MAVLink 2.0 message signing on AP wired channel
|
||
|
||
**Summary**: Validates D-C8-9 — AP-side rejects unsigned MAVLink GPS_INPUT messages on the signed channel; SUT-emitted (signed) messages pass; SBOM dump confirms passkey configuration.
|
||
**Traces to**: D-C8-9 (Plan-phase decision), Mode B Fact #109 (CVE-2026-1579 mitigation)
|
||
|
||
**Steps**:
|
||
|
||
| Step | Consumer Action | Expected Response |
|
||
|------|----------------|------------------|
|
||
| 1 | Start `ardupilot-plane-sitl` with signing enabled and the test passkey loaded | Signing enabled |
|
||
| 2 | Inject an UNSIGNED `GPS_INPUT` from `mavproxy-listener` (i.e. a non-SUT origin) | AP rejects the message; rejection logged in AP STATUSTEXT |
|
||
| 3 | Inject a SIGNED `GPS_INPUT` with the SUT's signing key | AP accepts |
|
||
| 4 | Inject a SIGNED `GPS_INPUT` with a DIFFERENT key | AP rejects |
|
||
| 5 | Run the SUT's SBOM-dump CI step | SBOM declares the MAVLink signing module + passkey configuration entry present |
|
||
|
||
**Pass criteria**: AP rejection of unsigned + wrong-key; AP acceptance of correct-signed; SBOM declares signing.
|
||
|
||
**Note**: iNav-side is NOT subject to this test — Mode B Fact #109 documents the asymmetry as accepted residual risk (no MAVLink signing in iNav firmware per Source #129).
|
||
|
||
---
|
||
|
||
### NFT-SEC-04: OpenCV CVE-2025-53644 mitigation (≥4.12.0 pin)
|
||
|
||
**Summary**: Validates D-CROSS-CVE-1 — the pinned OpenCV ≥4.12.0 either decodes the CVE-2025-53644 PoC JPEG safely or rejects it; no crash, no buffer overflow.
|
||
**Traces to**: D-CROSS-CVE-1, Mode B Fact #112
|
||
|
||
**Steps**:
|
||
|
||
| Step | Consumer Action | Expected Response |
|
||
|------|----------------|------------------|
|
||
| 1 | Build the SUT image with AddressSanitizer (ASan) instrumentation enabled (separate CI build) | Instrumented binary |
|
||
| 2 | Push `cve-jpeg-fixture` to every code path that uses OpenCV imread/imdecode: nav-camera frame source (C1), satellite tile thumbnail re-load (C4), tile cache import (C6) | Each path either decodes cleanly OR returns a graceful error |
|
||
| 3 | Observe ASan output | 0 buffer-overflow / use-after-free / uninitialized-read reports |
|
||
| 4 | Observe SUT process exit code | Process does NOT crash; if rejection path taken, exit code is 0 + error logged |
|
||
| 5 | CI step: lint the lockfile / pyproject.toml / requirements.txt for the OpenCV version pin | Pin asserts `opencv-python >= 4.12.0` (or platform-equivalent) |
|
||
|
||
**Pass criteria**: ASan clean; no crash; pinned version ≥ 4.12.0 in dependency manifest.
|
||
|
||
---
|
||
|
||
### NFT-SEC-05: Egress-blocked + DNS-blackholed defense-in-depth
|
||
|
||
**Summary**: Defense-in-depth complement to NFT-SEC-02 — verifies that even if the network policy were misconfigured, the SUT does not call out to public DNS / known satellite-provider hosts.
|
||
**Traces to**: RESTRICT-SAT-1 (defense-in-depth)
|
||
|
||
**Steps**:
|
||
|
||
| Step | Consumer Action | Expected Response |
|
||
|------|----------------|------------------|
|
||
| 1 | Configure SUT container with iptables OUTPUT DROP except `e2e-net` AND DNS blackholed via `--dns 0.0.0.0` | SUT comes up |
|
||
| 2 | Run Derkachi replay | All operations succeed; 0 outbound DNS queries (verified via tcpdump on egress) |
|
||
| 3 | Inspect SUT for hardcoded provider hostnames (e.g. `*.googleapis.com`, `*.maxar.com`, `*.mapbox.com`, `*.azaion.com` for the runtime path) | grep finds zero references in compiled binary's strings table for runtime-path code |
|
||
|
||
**Pass criteria**: 0 DNS queries during replay; 0 provider hostname references in runtime path.
|