Files
satellite-provider/_docs/05_security/owasp_review_cycle7.md
T
Oleksandr Bezdieniezhnykh bc04ba7f99 [AZ-794] [AZ-795] [AZ-796] Cycle 7 Steps 12-15 sync (test-spec / docs / security / perf)
Step 12 (Test-Spec Sync): adds BT-27 for the AZ-796 9-rule
validation surface and 12 cycle-7 AC rows + Coverage Summary
update to traceability-matrix.md.

Step 13 (Update Docs): module-layout + module docs for the new
SatelliteProvider.Api/Validators namespace + GlobalExceptionHandler
+ updated TileInventory DTO; tests_unit + tests_integration
document the new InventoryRequestValidatorTests (16 unit tests
covering all 9 rules) + TileInventoryValidationTests (16
integration tests) + ProblemDetailsAssertions support;
glossary entries for Validation Problem Details / FluentValidation
/ Unmapped Member Handling; system-flows F8 (Tile Inventory Bulk
Lookup) expanded with deserializer + validator gates and a 13-row
Validation Surface table; data_parameters § Tile Inventory
documents the v2 input schema + constraints; ripple_log_cycle7
captures the doc-side ripple decisions.

Step 14 (Security Audit): 5-phase audit ran; verdict
PASS_WITH_WARNINGS (3 Low findings — D-AZ795-1 FluentValidation
12.0.0 -> 12.1.1 recommended bump, F-AZ795-1 JsonException.Message
leak in 400 detail, F-AZ795-2 BadHttpRequestException.Message leak).
No Critical / High; auth runs before validation (confirmed in
Program.cs); two NuGet additions (FluentValidation 12.0.0 +
.DependencyInjectionExtensions 12.0.0) both CVE-clean. Per-phase
reports plus consolidated security_report_cycle7.md.

Step 15 (Performance Test): docker compose stack used for perf
run, scripts/run-performance-tests.sh exited 0 with 8/8 scenarios
PASS (second consecutive clean exit-0); added PT-09 cycle-7 smoke
probe (v2 z/x/y schema, 2500-tile all-miss batch) measuring
min=27ms median=44ms p95=73ms max=86ms (13.7x under AZ-505 AC-4
1000ms budget). PT-07/08 improvements traced to the cycle-6 TLS
handshake-overhead identification, not application-side change.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-22 11:24:27 +03:00

6.6 KiB

OWASP Top 10 Review (Cycle 7)

Date: 2026-05-22 Mode: Delta scan against OWASP Top 10:2021 (current at time of audit per https://owasp.org/www-project-top-ten/) Scope: Cycle-7 delta only — AZ-794 wire-format rename, AZ-795 strict-validation infrastructure, AZ-796 inventory-endpoint validator. Earlier cycles' OWASP reviews remain authoritative for their respective surfaces; this file does NOT re-walk the full cycle-5 surface.

A01 — Broken Access Control

Status: PASS

  • .RequireAuthorization() is preserved on every existing endpoint and is chained on the cycle-7 inventory endpoint at Program.cs:217 ahead of .WithValidation<TileInventoryRequest>() on line 218.
  • Endpoint-filter execution order is governed by ASP.NET Core's middleware → routing → endpoint-filter pipeline. UseAuthorization() (line 201) reads the endpoint metadata produced by .RequireAuthorization() and short-circuits anonymous callers with 401 BEFORE the endpoint dispatch reaches any endpoint filter. Cycle-7 verification: TileInventoryValidationTests does not include a "no token → 400" case because the framework prevents that path; the suite's TileInventoryTests.UnauthenticatedRequestReturns401_AC6 already covers it.
  • No new CORS policy in cycle 7. TilesCors (cycle-6 baseline) is unchanged.
  • No new IDOR paths — the inventory endpoint operates on caller-supplied identifiers but does not couple them to any tenant or owner field; tiles are globally-scoped in the post-AZ-484 model.

A02 — Cryptographic Failures

Status: N/A (cycle 7)

  • Cycle 7 has no cryptographic operations. JWT validation is unchanged from cycle 4 (HS256 with ≥ 32-byte secret, ValidateLifetime + ValidateIssuer + ValidateAudience = true, ClockSkew = 30s).
  • The cycle-5 UUIDv5 SHA-1 surface is unaffected.
  • TLS posture (Kestrel Http1AndHttp2 with self-signed dev cert / ingress termination in prod) — unchanged from cycle 6.

A03 — Injection

Status: PASS

  • No SQL / Dapper / Npgsql usage in any cycle-7 new file.
  • No Process.Start / shell-out / eval in any cycle-7 new file.
  • All inputs reaching the validator are strongly typed (int, Guid, IReadOnlyList<TileCoord>) — System.Text.Json has already parsed and rejected anything malformed before the validator runs.
  • The cycle-7 deserializer hardening (UnmappedMemberHandling.Disallow) raises the bar for the entire HTTP JSON surface by rejecting mass-assignment / property-injection attempts at parse time.

A04 — Insecure Design

Status: PASS (improvement)

  • AZ-795 / AZ-796 are themselves a design fix for ad-hoc validation. Pre-cycle-7, endpoints used inline try/catch blocks and per-handler defensive logic — easy to miss a path, easy to drift the shape of 4xx bodies. Cycle 7 centralises validation behind one ValidationEndpointFilter<T> + one GlobalExceptionHandler, both honouring a single contract (error-shape.md v1.0.0).
  • The architecture doc (_docs/02_document/architecture.md § 9) now carries a coverage table that names every public endpoint and its validation status — making future drift visible.

A05 — Security Misconfiguration

Status: PASS

  • UnmappedMemberHandling.Disallow is a defense-in-depth hardening (mass-assignment prevention).
  • Swagger exposure is still gated by app.Environment.IsDevelopment() (unchanged).
  • appsettings.Development.json clearly tags DEV-ONLY JWT iss/aud values; appsettings.json ships empty so production fail-fast triggers if env vars are missing (unchanged from cycle 4).
  • The new AddProblemDetails() registration is benign — it only standardises ProblemDetails generation for endpoints that explicitly return them.
  • Note: AddValidatorsFromAssemblyContaining<Program>() is scoped to SatelliteProvider.Api.dll only — it cannot pick up IValidator<T> definitions from any other assembly (deliberate; the validators MUST live in the API project where the endpoint contract lives).

A06 — Vulnerable & Outdated Components

Status: PASS_WITH_WARNINGS (Low)

  • See dependency_scan_cycle7.md for the full table. Summary:
    • FluentValidation 12.0.0 — no known CVEs; latest is 12.1.1 (hardening). Low/Hardening recommendation only.
    • FluentValidation.DependencyInjectionExtensions 12.0.0 — same.
    • All other packages unchanged from cycle 5.

A07 — Identification and Authentication Failures

Status: PASS

  • JWT validation parameters unchanged from cycle 4 (AddSatelliteJwt).
  • No new auth-bypass paths introduced by cycle 7. The new endpoint filter cannot run for anonymous callers (see A01).
  • The integration test TileInventoryValidationTests mints a valid token via the shared JwtTokenFactory — proves the happy path is properly auth-gated and not relying on any test-only bypass.

A08 — Software and Data Integrity Failures

Status: N/A (cycle 7)

  • No CI/CD changes, no artifact-signing changes, no auto-update paths touched in cycle 7.

A09 — Security Logging and Monitoring Failures

Status: PASS_WITH_WARNINGS

  • GlobalExceptionHandler 5xx branch logs Method, Path, correlationId, and the exception object (via Serilog default). This is the appropriate level — enough to debug, with correlationId for cross-referencing.
  • The 4xx branch (cycle-7 new logic) does NOT log the exception. This is intentional and correct: malformed request bodies would otherwise create a noisy log signal and could push PII / token content into the log file if attached unwisely. The cost of "no log of the 400" is acceptable because the response itself carries the field path and a deterministic error message, so the client can self-debug.
  • The Low information-disclosure findings (F-AZ795-1, F-AZ795-2) from static_analysis_cycle7.md belong here as well, but the impact is limited to a Low because the leaked content is type-name metadata, not credentials or PII.

A10 — Server-Side Request Forgery (SSRF)

Status: N/A (cycle 7)

  • No URL-input fields, no outbound HTTP calls triggered by the cycle-7 surface. (Pre-existing: GoogleMapsDownloaderV2 makes outbound calls to Google Maps; not modified by cycle 7.)

Cross-Reference with security_approach.md

The repo does not contain _docs/00_problem/security_approach.md (the pre-existing security audit cycles never produced one). The OWASP review proceeds against the cycle-5 + cycle-6 architectural decisions documented in _docs/02_document/architecture.md § 7 (Security Architecture) — which cycle-7 input-validation work cleanly extends rather than contradicts.

Verdict (Phase 3)

PASS_WITH_WARNINGS — 1 dependency-hardening Low (D-AZ795-1: 12.0.0 → 12.1.1) + 2 information-disclosure Lows (F-AZ795-1, F-AZ795-2). Zero Critical / High / Medium findings.