Files
annotations/_docs/02_tasks/todo/AZ-571_test_security.md
T
Oleksandr Bezdieniezhnykh cf632d9e2e [AZ-563] Decompose blackbox tests into AZ-564..574 task specs
Step 5 of autodev existing-code flow. Epic AZ-563 plus 11 atomic
tasks covering all 67 test scenarios from
_docs/02_document/tests/* exactly once:

- AZ-564 test infrastructure (xUnit + Docker + mock JWKS + dataseed)
- AZ-565..568 functional positive (FT-P-01..22)
- AZ-569..570 functional negative (FT-N-01..16)
- AZ-571 security (NFT-SEC-01..10)
- AZ-572 resilience (NFT-RES-01..06)
- AZ-573 resource limits (NFT-RES-LIM-01..06)
- AZ-574 performance (NFT-PERF-*)

_dependencies_table.md records the cross-check vs traceability
matrix (22 + 16 + 29 = 67 scenarios, no overlaps, no gaps; deferred
items remain deferred per matrix). All task headers carry their
Jira IDs (tracker: jira). Autodev state advanced to Step 6
(Implement Tests).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-14 21:13:53 +03:00

3.0 KiB

Security tests (NFT-SEC-01..10)

Task: AZ-571 Name: Security tests Description: Implement xUnit tests for all 10 security scenarios: JWT signature mismatch, expired, cross-policy DATASET/ANN, anonymous-access denials, error envelope no-stack-leak, path traversal in image/thumbnail GETs, token claim tampering, CORS preflight, alg-confusion alg=HS256 forgery. Complexity: 5 points Dependencies: AZ-564 (test infrastructure) Component: Blackbox Tests → Security Tracker: jira Epic: AZ-563

Scenarios Covered

Test ID Source What it asserts
NFT-SEC-01 _docs/02_document/tests/security-tests.md JWT signed with key NOT in JWKS. HTTP 401.
NFT-SEC-02 same JWT expired. HTTP 401.
NFT-SEC-03 same DATASET token → POST /annotations. HTTP 403.
NFT-SEC-04 same ANN token → PUT /settings/*. HTTP 403.
NFT-SEC-05 same Anonymous access to non-public endpoints. Only /health is anonymous; everything else returns 401 without auth.
NFT-SEC-06 same Error envelope under Production env mode does NOT leak stack traces.
NFT-SEC-07 same Path traversal in image / thumbnail GET routes. ../etc/passwd style payloads return 400/404, never 200 with foreign content.
NFT-SEC-08 same Token claim modification (signature breaks). HTTP 401.
NFT-SEC-09 same CORS preflight respects CorsConfig:AllowedOrigins allow-list under Production.
NFT-SEC-10 same Algorithm confusion — token forged with alg=HS256 using the published ES256 public key as the HMAC secret. HTTP 401.

System Under Test Boundary

  • HTTP only.
  • Token variants minted via TokenMinter.MintToken(claim, overrides).
  • NFT-SEC-06 requires the SUT to be re-booted with ASPNETCORE_ENVIRONMENT=Production (and a Production-safe CORS config). This is a separate compose profile or test class with its own SutRestartFixture.
  • NFT-SEC-09 requires a second SUT boot under Production with CorsConfig__AllowedOrigins__0: https://app.azaion.local. Asserts ACAO is exactly that one origin.

Acceptance Criteria

AC-1: Every scenario passes per its spec.

AC-2: NFT-SEC-10 explicitly verifies algorithm pinning Given a token forged with alg=HS256 and the published ES256 public key as the HMAC secret, When the runner presents it to POST /annotations, Then HTTP 401 is returned and the error envelope contains "Bearer error=invalid_token" in WWW-Authenticate.

AC-3: NFT-SEC-06 verifies no stack leak Given ASPNETCORE_ENVIRONMENT=Production, When a request triggers a 500-class error, Then the response body's error envelope contains only the safe error code and message — no stackTrace, no innerException, no file paths.

Constraints

  • AAA pattern.
  • [Trait("traces_to", "AC-F-50, AC-F-51, AC-F-52, SW-05, ENV-06")] plus per-test specific traces.
  • Production-env tests run in a dedicated test class with its own fixture (no leak between Production and E2ETest boots).