SPB Git

spb/akos

Public
4.2 KB

# AKOS security review (self-review, 2026-11-01)

Scope: code in akos/, deployment on M4M64c behind the MacLustr Tunnel, Claude Code integration. Method: threat model (docs/threat-model.md) walked control by control with the automated tests as evidence (make test, make test-node).

Area Status Evidence / notes
Transport TLS terminated by Caddy on BHS64 (auto certs), HSTS set by the app; backend bound to loopback + WireGuard address only (lsof on node: 127.0.0.1:8520, 10.67.0.33:8520, 127.0.0.1:8521) akos/app.py:serve, tests/security/test_ssrf_injection_limits.py::test_path_traversal_and_validation (headers)
Proxy trust X-Forwarded-* honoured only from 127.0.0.1, ::1, 10.67.0.1 akos/api/deps.py:client_ip, uvicorn forwarded_allow_ips
Authentication argon2id passwords; HttpOnly/Secure/SameSite=Lax session cookie (12 h); bearer tokens stored as sha256, constant-time compare, revocable, scoped, optionally bound to a project test_auth_tenant.py
Authorization roles viewer/operator/admin; scopes read/execute/discover/export/mcp/admin; project-bound tokens cannot read other projects' executions, bodies, datasets or projects test_auth_tenant.py::test_tenant_separation
SSRF scheme allowlist, blocked hosts (localhost/.local/.internal/metadata), private/link-local/CGNAT/loopback rejection after DNS resolution, IP pinning for the connection, redirects re-validated (max 3), credentials-in-URL rejected test_ssrf_blocks_private_and_metadata_targets, test_redirect_to_private_is_refused
Secrets values only in keychain; DB/API/logs/exports/generated code grep-tested for a fake secret; redaction filter on logs and API serialisation; rotation/revocation tested; no secret in git (.gitignore, .env.example) test_credentials_scoped_rotation_revocation_no_leak
Prompt injection via docs OpenAPI parsed structurally; descriptions stored as strings; codegen from templates; static AST scan refuses eval/exec/subprocess/os.system/file writes/unapproved imports test_prompt_injection_in_docs_is_inert, test_scan_rejects_dangerous_code
Enforcement boundary sandbox-exec profile denies outbound network except loopback and denies writes outside the workdir; egress proxy allows only live grants; blocked attempts logged tests/security/test_enforcement.py (node)
Audit integrity hash-chained events, DB trigger forbids UPDATE/DELETE, GET /audit/verify test_audit_chain_detects_tampering
Rate limiting / exhaustion per-token token bucket (300/min default), login 20/min per IP, 10 MiB request body cap, 25 MiB response cap, 30 s execution timeout, bounded worker concurrency, per-project/agent daily budgets test_rate_limit_token_bucket, test_policy_modes_and_provenance (big response)
Path traversal AKP file names validated, artifacts addressed by sha256/uuid, docs names alphanumeric test_path_traversal_and_validation
Idempotency idempotency_key unique on executions and jobs; replay returns the stored execution test_policy_modes_and_provenance
Dependencies pinned (uv.lock, pnpm-lock.yaml), uv sync --frozen in deploy hook manifest hooks

# Residual risks and exceptions

  1. Unmanaged routes (host shell outside sandbox, Claude Code Bash, remote MCP servers) are outside the boundary. They are documented, hooks only advise, and anything not mediated is labelled unobserved and excluded from verified exports.
  2. Keychain trust domain: anyone with an SSH session as the app user on M4M64c can read the keychain. Same posture as the other apps on the cluster; mitigated by SSH key-only access and audit of credential use. A central vault (e.g. 1Password Connect) would be a drop-in replacement of akos/vault/keychain.py.
  3. Single application DB role can in principle modify data tables (not audit rows). A separate read-only role for exports is a possible hardening.
  4. In-process rate limiting resets on restart and is per process (one process today).
  5. TypeScript client typecheck depends on tsc from web/node_modules; blocked (not failed) when absent.
  6. pg_trgm/FTS search is lexical; no embedding model is used (deliberate: no external calls, deterministic).
Files · da58f809c01c422e65c786b05d6ffa3079c9feba
Menu

Theme