- Overhauled README.md to serve as a unified system index and WIP tracker. - Standardized documentation filenames (ARCH__, GUIDE__, PLAN__) for better discoverability. - Archived completed project plans and scopes. - Fixed regressions in unit tests (errors, models, email) caused by V3 architectural updates. - Ensured unit tests remain non-destructive and environment-independent via mocking.
60 lines
3.2 KiB
Markdown
60 lines
3.2 KiB
Markdown
# Project: API Security Hardening (V3)
|
|
|
|
**Status:** Draft / Planning
|
|
**Date:** Jan 18, 2026
|
|
**Owner:** Scott / Aether API Team
|
|
|
|
## 1. Executive Summary
|
|
This project aims to close a critical security vulnerability in the Aether API V3 dependencies where the `x_no_account_id` header allows unauthorized "Superuser/Bypass" access without validation. Additionally, it addresses the lack of cryptographic verification for JWTs in the V3 CRUD layer.
|
|
|
|
## 2. The Vulnerabilities
|
|
|
|
### A. The "Bypass Header" (Critical)
|
|
* **Issue:** The `get_account_context_optional` dependency in `app/routers/dependencies_v3.py` accepts a header `x_no_account_id`. If present, it sets `auth_method = 'bypass'` and grants full administrative privileges (`super=True`).
|
|
* **Note:** This header may be sent as `x_no_account_id` or `x-no-account-id`. FastAPI's `Header` logic should handle the conversion, but validation must be explicit.
|
|
* **Current State:** There is **no** validation of this header. Sending `x_no_account_id: anything` works.
|
|
* **Risk:** Total system compromise via simple header injection.
|
|
|
|
### B. JWT Verification (High)
|
|
* **Issue:** The system validates users by looking up the `x_account_id` string in the database (Redis/MariaDB).
|
|
* **Current State:** It does **not** cryptographically verify the JWT signature or expiration in the V3 dependency chain.
|
|
* **Risk:** Account impersonation if an Account ID is leaked.
|
|
|
|
## 3. Implementation Plan
|
|
|
|
### Phase 1: Secure the Bypass Header (Immediate)
|
|
**Goal:** Restrict "Bypass Mode" to clients possessing a valid, active API Key.
|
|
|
|
1. **Refactor Dependencies:**
|
|
* Update `get_account_context_optional` to accept `x_aether_api_key`.
|
|
* **Logic Change:** If `x_no_account_id` header is detected:
|
|
* **Require** `x_aether_api_key`.
|
|
* **Lookup** key in `api_key` table.
|
|
* **Verify** `enable = 1` and `now()` is between `enable_from` and `enable_to`.
|
|
* **Failure Behavior:** If key is invalid/missing, log warning and deny 'bypass' status (fall back to 'guest').
|
|
|
|
2. **Verification:**
|
|
* Test `curl` with header only -> Expect 403/Forbidden.
|
|
* Test `curl` with header + valid Key -> Expect 200/OK.
|
|
* Test Frontend File Download (uses `x_no_account_id_token` param) -> Expect 200/OK (No regression).
|
|
|
|
### Phase 2: JWT Verification (Subsequent)
|
|
**Goal:** Replace DB-lookup auth with cryptographic JWT validation.
|
|
|
|
1. **Audit:** Confirm `app/lib_jwt.py` logic is sound.
|
|
2. **Middleware/Dependency:** Integrate `decode_jwt` into the `get_account_context` flow.
|
|
3. **Transition:** Allow dual-mode (DB lookup OR JWT) for a transition period if necessary, or cut over if frontend sends valid JWTs.
|
|
|
|
## 4. Impact Analysis
|
|
* **Frontend (SvelteKit):**
|
|
* Audit confirmed no usage of `x_no_account_id` **header** in active source code.
|
|
* Usage of `x_no_account_id_token` (Query Param) is **safe** and distinct from the header logic.
|
|
* **Scripts/External Tools:**
|
|
* Any external scripts using the "Bypass" header must be updated to send a valid API Key.
|
|
|
|
## 5. Action Items
|
|
- [ ] Create `PROJECT_SECURITY_HARDENING.md` (This document).
|
|
- [ ] Refactor `app/routers/dependencies_v3.py`.
|
|
- [ ] Verify fix with `curl` tests.
|
|
- [ ] Commit changes.
|