# Security Tests ### NFT-SEC-01: JWT Authentication Required on Protected Endpoints **Summary**: Validate all protected endpoints reject requests without a valid JWT token. **Traces to**: AC-14 (security — JWT auth on API) **Steps**: | Step | Consumer Action | Expected Response | |------|----------------|------------------| | 1 | POST /sessions with no Authorization header | HTTP 401 | | 2 | GET /sessions/{id}/stream with no Authorization header | HTTP 401 | | 3 | POST /sessions/{id}/anchor with no Authorization header | HTTP 401 | | 4 | DELETE /sessions/{id} with no Authorization header | HTTP 401 | | 5 | POST /objects/locate with no Authorization header | HTTP 401 | | 6 | GET /health with no Authorization header | HTTP 200 (health is public) | **Pass criteria**: All protected endpoints return 401; /health returns 200 without auth --- ### NFT-SEC-02: Expired JWT Token Rejection **Summary**: Validate the system rejects expired JWT tokens. **Traces to**: AC-14 (security) **Steps**: | Step | Consumer Action | Expected Response | |------|----------------|------------------| | 1 | Generate a JWT token with exp set to 1 hour ago | Expired token | | 2 | POST /sessions with expired token in Authorization header | HTTP 401 | | 3 | POST /objects/locate with expired token | HTTP 401 | **Pass criteria**: Expired tokens are rejected with 401 --- ### NFT-SEC-03: Invalid JWT Signature Rejection **Summary**: Validate the system rejects JWT tokens signed with the wrong key. **Traces to**: AC-14 (security) **Steps**: | Step | Consumer Action | Expected Response | |------|----------------|------------------| | 1 | Generate a JWT token with a different signing key | Invalid signature token | | 2 | POST /sessions with invalid-signature token | HTTP 401 | **Pass criteria**: Invalid-signature tokens are rejected with 401 --- ### NFT-SEC-04: Malformed API Request Handling **Summary**: Validate the system handles malformed API payloads without crashing or leaking internal details. **Traces to**: AC-14 (security), AC-16 (API robustness) **Steps**: | Step | Consumer Action | Expected Response | |------|----------------|------------------| | 1 | POST /objects/locate with empty body | HTTP 422 with generic error (no stack trace) | | 2 | POST /objects/locate with body `{"pixel_x": "not_a_number"}` | HTTP 422 with validation error | | 3 | POST /sessions with body exceeding 1MB | HTTP 413 or 422 (no crash) | | 4 | POST /sessions/{id}/anchor with body `{"lat": 999, "lon": 999}` | HTTP 422 (invalid coordinates) | | 5 | Verify system continues operating after all malformed requests | GET /health returns 200 | **Pass criteria**: All malformed requests return 4xx errors with safe error messages (no stack traces, no internal paths); system remains operational --- ### NFT-SEC-05: MAVLink Injection Resistance **Summary**: Validate the system ignores unexpected or malformed MAVLink messages on the MAVLink channel. **Traces to**: AC-15 (ground station commands), solution security analysis **Steps**: | Step | Consumer Action | Expected Response | |------|----------------|------------------| | 1 | Send unexpected MAVLink message types to the system's MAVLink port | System ignores (no crash, no state corruption) | | 2 | Send malformed COMMAND_LONG with invalid lat/lon in re-localization hint | System rejects or ignores invalid coordinates | | 3 | Verify GPS_INPUT output continues normally | No disruption | **Pass criteria**: System ignores unexpected messages; continues normal operation; does not process invalid re-localization coordinates