Files
kite/.planning/milestones/v0.2-phases/08-stack-upgrade-backend-decomposition/08-SECURITY.md
T
curo1305andClaude Sonnet 4.6 123ae5b29b chore: archive v0.2 phase directories to milestones/v0.2-phases/
Moves phases 08–11 execution artifacts from .planning/phases/ to
.planning/milestones/v0.2-phases/ to keep .planning/phases/ clean
for the next milestone.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 14:34:52 +02:00

12 KiB

phase, slug, status, threats_open, asvs_level, created
phase slug status threats_open asvs_level created
8 stack-upgrade-backend-decomposition verified 0 2 2026-06-12

Phase 8 — Security

Per-phase security contract: threat register, accepted risks, and audit trail.


Trust Boundaries

Boundary Description Data Crossing
client → POST /api/auth/change-password Authenticated user changes password; backend revokes all OTHER refresh tokens JWT access token (Bearer); password plaintext (TLS-only)
client → POST /api/auth/totp/enable Authenticated user enables TOTP; backend revokes all OTHER refresh tokens JWT access token; TOTP code
client → DELETE /api/auth/totp Authenticated user disables TOTP; backend revokes all OTHER refresh tokens JWT access token; TOTP code
api/cloud.py → api/schemas.py Module-load-time import; no runtime data crosses Class reference only
Admin list-cloud-connections → CloudConnectionOut SEC-08: credentials_enc deliberately excluded from schema Sanitized connection metadata
Vue component → Pinia toast store In-process function call Hardcoded string literal (no user input)
Backend response (sessions_revoked) → frontend toast trigger Backend integer validated server-side; frontend uses boolean test only Integer (count only)
Unauthenticated client → /api/auth/login, /api/auth/register, /api/auth/refresh Rate-limited via @limiter.limit("10/minute") Credentials (TLS-only)
Authenticated user → /api/auth/refresh Refresh-token rotation + family-revocation on reuse httpOnly Strict cookie
Browser → backend API All requests carry Bearer token from authStore memory only JWT access token (never localStorage)
Browser → domain API modules In-process import; request() reads authStore.accessToken Access token (Pinia memory)
npmjs.com → frontend node_modules 8 PERF-01 packages installed Bundled JS (supply chain)
pypi.org → backend venv requirements.txt exact-pinned via D-17 Python packages (supply chain)

Threat Register

Threat ID Category Component Disposition Mitigation Status
T-08-01-01 Tampering Test fixture isolation mitigate Each CR test creates its own user via _register_user()/_login_session() helpers; revoke_client fixture provides isolated FakeRedis + db_session per test closed
T-08-01-02 Repudiation xfail strict mode mitigate @pytest.mark.xfail removed in plan 08-03; all three CR tests run strictly closed
T-08-01-SC Supply Chain pytest, pyotp accept Already pinned in requirements.txt (pytest==9.0.3, pyotp==2.9.0) closed
T-08-02-01 Information Disclosure CloudConnectionOut schema mitigate Field whitelist in api/schemas.py:14-42; credentials_enc confirmed absent closed
T-08-02-02 Tampering id coercion mitigate @field_validator("id", mode="before") coerce_id_to_str preserved verbatim at api/schemas.py:38-42 closed
T-08-02-03 Denial of Service Duplicate class definitions mitigate Old CloudConnectionOut in api/admin.py deleted in plan 08-04; api/cloud.py:35 imports only from api.schemas closed
T-08-02-SC Supply Chain No new packages accept Plan 08-02 installs zero new packages closed
T-08-03-01 Spoofing Toast message injection mitigate Toast message is a string literal in SettingsAccountTab.vue:204,240 and TotpEnrollment.vue:156; no user-controlled content closed
T-08-03-02 Repudiation Audit log for revoked sessions mitigate write_audit_log with sessions_revoked metadata preserved in api/auth/password.py:82-89, api/auth/totp.py:93-103, api/auth/totp.py:141-148 closed
T-08-03-03 Information Disclosure Toast leaks session count accept UI shows generic "Other sessions have been terminated."; exact count not disclosed closed
T-08-03-04 Tampering xfail strict=False masks regression mitigate Zero @pytest.mark.xfail decorators remain in backend/tests/test_auth.py closed
T-08-03-SC Supply Chain No new packages accept Plan 08-03 installs zero new packages closed
T-08-04-01 Elevation of Privilege Admin sub-router auth gate mitigate Every handler in users.py (7), quotas.py (2), ai.py (4) has _admin: User = Depends(get_current_admin) closed
T-08-04-02 Tampering Sub-router prefix doubling mitigate Sub-routers carry no prefix; sole prefix /api/admin in api/admin/__init__.py:20 closed
T-08-04-03 Information Disclosure _user_to_dict field set mitigate api/admin/shared.py:13-28 returns 10 whitelisted fields; password_hash, credentials_enc, totp_secret absent closed
T-08-04-04 Denial of Service Circular import via __init__.py mitigate api/admin/__init__.py — only APIRouter creation and three include_router calls closed
T-08-04-05 Tampering Validator duplication mitigate provider_must_be_known delegates entirely to services.ai_config.validate_provider_id (api/admin/ai.py:25,72-73,93-94) closed
T-08-04-06 Information Disclosure Old admin.py left in place mitigate backend/api/admin.py, backend/api/documents.py, backend/api/auth.py — all three old monolith files deleted closed
T-08-04-SC Supply Chain No new packages accept Plan 08-04 installs zero new packages closed
T-08-05-01 Elevation of Privilege IDOR on document endpoints mitigate Ownership assertion doc.user_id != current_user.id → 404 preserved on all handlers: crud.py:199-201,250-251,306-307,379-380, upload.py:289-291, content.py:89 closed
T-08-05-02 Tampering Sub-router prefix doubling mitigate Sub-routers carry no prefix; sole prefix /api/documents in api/documents/__init__.py:21 closed
T-08-05-03 Information Disclosure DocumentPatch.filename validator mitigate filename_no_path_separators raises ValueError on / or \ in api/documents/shared.py:40-45 closed
T-08-05-04 Tampering Atomic quota UPDATE invariant mitigate Atomic UPDATE quotas SET used_bytes = used_bytes + $delta WHERE … RETURNING preserved in upload.py:310-316; atomic decrement in services/storage.py:179-186 closed
T-08-05-05 Denial of Service Circular import via __init__.py mitigate api/documents/__init__.py — only aggregation closed
T-08-05-SC Supply Chain No new packages accept Plan 08-05 installs zero new packages closed
T-08-06-01 Spoofing limiter re-export mitigate api/auth/__init__.py:13 re-exports the same Limiter instance from shared.py:22; identity confirmed via app.state.limiter is api.auth.limiter closed
T-08-06-02 Repudiation CR-01/CR-02/CR-03 audit log entries mitigate write_audit_log with sessions_revoked metadata preserved on all three handlers in password.py and totp.py closed
T-08-06-03 Tampering Refresh-token rotation logic mitigate JTI, fgp, family-revocation on reuse all present in services/auth.py:114-115,233-239 closed
T-08-06-04 Information Disclosure Sub-router prefix doubling mitigate Sub-routers carry no prefix; sole prefix /api/auth in api/auth/__init__.py:15 closed
T-08-06-05 Denial of Service Circular import via __init__.py mitigate api/auth/__init__.py — only aggregation closed
T-08-06-06 Elevation of Privilege Session revocation skip mitigate skip_token_hash=skip_hash preserved in password.py:79-80, totp.py:89-90 (enable), totp.py:136-137 (disable) closed
T-08-06-SC Supply Chain No new packages accept Plan 08-06 installs zero new packages closed
T-08-07-01 Spoofing Bearer token injection mitigate utils.js:31-37 lazy-imports authStore and reads authStore.accessToken; pattern preserved in fetchWithRetry:97-102 closed
T-08-07-02 Tampering Circular import producing undefined exports mitigate request lives in utils.js; all domain modules (documents.js:8, auth.js:8, etc.) import from utils.js closed
T-08-07-03 Repudiation 401-refresh-retry loop mitigate _retry flag preserved in request() (utils.js:45) and fetchWithRetry() (utils.js:107); recursion bounded closed
T-08-07-04 Information Disclosure Token stored in JS storage mitigate utils.js:35-36 reads authStore.accessToken (Pinia memory only); zero localStorage/sessionStorage references closed
T-08-07-05 Tampering export * name collision mitigate All 7 domain module export names verified unique; frontend build + test suite would fail on collision closed
T-08-07-06 Denial of Service Consumer files break mitigate client.js:13-20export * from each domain module + explicit re-exports from utils.js; 36 consumer files confirmed untouched closed
T-08-07-SC Supply Chain No new npm packages accept Plan 08-07 installs zero new packages closed
T-08-08-01 Supply Chain (Tampering) 8 npm package installs mitigate Human checkpoint (task 1) required; packages verified on npmjs.com; package.json:12-19 confirms all 8 present closed
T-08-08-02 Tampering Vite 6 migration breaking behavior mitigate No breaking changes apply (no custom resolve.conditions, no Sass, no library mode); package.json:30"vite": "^6.4.3"; npm test + build pass closed
T-08-08-03 Information Disclosure requirements.txt leaks versions accept Version visibility in requirements.txt accepted; reproducibility benefit outweighs disclosure closed
T-08-08-04 Denial of Service alembic version discrepancy mitigate requirements.txt:18-19alembic==1.16.5 with inline comment documenting the >=1.18.41.16.5 discrepancy for future deliberate bump closed
T-08-08-05 Tampering @vitejs/plugin-vue peer-dep mismatch mitigate Both vite@^6 and @vitejs/plugin-vue@^6 installed together per RESEARCH.md §Pitfall 6; package.json:23,30 confirms major v6 alignment closed
T-08-08-SC Supply Chain npm packages mitigate Human checkpoint is the gate; packages verified; SUMMARY.md confirms pass closed

Status: open · closed Disposition: mitigate (implementation required) · accept (documented risk) · transfer (third-party)


Accepted Risks Log

Risk ID Threat Ref Rationale Accepted By Date
AR-08-01 T-08-01-SC pytest/pyotp already pinned in requirements.txt before this phase project owner 2026-06-12
AR-08-02 T-08-02-SC Plan 08-02 adds no new packages project owner 2026-06-12
AR-08-03 T-08-03-03 Toast shows generic message only; session count not disclosed to UI project owner 2026-06-12
AR-08-04 T-08-03-SC Plan 08-03 adds no new packages project owner 2026-06-12
AR-08-05 T-08-04-SC Plan 08-04 adds no new packages project owner 2026-06-12
AR-08-06 T-08-05-SC Plan 08-05 adds no new packages project owner 2026-06-12
AR-08-07 T-08-06-SC Plan 08-06 adds no new packages project owner 2026-06-12
AR-08-08 T-08-07-SC Plan 08-07 adds no new npm packages project owner 2026-06-12
AR-08-09 T-08-08-03 Package versions in requirements.txt are not secrets; reproducibility benefit accepted project owner 2026-06-12

Security Audit Trail

Audit Date Threats Total Closed Open Run By
2026-06-12 45 45 0 gsd-security-auditor (claude-sonnet-4-6)

Sign-Off

  • All threats have a disposition (mitigate / accept / transfer)
  • Accepted risks documented in Accepted Risks Log
  • threats_open: 0 confirmed
  • status: verified set in frontmatter

Approval: verified 2026-06-12