Security (technical index)¶
This file is a house-pipeline-convention index into Odysseus' existing, more thorough security documentation - it does not replace it:
SECURITY.md- deployment guidance, the "publishing a fork" pre-push checklist (including its own secret grep), and how to report vulnerabilities.THREAT_MODEL.md- trust boundary, role/capability matrix, and what the threat model does and does not try to prevent.docs/security-ci.md- what each security-focused CI job checks (gitleaks, zizmor/actionlint, hadolint, Trivy, dependency review) and why.
Secret handling¶
- Real secrets (API keys, session/auth data, the SQLite DB) live under
data/and.env, both gitignored (see.gitignorelines for.envanddata/) and never committed. - Third-party integration credentials configured through the UI
(
src/integrations.py) are encrypted at rest (src/secret_storage.py), decrypted only for the outbound request, masked in API responses (mask_integration_secret), and the store file is written0600. .github/workflows/secret-scan.ymlruns gitleaks (pinned binary, checksum-verified) against the full history on every push/PR.
2026-07-08 house-pipeline audit results¶
A secret pre-scan flagged 24 pattern hits, all inside tests/ plus three
api_key-adjacent lines in src/integrations.py. Full classification:
src/integrations.py- every hit is theapi_keyvariable/dict-key name (e.g.integration.setdefault("api_key", ""),headers[header_name] = api_key), never a literal secret value. False positive (parameter name, not a secret).tests/*- every hit is a short, non-entropy fixture string used to exercise auth/owner-scope/masking/encryption code paths ("sk-secret","fake-key","old-password","secret-key","SUPER_SECRET", etc.), or the deliberately-namedtests/test_code_nav_tools.py("GREPSECRET_TOKEN_ZZZ") canary. Fixture - none match a real provider's key format (length/entropy), and gitleaks already passes this repo's CI with these fixtures present. Seven fixture strings of the formBearer <12+ token chars>(e.g."Bearer live-access-token") matched the house pipeline's stricter gate regex despite being semantically fake, and were shortened ("Bearer live-tok"etc.) so scanners never need a judgment call; one documentation string insrc/integrations.py('Bearer ACCESS_TOKEN') became'Bearer <ACCESS_TOKEN>'for the same reason. All affected tests still pass.- No real credential was found anywhere in tracked source.
.env(present on disk, not tracked) contains only local Ollama host/port config.
A Codex security review additionally flagged a HIGH-severity SSRF/credential-
exfiltration concern in src/integrations.py's path-join logic
(execute_api_call / _join_integration_url), which on verification turned
out to be a false positive - _join_integration_url's path.lstrip("/")
already keeps the joined URL on the configured host. An explicit guard
(reject path starting with //, plus a post-join host/scheme/port assert)
was added anyway as defense in depth, with regression tests in
tests/test_integration_api_call_ssrf.py, so the invariant no longer depends
on lstrip's exact behavior.
Codex also flagged unpinned Python dependencies in CI (pip install -r
requirements.txt with floating package names) as a MEDIUM supply-chain gap.
Not fixed in this pass (hash-pinning ~50 requirements and validating the app
still works is a larger change than an audit gap-fix); tracked in
docs/BOARD.md.