[AZ-1113] Cycle 10 closeout: docs, perf harness, security

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-06-26 10:55:59 +03:00
parent 01d7e7d584
commit c79998bfa7
24 changed files with 600 additions and 46 deletions
@@ -0,0 +1,35 @@
# Dependency Scan (Cycle 10)
**Date**: 2026-06-25
**Mode**: Delta scan
**Scope**: Cycle-10 delta over cycle-9 (`dependency_scan_cycle9.md`). Surface = AZ-1113 (REST 400 error sanitization — no package manifest changes).
**Method**: `dotnet list SatelliteProvider.sln package --vulnerable --include-transitive`.
## Cycle-10 Package Manifest Diff
| csproj | Cycle 9 baseline | Cycle 10 change |
|--------|------------------|-----------------|
| All csproj | unchanged | **+0** packages added or bumped |
## Vulnerable Package Scan (2026-06-25)
| Project | Finding | Severity | Notes |
|---------|---------|----------|-------|
| `SatelliteProvider.Api` | none | — | Production runtime — clean |
| `SatelliteProvider.IntegrationTests` | transitive `Microsoft.IdentityModel.JsonWebTokens` 7.0.3, `System.IdentityModel.Tokens.Jwt` 7.0.3 | Moderate | GHSA-59j7-ghrg-fj52 — **test-runtime only** (pre-existing; unchanged) |
| `SatelliteProvider.TestSupport` | `System.IdentityModel.Tokens.Jwt` 7.0.3 + transitive JsonWebTokens 7.0.3 | Moderate | test-runtime only — pre-existing |
## Cycle-10 Findings
**No new dependency CVEs.** AZ-1113 is a code-only change (static error strings); no NuGet manifest edits.
## Carry-overs
- **D-AZ795-1** (Low): FluentValidation 12.0.0 → 12.1.1 — still open (explicitly out of AZ-1113 scope)
- **D2-cy4** (Medium, test-runtime): `Microsoft.NET.Test.Sdk` transitive — still open
## Verdict
**PASS** (cycle-10 delta) — zero new CVEs.
Cumulative: **PASS_WITH_WARNINGS** — D2-cy4 + D-AZ795-1 carry-overs unchanged.
@@ -0,0 +1,13 @@
# Infrastructure & Configuration Review (Cycle 10)
**Date**: 2026-06-25
**Mode**: Delta scan
**Scope**: Cycle-10 infrastructure changes only.
| File | Change | Security relevance |
|------|--------|-------------------|
| All Docker / compose / CI / appsettings | **unchanged** | AZ-1113 is application-code only |
## Verdict
**PASS** (cycle-10 delta) — no infrastructure surface change.
+30
View File
@@ -0,0 +1,30 @@
# OWASP Top 10 Review (Cycle 10)
**Date**: 2026-06-25
**Framework**: OWASP Top 10:2021
**Mode**: Delta review — AZ-1113 over cycle-9 baseline (`owasp_review_cycle9.md`).
| Category | Cycle-9 status | Cycle-10 delta |
|----------|----------------|----------------|
| A01 — Broken Access Control | PASS | No change |
| A02 — Cryptographic Failures | PASS | No change |
| A03 — Injection | PASS | No change |
| A04 — Insecure Design | PASS | No change |
| A05 — Security Misconfiguration | PASS | No change |
| A06 — Vulnerable Components | PASS_WITH_WARNINGS | No new packages; D-AZ795-1 + D2-cy4 carry-overs unchanged |
| A07 — Auth Failures | PASS | No change |
| A08 — Data Integrity Failures | PASS | No change |
| A09 — Logging / Monitoring Failures | PASS_WITH_WARNINGS → **improved** | F-AZ795-1, F-AZ795-2, F-AZ810-1 **resolved**; F-AZ810-2 still open (informational) |
| A10 — SSRF | N/A | No URL-fetch changes |
## A09 detail
AZ-1113 closes the REST client-visible exception echo paths identified in cycles 78. Server-side logging of full exceptions is preserved (existing patterns). `error-shape.md` v1.0.1 documents the static strings for consumer reference.
**Remaining A09 item**: F-AZ810-2 (`DateTime` vs `DateTimeOffset` on `capturedAt`) — time-handling correctness, not information disclosure.
## Verdict
**PASS** (cycle-10 delta on A09 information-disclosure items).
Cumulative: **PASS_WITH_WARNINGS** — F-AZ810-2 + dependency carry-overs only.
@@ -0,0 +1,53 @@
# Security Audit Report (Cycle 10)
**Date**: 2026-06-25
**Scope**: Cycle-10 delta — AZ-1113 (REST 400 error message sanitization).
**Trigger**: `/autodev` Step 14 — user chose **A) Run security audit**.
**Verdict (cycle-10 delta)**: **PASS** — 3 REST information-disclosure carry-overs resolved; 0 new Critical/High/Medium.
**Verdict (cumulative)**: **PASS_WITH_WARNINGS** — F-AZ810-2, D-AZ795-1, D2-cy4 remain open.
## Summary
| Severity | Cycle 10 at audit | Cumulative open |
|----------|-------------------|-----------------|
| Critical | 0 | 0 |
| High | 0 | 0 |
| Medium | 0 | 1 (D2-cy4 test-runtime) |
| Low | 0 new | 2 (F-AZ810-2, D-AZ795-1) |
## OWASP Top 10:2021 (cycle-10 delta)
See `owasp_review_cycle10.md` — A09 improved; all other categories unchanged PASS/N/A.
## Findings
| # | Severity | Category | Location | Title | Status |
|---|----------|----------|----------|-------|--------|
| F-AZ795-1 | Low | Information Disclosure (A09) | `GlobalExceptionHandler` | `JsonException.Message` in 400 `errors[]` | **RESOLVED** (AZ-1113) |
| F-AZ795-2 | Low | Information Disclosure (A09) | `GlobalExceptionHandler` | `BadHttpRequestException.Message` in `detail` | **RESOLVED** (AZ-1113) |
| F-AZ810-1 | Low | Information Disclosure (A09) | `UavUploadValidationFilter` + `UavTileUploadHandler` | Metadata parse `ex.Message` echo | **RESOLVED** (AZ-1113) |
## Carry-overs (still open)
- **F-AZ810-2** — `DateTime` vs `DateTimeOffset` on `UavTileMetadata.CapturedAt` (Low / informational)
- **D-AZ795-1** — FluentValidation 12.0.0 → 12.1.1
- **D2-cy4** — test SDK transitive JWT advisory (Moderate, test-runtime only)
## Recommendations
### Immediate
- None blocking cycle 10 ship.
### Short-term
- F-AZ810-2: add `DateTimeKind.Unspecified` rejection or migrate to `DateTimeOffset` (separate task).
- D-AZ795-1: bump FluentValidation when a coordinated package bump task lands.
### Long-term
- D2-cy4: pin JWT test packages when upstream resolves GHSA-59j7-ghrg-fj52 for 7.0.3 line.
## Artifacts
- `dependency_scan_cycle10.md`
- `static_analysis_cycle10.md`
- `owasp_review_cycle10.md`
- `infrastructure_review_cycle10.md`
@@ -0,0 +1,57 @@
# Static Analysis (Cycle 10)
**Date**: 2026-06-25
**Mode**: Delta scan
**Scope**: AZ-1113 REST 400 error message sanitization. Cycle-9 baseline remains authoritative for gRPC surface.
**Files in scope**:
- `SatelliteProvider.Api/GlobalExceptionHandler.cs`
- `SatelliteProvider.Api/Validators/UavUploadValidationFilter.cs`
- `SatelliteProvider.Services.TileDownloader/UavTileUploadHandler.cs`
- `SatelliteProvider.Tests/GlobalExceptionHandlerTests.cs`
- `SatelliteProvider.Tests/UavTileUploadHandlerTests.cs`
- `SatelliteProvider.IntegrationTests/UavUploadValidationTests.cs` (+ tightened assertions in region/route/inventory validation tests)
**Method**: Read changed call sites; verify static constants replace `ex.Message` / `badRequest.Message` echoes; grep for remaining raw exception text in client-facing 400 paths.
## Resolved findings (AZ-1113)
### F-AZ795-1 — `JsonException.Message` propagated in `GlobalExceptionHandler` (Low / A09) — **RESOLVED**
- **Location**: `GlobalExceptionHandler.cs` (deserializer branch).
- **Resolution**: `errors[<path>]` values use `JsonFieldErrorMessage` (`"The field value is invalid."`). Unit test `TryHandleAsync_DeserializationFailure_WritesValidationProblemDetailsWithJsonPath_AZ795` asserts no `TileInventoryRequest` type name leak.
### F-AZ795-2 — `BadHttpRequestException.Message` propagated as `detail` (Low / A09) — **RESOLVED**
- **Location**: `GlobalExceptionHandler.cs` (non-JSON bind branch).
- **Resolution**: `detail` uses `BadRequestDetailMessage` (`"The request could not be processed."`). Unit test `TryHandleAsync_BadHttpRequestExceptionWithoutJson_UsesStaticDetail` asserts no `Latitude` echo.
### F-AZ810-1 — `JsonException.Message` in `UavUploadValidationFilter` (Low / A09) — **RESOLVED**
- **Location**: `UavUploadValidationFilter.cs`.
- **Resolution**: `errors["metadata"]` uses `MetadataJsonParseError` (`` `metadata` could not be parsed as JSON. ``). Integration test `MetadataNotAnObject_Returns400` asserts response body lacks `System.`.
### F-AZ810-1b — Defence-in-depth path in `UavTileUploadHandler` (Low / A09) — **RESOLVED**
- **Location**: `UavTileUploadHandler.cs` metadata parse catch.
- **Resolution**: Envelope error uses same static string as filter. Unit test `HandleAsync_InvalidMetadataJson_ReturnsEnvelopeError`.
## Open carry-overs (unchanged by cycle 10)
### F-AZ810-2 — `UavTileMetadata.CapturedAt` typed `DateTime` not `DateTimeOffset` (Low / Informational)
- Still open — separate task per AZ-1113 exclusions.
## Pass areas (cycle-10 delta)
| Area | Result |
|------|--------|
| SQL injection | N/A — no SQL changes |
| Hardcoded secrets | None introduced |
| 5xx sanitization (AZ-353) | Unchanged — still sanitised |
| gRPC error messages | Unchanged from cycle-9 fix — still generic |
| New attack surface | None — message content only |
## Verdict
**PASS** (cycle-10 delta) — three REST information-disclosure carry-overs resolved; zero new findings.