[autodev] archive batch 87 tasks, advance to batch 88

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-05-17 17:33:43 +03:00
parent c56d4584e6
commit d1e30f818f
5 changed files with 4 additions and 4 deletions
@@ -0,0 +1,66 @@
# NFT-SEC-01 — Cache-poisoning safety probability budget
**Task**: AZ-436_nft_sec_01_cache_poisoning
**Name**: P(false-trust) ≤ 1e-6 per flight via per-tile signing + voting (AC-NEW-9 / Mode B Fact #103)
**Description**: Implement NFT-SEC-01 — synthetic flights with crafted poisoned tiles (≤5 % poison ratio); SUT MUST reject or downgrade them via signing-cert mismatch + Service voting + freshness gate; aggregate `false_trust_count_per_flight ≤ 1e-6 × flight_count`.
**Complexity**: 5 points
**Dependencies**: AZ-406, AZ-407
**Component**: Blackbox Tests / Security (epic AZ-262)
**Tracker**: AZ-436
**Epic**: AZ-262 (E-BBT)
## Problem
Cache-poisoning is the highest-impact security risk for the SUT — a single false-trust event yields a silent location drift attacker can use to compromise the mission. AC-NEW-9 / Mode B Fact #103 set a 1e-6 per-flight budget; only large-N synthetic-flight runs can validate this with statistical confidence.
## Outcome
- pytest scenario at `e2e/tests/security/test_nft_sec_01_cache_poisoning.py`. Tier-1 OR Tier-2.
- N synthetic flights (default N=1e4 — i.e. 10000 micro-replays of 60 s each; configurable for shorter CI runs); each flight's tile cache contains a small fraction (≤5 %) of crafted poisoned tiles (signing-cert mismatch, freshness violation, voting-disagreement).
- For each flight: count `false_trust_events` (a frame where SUT emits `satellite_anchored` from a poisoned tile).
- Aggregate: `total_false_trust_events ≤ N × 1e-6` (with statistical margin documented in the evidence).
## Scope
### Included
- Crafted-poisoned-tile generator (signing-cert variation, freshness variation, content variation per Mode B Fact #103).
- N synthetic flights via runner orchestration.
- Aggregate counting + margin statistics.
### Excluded
- Stale-tile rejection on the freshness axis alone — owned by FT-N-05 (AZ-427).
## Acceptance Criteria
**AC-1: N flights complete**
Given the test runs at default N=10000 OR the runner-configured N
Then all N synthetic flights complete (no early-return on partial failures).
**AC-2: poisoned-tile production**
Given the crafted-tile generator
Then the per-flight cache contains poisoned tiles in [1 %, 5 %] of all tiles, with at least one tile per defense layer (signing-cert mismatch, freshness violation, voting disagreement).
**AC-3: false-trust budget**
Given the aggregate over N flights
Then `total_false_trust_events ≤ N × 1e-6` (e.g. ≤0.01 events at N=10000 = the test passes if the count is 0).
**AC-4: parameterization**
Given conftest parameterization
Then the scenario runs per `(fc_adapter, vio_strategy)`. Note: N=10000 × 4 parameterizations is very expensive; the default per-CI run uses N=1000 + a single parameterization, and full N=10000 is gated behind a `release-gate` env flag.
## System Under Test Boundary
End-to-end through public boundaries.
- **Allowed**: tile-cache mount with crafted poisoned tiles, outbound `source_label` capture, FDR signing-rejection events.
- **Forbidden**: monkeypatching the signing-verification logic.
## Constraints
- Probability budget is statistical — at N=1000 the budget is 1e-3 expected events; the test passes only if 0 events are observed (per stricter zero-tolerance default).
- Crafted-tile generator's signing-cert path uses a deliberately-not-trusted CA; freshness path uses age-injected tiles; content path uses a tile whose embedded source-of-truth disagrees with neighboring votes.
## Document Dependencies
- `_docs/02_document/tests/security-tests.md` § NFT-SEC-01
- `_docs/02_document/tests/test-data.md` § Security
@@ -0,0 +1,66 @@
# NFT-SEC-02 + NFT-SEC-05 — No-egress contract + DNS blackhole defense-in-depth
**Task**: AZ-437_nft_sec_02_05_no_egress
**Name**: Combined no-network-egress + DNS-blackhole defense-in-depth (AC-NEW-10 / Mode B accepted residual risk #1)
**Description**: Implement NFT-SEC-02 (Docker network `internal: true` blocks all egress; no DNS lookup; no outbound TCP/UDP/ICMP) and NFT-SEC-05 (DNS blackhole defense-in-depth: even if `internal: true` is misconfigured, no DNS-based exfiltration). Both share the egress-counter observation pattern.
**Complexity**: 3 points
**Dependencies**: AZ-406, AZ-407
**Component**: Blackbox Tests / Security (epic AZ-262)
**Tracker**: AZ-437
**Epic**: AZ-262 (E-BBT)
## Problem
The "no network egress" guarantee is the project's data-residency cornerstone. NFT-SEC-02 verifies the Docker `internal: true` net behavior; NFT-SEC-05 verifies the defense-in-depth (DNS-blackhole sidecar) so that a single misconfiguration cannot create an exfiltration path.
## Outcome
- pytest scenarios at `e2e/tests/security/test_nft_sec_02_no_egress.py` and `test_nft_sec_05_dns_blackhole.py`.
- NFT-SEC-02: 5 min Derkachi replay; Docker network stats counter; assert `non_e2e_net_egress_packets == 0`.
- NFT-SEC-05: same replay; verify DNS blackhole sidecar is healthy; force a DNS resolution attempt from the SUT (via runner-issued `nslookup` invocation through SUT exec — done as a probe); assert resolution fails AND no UDP packet leaves the host even with a hypothetical net misconfiguration.
## Scope
### Included
- Docker network egress counter read.
- DNS-resolution probe + UDP egress observation.
### Excluded
- The cache-poisoning budget — owned by NFT-SEC-01.
- MAVLink signing-rejection — owned by NFT-SEC-03.
## Acceptance Criteria
**AC-1: NFT-SEC-02 — egress counter**
Given a 5 min Derkachi replay against `e2e-net.internal: true`
Then `docker network inspect e2e-net` shows zero packets to non-`e2e-net` destinations from the SUT container's interface.
**AC-2: NFT-SEC-05 — DNS-blackhole health**
Given the DNS-blackhole sidecar configured per `environment.md`
When the test pings the sidecar's health endpoint via the e2e network
Then a 200/healthy response is received.
**AC-3: NFT-SEC-05 — DNS resolution fails**
Given the SUT container executes a runner-issued `nslookup example.com`
Then the lookup fails (NXDOMAIN, timeout, or "no servers can be reached") AND the host's outbound interface counter shows no incremented UDP-53 packets during the probe.
**AC-4: parameterization**
Given conftest parameterization
Then both methods run per `(fc_adapter, vio_strategy)`.
## System Under Test Boundary
End-to-end through public boundaries.
- **Allowed**: Docker network stats (public Docker API), host-level interface counter (a public OS artifact), runner-issued exec into SUT container for the nslookup probe (this is a security probe, not a SUT modification).
- **Forbidden**: importing SUT internals to detect outbound calls.
## Constraints
- The nslookup probe MUST execute inside the SUT container's network namespace (via `docker exec`); execution from the runner host doesn't validate the SUT's net isolation.
## Document Dependencies
- `_docs/02_document/tests/security-tests.md` § NFT-SEC-02, § NFT-SEC-05
- `_docs/02_document/tests/test-data.md` § Security
- `_docs/02_document/tests/environment.md` § DNS blackhole sidecar
@@ -0,0 +1,72 @@
# NFT-SEC-03 — MAVLink 2.0 signing rejection
**Task**: AZ-438_nft_sec_03_mavlink_signing
**Name**: AP rejects unsigned / wrong-key / replayed messages (AC-NEW-11 / D-C8-9)
**Description**: Implement NFT-SEC-03 — Tier-1 OR Tier-2; AP-only; runner sends each of (a) unsigned `GPS_INPUT`, (b) signed-with-wrong-key, (c) replayed-from-tlog; AP SITL rejects each via `BAD_SIGNATURE` STATUSTEXT.
**Complexity**: 3 points
**Dependencies**: AZ-406, AZ-407 (mavlink-passkey)
**Component**: Blackbox Tests / Security (epic AZ-262)
**Tracker**: AZ-438
**Epic**: AZ-262 (E-BBT)
## Problem
The MAVLink 2.0 signing handshake (D-C8-9) only protects the channel if AP correctly rejects un-signed / wrong-key / replayed messages. NFT-SEC-03 directly probes those rejection paths.
## Outcome
- pytest scenario at `e2e/tests/security/test_nft_sec_03_mavlink_signing.py`. AP-only.
- Three sub-cases (sent in order; pause between each):
- (a) Runner crafts and sends an unsigned `GPS_INPUT` to AP SITL.
- (b) Runner crafts and sends a `GPS_INPUT` signed with a wrong-key passkey.
- (c) Runner replays a captured signed `GPS_INPUT` from a prior `.tlog` (counter-replay attack).
- For each: assert AP emits `BAD_SIGNATURE` STATUSTEXT within ≤500 ms; AP's GPS state does NOT update from these messages.
## Scope
### Included
- All three sub-cases.
- mavproxy STATUSTEXT capture for `BAD_SIGNATURE`.
- AP GPS state read for the no-update assertion.
### Excluded
- iNav variant — N/A; iNav has no MSP signing.
- Signing handshake setup — owned by FT-P-09-AP (AZ-416).
## Acceptance Criteria
**AC-1: tier guard**
Given `fc_adapter == inav`
Then the test SKIPs.
**AC-2: unsigned rejection**
Given the runner sends an unsigned `GPS_INPUT`
Then AP emits `BAD_SIGNATURE` (or equivalent rejection STATUSTEXT) within ≤500 ms; AP's `GLOBAL_POSITION_INT` does NOT update.
**AC-3: wrong-key rejection**
Given the runner sends a `GPS_INPUT` signed with a wrong-key passkey
Then same as AC-2.
**AC-4: replayed-message rejection**
Given the runner replays a captured signed `GPS_INPUT` from a prior `.tlog`
Then same as AC-2 (signing's monotonic counter prevents replay acceptance).
**AC-5: vio_strategy parameterization**
Given conftest parameterization
Then the scenario runs once per `vio_strategy` (the SUT's VIO is irrelevant here — runner is the sender).
## System Under Test Boundary
The "SUT" here is the AP's signing-acceptance behavior. The probe is at the AP boundary.
- **Allowed**: runner-crafted MAVLink messages (a public protocol surface).
- **Forbidden**: monkeypatching AP's signing logic.
## Constraints
- The `BAD_SIGNATURE` STATUSTEXT regex matches the AP-emitted text (e.g. "MAVLink: BAD_SIGNATURE" or equivalent — the exact string is canonical to AP and recorded in the test fixture).
## Document Dependencies
- `_docs/02_document/tests/security-tests.md` § NFT-SEC-03
- `_docs/02_document/tests/test-data.md` § Security (NFT-SEC-03 row)
@@ -0,0 +1,63 @@
# NFT-SEC-04 — OpenCV CVE-2025-53644 + AddressSanitizer fuzz
**Task**: AZ-439_nft_sec_04_opencv_cve
**Name**: Crafted JPEG (CVE-2025-53644) does NOT crash; ≥4 h ASan fuzz no findings (RESTRICT-CVE-1)
**Description**: Implement NFT-SEC-04 — Tier-1 OR Tier-2; (a) feed `cve-jpeg-fixture` to nav-camera input and assert no crash + graceful error; (b) run an AddressSanitizer-instrumented build under fuzz inputs for ≥4 h with no ASan findings.
**Complexity**: 5 points
**Dependencies**: AZ-406, AZ-407 (cve-jpeg-fixture), AZ-444 (optional Tier-2)
**Component**: Blackbox Tests / Security (epic AZ-262)
**Tracker**: AZ-439
**Epic**: AZ-262 (E-BBT)
## Problem
The pinned OpenCV version (≥4.12) must be CVE-immune to the documented vulnerability (RESTRICT-CVE-1). Without a probe + fuzz validation, regressions on a future OpenCV bump could silently reintroduce a security defect.
## Outcome
- pytest scenarios at `e2e/tests/security/test_nft_sec_04_opencv_cve.py` (probe) and `test_nft_sec_04_asan_fuzz.py` (long-running fuzz, gated behind release-gate flag).
- Probe (always run): push `cve-jpeg-fixture` as a single nav-camera frame; assert no crash; assert SUT either decodes it or returns a graceful error event in FDR.
- Fuzz (release-gate): run `build_kind=ASan` SUT image with a randomized JPEG-fuzz harness for ≥4 h; assert 0 ASan findings.
## Scope
### Included
- CVE-probe sub-test (always run).
- ASan-fuzz sub-test (release-gate, gated by `RELEASE_GATE=true` env flag).
### Excluded
- General fuzzing of non-image inputs — out of scope.
## Acceptance Criteria
**AC-1: CVE probe — no crash**
Given the SUT is fed `cve-2025-53644.jpg` as a nav-camera frame
Then the SUT does NOT crash; the SUT process remains alive after the frame; the FDR contains either a decode-success record OR a `frame-decode-error` record (graceful error).
**AC-2: ASan fuzz no findings**
Given the `build_kind=ASan` SUT image is running fuzz inputs for ≥4 h
Then 0 ASan findings (heap-buffer-overflow, use-after-free, etc.) appear in the captured stderr / ASan log.
**AC-3: ASan fuzz coverage**
Given the 4 h fuzz run
Then the fuzz harness reaches ≥1000 unique JPEG corpus inputs (a coverage proxy via `--corpus-info` or equivalent) — informational only; no hard threshold.
**AC-4: parameterization**
Given conftest parameterization
Then the probe runs per `(fc_adapter, vio_strategy)`; the fuzz runs once per `vio_strategy` (fc_adapter is irrelevant for image-decode).
## System Under Test Boundary
End-to-end through public boundaries; the ASan fuzz uses the SUT's own image-decode path (no direct OpenCV calls from the harness).
- **Allowed**: nav-camera frame push (a public input), ASan log capture, FDR archive read.
- **Forbidden**: directly testing `cv2.imdecode` outside the SUT.
## Constraints
- Fuzz duration is ≥4 h per RESTRICT-CVE-1; default CI run uses the probe only (~30 s) and gates the fuzz behind `RELEASE_GATE=true`.
## Document Dependencies
- `_docs/02_document/tests/security-tests.md` § NFT-SEC-04
- `_docs/02_document/tests/test-data.md` § Security (NFT-SEC-04 row)