Files
gps-denied-onboard/_docs/02_document/tests/security-tests.md
T
Oleksandr Bezdieniezhnykh bf13549b32
ci/woodpecker/push/02-build-push Pipeline failed
[autodev] Update configuration and documentation for cycle-1
- 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.
2026-05-20 08:05:35 +03:00

98 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.