- Enhanced `.env.example` with detailed CMake build flags and replay-mode strategy flags for development and CI environments. - Updated `.gitignore` to include a new deploy rollback bookmark. - Revised `_docs/_autodev_state.md` to reflect the current task status and steps. - Added new lessons to `_docs/LESSONS.md` regarding testing and architectural improvements. - Documented changes in `_docs/02_document/deployment/ci_cd_pipeline.md` to reflect the relaxed OpenCV version pin. - Updated test data documentation in `_docs/02_document/tests/test-data.md` to clarify fixture usage and paths. This commit continues the cycle-1 documentation sync and addresses various configuration updates for improved clarity and functionality.
6.4 KiB
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.11.0.86,<4.12 (cycle-1 relaxation per _docs/_process_leftovers/2026-05-11_d_cross_cve_1_opencv_pin_deferred.md; original target was >=4.12.0 and will replay once gtsam ships numpy-2 wheels) |
Pass criteria: ASan clean; no crash; pinned version satisfies the cycle-1 floor opencv-python>=4.11.0.86,<4.12 (D-CROSS-CVE-1 follow-up open). The leftover-replay condition lifts the floor back to >=4.12.0 once upstream constraints clear.
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.