test(security): A-3 pre-fix tests for auth middleware coverage bugs
Pre-fix test suite documenting 8 auth middleware bugs found during the A-3 recon audit. Tests are written to FAIL where they assert correct post-fix behavior, and PASS where they document current buggy behavior. No bugs are fixed in this commit. Tests added: - F-A3-11 CRITICAL: WebAuthMiddleware leaks JWT secret to stdout (3 tests: secret in output, emoji in output, ETHOS format) - F-A3-7 CRITICAL: Config download requires no auth (2 tests) - F-A3-6 HIGH: Update package download requires no auth (2 tests) - F-A3-10 HIGH: Scheduler stats accepts agent JWT (2 tests) - F-A3-12 MEDIUM: Cross-type JWT token confusion (2 tests) - F-A3-2 MEDIUM: /auth/verify dead endpoint (2 tests) - F-A3-13 LOW: RequireAdmin middleware missing (1 test + 1 build-tagged) - F-A3-9 MEDIUM: Agent self-unregister no rate limit (2 tests) Current state: 10 FAIL, 7 PASS, 1 SKIP (build-tagged), 1 unchanged See docs/A3_PreFix_Tests.md for full inventory. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
229
docs/A3_PreFix_Tests.md
Normal file
229
docs/A3_PreFix_Tests.md
Normal file
@@ -0,0 +1,229 @@
|
||||
# A-3 Pre-Fix Test Suite
|
||||
|
||||
**Date:** 2026-03-28
|
||||
**Branch:** culurien
|
||||
**Purpose:** Document auth middleware coverage bugs BEFORE fixes are applied.
|
||||
**Reference:** A-3 Auth Middleware Audit (recon findings F-A3-1 through F-A3-14)
|
||||
|
||||
These tests prove that the bugs exist today and will prove the fixes work
|
||||
when applied. Do NOT modify these tests before the fix is ready — they are
|
||||
the regression baseline.
|
||||
|
||||
---
|
||||
|
||||
## Test Files Created
|
||||
|
||||
| File | Package | Bugs Documented |
|
||||
|------|---------|-----------------|
|
||||
| `aggregator-server/internal/api/middleware/auth_secret_leak_test.go` | `middleware_test` | F-A3-11 (agent-side baseline) |
|
||||
| `aggregator-server/internal/api/handlers/auth_middleware_leak_test.go` | `handlers_test` | F-A3-11 (web middleware leak) |
|
||||
| `aggregator-server/internal/api/handlers/downloads_auth_test.go` | `handlers_test` | F-A3-7, F-A3-6 |
|
||||
| `aggregator-server/internal/api/middleware/scheduler_auth_test.go` | `middleware_test` | F-A3-10 |
|
||||
| `aggregator-server/internal/api/middleware/token_confusion_test.go` | `middleware_test` | F-A3-12 |
|
||||
| `aggregator-server/internal/api/handlers/auth_verify_test.go` | `handlers_test` | F-A3-2 |
|
||||
| `aggregator-server/internal/api/middleware/require_admin_test.go` | `middleware_test` | F-A3-13 |
|
||||
| `aggregator-server/internal/api/middleware/require_admin_behavior_test.go` | `middleware_test` | F-A3-13 (build-tagged, cannot compile yet) |
|
||||
| `aggregator-server/internal/api/handlers/agent_unregister_test.go` | `handlers_test` | F-A3-9 |
|
||||
|
||||
---
|
||||
|
||||
## How to Run
|
||||
|
||||
```bash
|
||||
# Middleware tests (scheduler, token confusion, RequireAdmin, agent auth)
|
||||
cd aggregator-server && go test ./internal/api/middleware/... -v
|
||||
|
||||
# Handler tests (JWT leak, downloads auth, verify, unregister)
|
||||
cd aggregator-server && go test ./internal/api/handlers/... -v
|
||||
|
||||
# Run specific test groups
|
||||
cd aggregator-server && go test ./internal/api/middleware/... -v -run TestScheduler
|
||||
cd aggregator-server && go test ./internal/api/middleware/... -v -run TestToken
|
||||
cd aggregator-server && go test ./internal/api/middleware/... -v -run TestRequireAdmin
|
||||
cd aggregator-server && go test ./internal/api/handlers/... -v -run TestWebAuth
|
||||
cd aggregator-server && go test ./internal/api/handlers/... -v -run TestConfigDownload
|
||||
cd aggregator-server && go test ./internal/api/handlers/... -v -run TestAuthVerify
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Test Inventory
|
||||
|
||||
### File 1: `middleware/auth_secret_leak_test.go` — Agent Middleware Baseline
|
||||
|
||||
#### `TestAgentAuthMiddlewareDoesNotLogSecret`
|
||||
- **Bug:** F-A3-11 (baseline contrast — agent middleware is clean)
|
||||
- **Asserts:** Agent AuthMiddleware does NOT print JWT secret to stdout
|
||||
- **Current state:** PASS (agent middleware is not affected)
|
||||
- **Purpose:** Establishes that the leak is specific to WebAuthMiddleware
|
||||
|
||||
#### `TestAgentAuthMiddlewareLogHasNoEmoji`
|
||||
- **Bug:** F-A3-11 (baseline contrast)
|
||||
- **Asserts:** Agent AuthMiddleware stdout has no emoji characters
|
||||
- **Current state:** PASS
|
||||
|
||||
### File 2: `handlers/auth_middleware_leak_test.go` — WebAuth Secret Leak
|
||||
|
||||
#### `TestWebAuthMiddlewareDoesNotLogSecret`
|
||||
- **Bug:** F-A3-11 CRITICAL
|
||||
- **Asserts:** WebAuthMiddleware stdout does NOT contain the JWT secret string
|
||||
- **Current state:** FAIL — auth.go:128 prints `h.jwtSecret` directly
|
||||
- **After fix:** PASS — remove secret from log output
|
||||
|
||||
#### `TestWebAuthMiddlewareLogFormatHasNoEmoji`
|
||||
- **Bug:** F-A3-11 CRITICAL
|
||||
- **Asserts:** WebAuthMiddleware stdout has no emoji (specifically U+1F513), word "secret" absent
|
||||
- **Current state:** FAIL — output contains lock emoji and word "secret"
|
||||
- **After fix:** PASS — use `[WARNING] [server] [auth]` format
|
||||
|
||||
#### `TestWebAuthMiddlewareLogFormatCompliant`
|
||||
- **Bug:** F-A3-11 CRITICAL
|
||||
- **Asserts:** If stdout output exists, lines start with `[TAG]` pattern, no secret in output
|
||||
- **Current state:** FAIL — output is emoji-prefixed, contains secret
|
||||
- **After fix:** PASS — ETHOS-compliant format or no stdout output
|
||||
|
||||
### File 3: `handlers/downloads_auth_test.go` — Unauthenticated Downloads
|
||||
|
||||
#### `TestConfigDownloadRequiresAuth`
|
||||
- **Bug:** F-A3-7 CRITICAL
|
||||
- **Asserts:** GET /downloads/config/:agent_id returns 401/403 without auth
|
||||
- **Current state:** FAIL — returns 200 (no auth middleware on route)
|
||||
- **After fix:** PASS — add AuthMiddleware or WebAuthMiddleware
|
||||
|
||||
#### `TestConfigDownloadCurrentlyUnauthenticated`
|
||||
- **Bug:** F-A3-7 CRITICAL
|
||||
- **Asserts:** Config download succeeds without auth (documents bug)
|
||||
- **Current state:** PASS — no auth middleware, request reaches handler
|
||||
- **After fix:** FAIL — update to assert 401
|
||||
|
||||
#### `TestUpdatePackageDownloadRequiresAuth`
|
||||
- **Bug:** F-A3-6 HIGH
|
||||
- **Asserts:** GET /downloads/updates/:package_id returns 401/403 without auth
|
||||
- **Current state:** FAIL — returns 200 (no auth middleware)
|
||||
- **After fix:** PASS — add AuthMiddleware
|
||||
|
||||
#### `TestUpdatePackageDownloadCurrentlyUnauthenticated`
|
||||
- **Bug:** F-A3-6 HIGH
|
||||
- **Asserts:** Update package download succeeds without auth (documents bug)
|
||||
- **Current state:** PASS
|
||||
- **After fix:** FAIL — update to assert 401
|
||||
|
||||
### File 4: `middleware/scheduler_auth_test.go` — Scheduler Wrong Auth
|
||||
|
||||
#### `TestSchedulerStatsRequiresAdminAuth`
|
||||
- **Bug:** F-A3-10 HIGH
|
||||
- **Asserts:** Agent JWT is rejected on /scheduler/stats (should require admin)
|
||||
- **Current state:** FAIL — agent JWT accepted (200)
|
||||
- **After fix:** PASS — change to WebAuthMiddleware
|
||||
|
||||
#### `TestSchedulerStatsCurrentlyAcceptsAgentJWT`
|
||||
- **Bug:** F-A3-10 HIGH
|
||||
- **Asserts:** Agent JWT is accepted on /scheduler/stats (documents bug)
|
||||
- **Current state:** PASS — AuthMiddleware accepts agent JWT
|
||||
- **After fix:** FAIL — update to assert rejection
|
||||
|
||||
### File 5: `middleware/token_confusion_test.go` — Cross-Type Token Confusion
|
||||
|
||||
#### `TestWebTokenRejectedByAgentAuthMiddleware`
|
||||
- **Bug:** F-A3-12 MEDIUM
|
||||
- **Asserts:** Web/admin JWT is rejected by agent AuthMiddleware
|
||||
- **Current state:** FAIL — web JWT passes agent auth (shared secret, no audience check)
|
||||
- **After fix:** PASS — add issuer/audience claims or separate secrets
|
||||
|
||||
#### `TestAgentTokenRejectedByWebAuthMiddleware`
|
||||
- **Bug:** F-A3-12 MEDIUM
|
||||
- **Asserts:** Agent JWT is rejected by WebAuthMiddleware
|
||||
- **Current state:** FAIL — agent JWT passes web auth (shared secret, claims parse succeeds)
|
||||
- **After fix:** PASS — add issuer/audience claims or separate secrets
|
||||
|
||||
### File 6: `handlers/auth_verify_test.go` — Dead Verify Endpoint
|
||||
|
||||
#### `TestAuthVerifyAlwaysReturns401WithoutMiddleware`
|
||||
- **Bug:** F-A3-2 MEDIUM
|
||||
- **Asserts:** /auth/verify returns 401 even with valid JWT (no middleware sets context)
|
||||
- **Current state:** PASS — documents the dead endpoint
|
||||
- **After fix:** N/A (test documents pre-fix state)
|
||||
|
||||
#### `TestAuthVerifyWorksWithMiddleware`
|
||||
- **Bug:** F-A3-2 MEDIUM
|
||||
- **Asserts:** /auth/verify returns 200 when WebAuthMiddleware is applied
|
||||
- **Current state:** PASS — demonstrates the fix is just adding middleware to the route
|
||||
- **Note:** This test already passes because it applies WebAuthMiddleware directly. The bug is in the route registration (main.go:388), not in the handler code.
|
||||
|
||||
### File 7: `middleware/require_admin_test.go` — Missing RequireAdmin
|
||||
|
||||
#### `TestRequireAdminMiddlewareExists`
|
||||
- **Bug:** F-A3-13 LOW
|
||||
- **Asserts:** RequireAdmin function exists in middleware package (AST scan)
|
||||
- **Current state:** FAIL — function not found
|
||||
- **After fix:** PASS — implement RequireAdmin()
|
||||
|
||||
### File 8: `middleware/require_admin_behavior_test.go` — RequireAdmin Behavior
|
||||
|
||||
- **Build tag:** `//go:build ignore` — cannot compile until RequireAdmin exists
|
||||
- **Bug:** F-A3-13 LOW
|
||||
- **Contains:** `TestRequireAdminBlocksNonAdminUsers` — tests admin vs non-admin role check
|
||||
- **Current state:** Cannot compile (skipped)
|
||||
- **After fix:** Remove build tag, test should PASS
|
||||
|
||||
### File 9: `handlers/agent_unregister_test.go` — Missing Rate Limit
|
||||
|
||||
#### `TestAgentSelfUnregisterHasNoRateLimit`
|
||||
- **Bug:** F-A3-9 MEDIUM
|
||||
- **Asserts:** Documents that DELETE /:id route has no rate limiter
|
||||
- **Current state:** PASS — documents the bug
|
||||
|
||||
#### `TestAgentSelfUnregisterShouldHaveRateLimit`
|
||||
- **Bug:** F-A3-9 MEDIUM
|
||||
- **Asserts:** DELETE /:id SHOULD have rate limiter in middleware chain
|
||||
- **Current state:** FAIL — no rate limiter on route
|
||||
- **After fix:** PASS — add rate limiter
|
||||
|
||||
---
|
||||
|
||||
## State-Change Summary
|
||||
|
||||
| Test | Current | After Fix |
|
||||
|------|---------|-----------|
|
||||
| TestAgentAuthMiddlewareDoesNotLogSecret | PASS | PASS (unchanged) |
|
||||
| TestAgentAuthMiddlewareLogHasNoEmoji | PASS | PASS (unchanged) |
|
||||
| TestWebAuthMiddlewareDoesNotLogSecret | **FAIL** | PASS |
|
||||
| TestWebAuthMiddlewareLogFormatHasNoEmoji | **FAIL** | PASS |
|
||||
| TestWebAuthMiddlewareLogFormatCompliant | **FAIL** | PASS |
|
||||
| TestConfigDownloadRequiresAuth | **FAIL** | PASS |
|
||||
| TestConfigDownloadCurrentlyUnauthenticated | PASS | FAIL (update) |
|
||||
| TestUpdatePackageDownloadRequiresAuth | **FAIL** | PASS |
|
||||
| TestUpdatePackageDownloadCurrentlyUnauthenticated | PASS | FAIL (update) |
|
||||
| TestSchedulerStatsRequiresAdminAuth | **FAIL** | PASS |
|
||||
| TestSchedulerStatsCurrentlyAcceptsAgentJWT | PASS | FAIL (update) |
|
||||
| TestWebTokenRejectedByAgentAuthMiddleware | **FAIL** | PASS |
|
||||
| TestAgentTokenRejectedByWebAuthMiddleware | **FAIL** | PASS |
|
||||
| TestAuthVerifyAlwaysReturns401WithoutMiddleware | PASS | PASS (unchanged) |
|
||||
| TestAuthVerifyWorksWithMiddleware | PASS | PASS (unchanged) |
|
||||
| TestRequireAdminMiddlewareExists | **FAIL** | PASS |
|
||||
| TestRequireAdminBlocksNonAdminUsers | SKIP (build tag) | PASS |
|
||||
| TestAgentSelfUnregisterHasNoRateLimit | PASS | PASS (unchanged) |
|
||||
| TestAgentSelfUnregisterShouldHaveRateLimit | **FAIL** | PASS |
|
||||
|
||||
**Bold FAIL** = tests that assert correct post-fix behavior (will flip to PASS after fix).
|
||||
Regular PASS = tests that document current buggy state (some will flip to FAIL after fix).
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
1. **TestAuthVerifyWorksWithMiddleware** passes even in pre-fix state because it
|
||||
directly applies WebAuthMiddleware to the test router. The bug is not in the
|
||||
handler but in the route registration (main.go:388 missing middleware). This
|
||||
test validates that the fix is a one-line change.
|
||||
|
||||
2. **TestAgentTokenRejectedByWebAuthMiddleware** reveals that JWT cross-type
|
||||
confusion works in BOTH directions: agent tokens pass web auth AND web tokens
|
||||
pass agent auth. The `jwt.ParseWithClaims` call succeeds because both claim
|
||||
types share the same signing key and the JSON unmarshaling is permissive.
|
||||
|
||||
3. **require_admin_behavior_test.go** uses `//go:build ignore` because it
|
||||
references `middleware.RequireAdmin` which does not exist. Enable this test
|
||||
when F-A3-13 is fixed by removing the build tag.
|
||||
|
||||
4. All A-2 tests continue to pass (no regressions from A-3 test additions).
|
||||
Reference in New Issue
Block a user