Files
satellite-provider/_docs/05_security/infrastructure_review_cycle8.md
T
Oleksandr Bezdieniezhnykh ac40a8b352 [AZ-808] [AZ-809] [AZ-810] [AZ-811] [AZ-812] Cycle 8 security audit
PASS_WITH_WARNINGS. Zero Critical / High.

New cycle-8 findings:
- F-AZ809-1 (Medium / A04 Insecure Design): unbounded
  geofences.polygons enables an authenticated DoS on
  POST /api/satellite/route. Cap candidate: 50 or 500.
- F-AZ810-1 (Low / A09): JsonException.Message echoed in
  UavUploadValidationFilter (new instance of cycle-7 F-AZ795-1
  pattern in a second code path).
- F-AZ810-2 (Low / Informational): UavTileMetadata.CapturedAt
  typed DateTime not DateTimeOffset; freshness window drifts in
  non-UTC dev environments. Zero impact in UTC-deployed prod.

Carry-overs (cycle 7): F-AZ795-1, F-AZ795-2, D-AZ795-1 still
open. Cycle 4 D2-cy4 still open (test-runtime Medium).

Cycle-8 architectural wins recorded: per-endpoint validation
reached 100% coverage; three approved validation paths
formalised; OSM wire-format normalisation under strict mode
(AZ-812); UAV-handler defence-in-depth retained.

Highest-priority cycle-9 follow-up: F-AZ809-1 polygon cap.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-23 15:17:31 +03:00

71 lines
6.2 KiB
Markdown

# Infrastructure & Configuration Review (Cycle 8)
**Date**: 2026-05-23
**Mode**: Delta scan
**Scope**: Cycle-8 changes to deployment configs, CI/CD files, environment templates, and shell scripts only.
## Cycle-8 Infrastructure-Layer Diff
Computed via `git diff --name-only 865dfdb..b763da3` (cycle-7 tip → cycle-8 tip), filtered to infrastructure-relevant paths:
| File | Diff summary | Security relevance |
|------|--------------|--------------------|
| `Dockerfile`, `Dockerfile.tests`, `Dockerfile.api` (and any image-build file) | **NOT modified** | None — cycle 8 did not touch any image build. |
| `docker-compose.yml`, `docker-compose.tests.yml`, `docker-compose.prod.yml` (and any orchestration file) | **NOT modified** | None — cycle 8 did not touch any compose file. |
| `.woodpecker.yml`, `.github/workflows/**` (and any CI/CD pipeline definition) | **NOT modified** | None — cycle 8 added no automated pipeline changes. |
| `.env`, `.env.example`, `.env.tests` (and any environment template) | **NOT modified** | None — cycle 8 read no new env vars (every cycle-8 validator and filter is pure code; FluentValidation 12.0.0 has no config knobs). |
| `appsettings.json`, `appsettings.Development.json`, `appsettings.tests.json` | **NOT modified** | None — cycle 8 added no new configuration sections. The pre-existing `UavQualityConfig` section is unchanged. |
| `scripts/probe_latlon_validation.sh` | NEW manual probe script for AZ-811 | Reviewed in `static_analysis_cycle8.md` § Test Code Review § `scripts/probe_*_validation.sh`. ✓ |
| `scripts/probe_region_validation.sh` | NEW manual probe script for AZ-808 | Reviewed in `static_analysis_cycle8.md` § Test Code Review § `scripts/probe_*_validation.sh`. ✓ |
| `scripts/probe_route_validation.sh` | NEW manual probe script for AZ-809 | Reviewed in `static_analysis_cycle8.md` § Test Code Review § `scripts/probe_*_validation.sh`. ✓ |
| `scripts/probe_upload_validation.sh` | NEW manual probe script for AZ-810 | Reviewed in `static_analysis_cycle8.md` § Test Code Review § `scripts/probe_*_validation.sh`. ✓ |
| `scripts/run-performance-tests.sh` | Modified — diff is exclusively the AZ-812 wire-format rename (`?Latitude=…&Longitude=…&ZoomLevel=…``?lat=…&lon=…&zoom=…` across query strings, and `{"latitude":…,"longitude":…}``{"lat":…,"lon":…}` across JSON bodies in PT-01 through PT-08 invocations) | No new credentials, no new shell-injection surface. The change is a forced wire-update made necessary by AZ-812's contract rename. ✓ |
| `.vscode/launch.json`, `.vscode/tasks.json`, `README.md` | Modified — developer-tooling artifacts | Out of scope for security audit (not deployed; do not affect runtime). |
## Probe Shell Scripts — Common Safety Posture
All four new `probe_*_validation.sh` scripts follow the same defensive pattern (verified per `static_analysis_cycle8.md`):
- `#!/usr/bin/env bash` with `set -euo pipefail` at the top — fail-fast on undefined vars, broken pipes, command failures.
- `API_URL="${API_URL:-https://localhost:8080}"` default; `JWT="${JWT:-}"` with an explicit `if [[ -z "${JWT}" ]]; then echo "ERROR: set JWT env var to a bearer token. …"; exit 2; fi` guard.
- `curl -k` used (justified — the dev cert is self-signed; the scripts target localhost in dev/test only — documented in each script's header).
- Hand-built JSON payloads via shell variable interpolation — values are integer / quoted strings only, no caller-supplied shell strings.
- No embedded secrets, no hardcoded `$JWT`, no `.env` reads.
Identical posture to the cycle-7 `probe_inventory_validation.sh`. ✓
## Container & Image Security — Carried Forward Unchanged
| Check | Status (carried from cycle 5/6/7) | Cycle-8 impact |
|-------|-----------------------------------|----------------|
| Non-root container user (Dockerfile `USER` directive) | Already in effect | None — no Dockerfile change. |
| Minimal base image (alpine/distroless/etc.) | The API image uses the .NET 10 SDK base — same as cycle 7; image hardening is still owned by a separate, unscheduled follow-up task. | None. |
| No secrets in build args | Verified cycle 5; no `Dockerfile` change in cycle 7 or 8 | None. |
| Health checks | Compose `healthcheck` block on Postgres unchanged | None. |
## CI/CD Security — Carried Forward Unchanged
| Check | Status | Cycle-8 impact |
|-------|--------|----------------|
| Secrets management (env vars / vault, not pipeline literals) | Existing pattern preserved | None. |
| No credentials in pipeline definitions | `.woodpecker.yml` untouched in cycle 8 | None. |
| Artifact signing | Existing posture (none — owned by a separate operational improvement track) | None. |
| Dependency-audit step in pipeline | Existing posture (manual audit per `dependency_scan_cycle*.md`; no automated `dotnet list package --vulnerable` in CI due to the build-hang issue noted in `AGENTS.md`) | None. |
## Environment & Secrets
- `.env.example` — not modified in cycle 8. The cycle-8 code reads no new env vars.
- `appsettings.Development.json` — not modified in cycle 8.
- `appsettings.json` — production template; unchanged in cycle 8.
- The cycle-7 host-port change (`5432:5432``5433:5432`) is preserved through cycle 8; not relevant to production exposure (production containers run on a private docker network without host-port mapping per the existing deployment model).
## Cycle-7 + Earlier Carry-overs
No infrastructure-layer carry-overs from earlier cycles. The cycle-2 `UavQualityConfig`-derived `KestrelServerOptions.Limits.MaxRequestBodySize = 500 MiB` (set in `Program.cs:41-43`) is noted in `owasp_review_cycle8.md` § A05 as a configuration choice that contributed to the F-AZ809-1 exploit-math worst case, but it is not itself an infrastructure-layer finding — the value is correct for the UAV upload endpoint, and the proper fix is per-endpoint size narrowing (a code change, not an infra change).
## Verdict (Phase 4)
**PASS** — zero new infrastructure-layer findings.
The four new probe scripts are dev/test only, env-driven, fail-fast under `set -euo pipefail`, and contain no embedded credentials. The single perf-script update is a wire-rename diff with no security impact. Cycle 8 made no Docker, compose, CI, env-template, or appsettings changes.