mirror of
https://github.com/azaion/satellite-provider.git
synced 2026-06-26 07:21:13 +00:00
Sanitize 400 error messages in GlobalExceptionHandler and validation filters to use static strings. This change improves consistency and prevents leaking internal exception details. Updated tests to reflect new error messages for JSON parsing and bad request scenarios.
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
# REST 400 error message sanitization
|
||||
|
||||
**Task**: AZ-1113_rest_error_sanitizer
|
||||
**Name**: Sanitize REST 400 error messages (F-AZ795-1/2, F-AZ810-1)
|
||||
**Description**: Replace raw `JsonException` / `BadHttpRequestException` messages in client-facing HTTP 400 bodies with static, consumer-safe strings while preserving structured `errors[]` field paths.
|
||||
**Complexity**: 2 points
|
||||
**Dependencies**: AZ-795 (shared validation infra), AZ-810 (UavUploadValidationFilter)
|
||||
**Component**: SatelliteProvider.Api, SatelliteProvider.Services.TileDownloader
|
||||
**Tracker**: AZ-1113 (https://denyspopov.atlassian.net/browse/AZ-1113)
|
||||
**Epic**: AZ-795
|
||||
|
||||
## Problem
|
||||
|
||||
Strict JSON validation (AZ-795+) surfaces deserialization failures as HTTP 400 + RFC 7807 `ValidationProblemDetails`. Several code paths echo raw `Exception.Message` values that leak internal .NET type names, JSON paths with framework wording, or parameter binding details (F-AZ795-1, F-AZ795-2, F-AZ810-1). All paths are auth-gated but the production error contract should not expose implementation fingerprints.
|
||||
|
||||
## Outcome
|
||||
|
||||
- Client-visible 400 messages use fixed, documented strings; full exception details remain server-side only (existing log / correlationId patterns).
|
||||
- All three call sites sanitized in one change: `GlobalExceptionHandler`, `UavUploadValidationFilter`, `UavTileUploadHandler`.
|
||||
- `error-shape.md` documents the sanitization policy; existing integration tests updated; new assertions lock the contract.
|
||||
|
||||
## Scope
|
||||
|
||||
### Included
|
||||
- `SatelliteProvider.Api/GlobalExceptionHandler.cs` — sanitize `JsonException` messages in `errors[]` map entries; sanitize non-deserialization `BadHttpRequestException` `detail` (F-AZ795-1, F-AZ795-2)
|
||||
- `SatelliteProvider.Api/Validators/UavUploadValidationFilter.cs` — sanitize metadata JSON parse failures (F-AZ810-1)
|
||||
- `SatelliteProvider.Services.TileDownloader/UavTileUploadHandler.cs` — sanitize defense-in-depth metadata parse path (same finding class)
|
||||
- Unit tests: extend `GlobalExceptionHandlerTests`; add/adjust filter/handler tests as needed
|
||||
- Integration tests: assert response bodies do not contain `System.` substrings or known leaky patterns from fixture payloads
|
||||
- `_docs/02_document/contracts/api/error-shape.md` — patch bump + Information Disclosure section
|
||||
|
||||
### Excluded
|
||||
- FluentValidation rule message changes (already consumer-oriented)
|
||||
- gRPC `DeliveryError` path (resolved cycle 9)
|
||||
- F-AZ810-2 `DateTime` vs `DateTimeOffset` (separate task)
|
||||
- FluentValidation 12.0.0 → 12.1.1 bump (D-AZ795-1)
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
**AC-1: GlobalExceptionHandler JsonException sanitization**
|
||||
Given an authenticated request whose body triggers `BadHttpRequestException` with inner `JsonException` (unknown field or type mismatch)
|
||||
When the exception reaches `GlobalExceptionHandler`
|
||||
Then HTTP 400 `errors[<fieldPath>]` contains a static message (no `.NET` type name, no `System.Text.Json` fingerprint)
|
||||
And the raw exception is not echoed in `detail`
|
||||
|
||||
**AC-2: GlobalExceptionHandler non-JSON BadHttpRequest sanitization**
|
||||
Given a `BadHttpRequestException` without inner `JsonException` (e.g. query binding failure)
|
||||
When handled by `GlobalExceptionHandler`
|
||||
Then `detail` is a static string (not `badRequest.Message` verbatim)
|
||||
|
||||
**AC-3: UAV upload filter sanitization**
|
||||
Given `POST /api/satellite/upload` with malformed `metadata` JSON
|
||||
When `UavUploadValidationFilter` catches `JsonException`
|
||||
Then `errors["metadata"]` is a static string without `ex.Message`
|
||||
And an integration test proves no `System.` substring in the response body
|
||||
|
||||
**AC-4: UAV handler defense-in-depth sanitization**
|
||||
Given direct invocation or filter-bypass path where `UavTileUploadHandler` parses invalid metadata JSON
|
||||
When `JsonException` is caught
|
||||
Then the returned envelope error message is static (no `ex.Message`)
|
||||
|
||||
**AC-5: Contract documentation**
|
||||
Given the change ships
|
||||
When `error-shape.md` is read
|
||||
Then an Information Disclosure section lists sanitized vs allowed message sources and the static strings used
|
||||
|
||||
## Non-Functional Requirements
|
||||
|
||||
**Compatibility**
|
||||
- Preserve RFC 7807 shape, field paths in `errors[]`, and HTTP status codes — only message *content* changes
|
||||
- Update tests that currently assert substring of raw `JsonException.Message` (e.g. `GlobalExceptionHandlerTests.TryHandleAsync_DeserializationFailure_*`)
|
||||
|
||||
**Security**
|
||||
- No regression to AZ-353 5xx sanitization
|
||||
|
||||
## Unit Tests
|
||||
|
||||
| AC Ref | What to Test | Required Outcome |
|
||||
|--------|-------------|-----------------|
|
||||
| AC-1 | `GlobalExceptionHandler` + `JsonException` inner | `errors` values are static; no type name leak |
|
||||
| AC-2 | `GlobalExceptionHandler` + bind-only `BadHttpRequestException` | `detail` is static |
|
||||
| AC-4 | `UavTileUploadHandler` metadata parse failure | Envelope message static |
|
||||
|
||||
## Blackbox Tests
|
||||
|
||||
| AC Ref | Initial Data/Conditions | What to Test | Expected Behavior | NFR References |
|
||||
|--------|------------------------|-------------|-------------------|----------------|
|
||||
| AC-3 | Valid JWT + GPS claim; multipart with invalid metadata JSON | `POST /api/satellite/upload` | 400; body lacks `System.` | Security |
|
||||
|
||||
## Constraints
|
||||
|
||||
- Follow existing `ProblemDetails` / `ValidationProblemDetails` patterns in `error-shape.md` v1.0.0
|
||||
- Do not add verbose logging beyond existing exception logs
|
||||
|
||||
## Risks & Mitigation
|
||||
|
||||
| Risk | Mitigation |
|
||||
|------|------------|
|
||||
| Tests assert old raw messages | Update unit + integration assertions in same PR |
|
||||
| Consumers parsed error text | Field paths unchanged; only generic message strings — document in error-shape patch |
|
||||
|
||||
## Contract
|
||||
|
||||
Producer task — patch bump to `_docs/02_document/contracts/api/error-shape.md` (v1.0.0 → v1.0.1): document static 400 strings for deserializer/binding failures.
|
||||
Reference in New Issue
Block a user