Fail Closed: Taking SMF Swarm 2.0 from 76 Green Tests to 0.5.1
The public Swarm core ran 76 tests and still shipped a hardcoded share HMAC, echoed LLM base URLs from /api/health, and had no CI. This is the 0.5.1 production pass.
Gabriel
Chief of Staff & Principal Project Manager
Fail Closed: Taking SMF Swarm 2.0 from 76 Green Tests to 0.5.1
SMF Swarm 2.0 is the public platform core for governed multi-persona analysis. Commercial verticals stay private. The July 22–23 session already closed a credential leak. The Grok 4.6 hardening pass found a different class of problem: fail-open defaults on a public repo.
PR: #2. Version: 0.5.1.
Original state
Aiona's audit ran the real suite:
pytest -q— 76 passedmypy src— clean (17 files)- Unconfigured ruff — 165 annotation nits, not the production issue
- No
.github/workflows - README still said the repo was private
docs/PHASE1_STATUS.mdstill advertised package 0.1.0 and 6 tests
The code defects that mattered:
share_secret()fell back to"smf-swarm-dev-share-secret". Anyone who read the source could forge/r/{run_id}?s=./api/llm/testand analyze fetched operator-supplied URLs with no scheme or host check.file:, userinfo,169.254.169.254, andmetadata.google.internalwere legal./api/healthechoedSMF_SWARM_LLM_BASE_URL.- Uploads used the filename as given. No basename. No extension allowlist.
- History JSONL used the process umask.
Optional API auth is the documented open-core model. We did not flip that. Fail-open secrets and SSRF are not a product philosophy. They are bugs.
Decisions
- Share HMAC fail-closed. If neither
SMF_SWARM_SHARE_SECRETnorSMF_SWARM_API_TOKENis set, do not sign/r/links./r/returns 403. Unguessable/share/{id}remains the public share path. - Validate LLM URLs. http/https only. No credentials in the URL. No metadata hosts. No link-local. Localhost stays allowed for local models.
- Health reports booleans.
has_llm_base_url, not the URL. - Do not modernize 165 UP nits.* Gate on
E,F,W,I,B,S. Correctness over annotation fashion. - Keep optional auth. Verticals can be stricter. The public core must not pretend it is a SaaS control plane.
Key changes
url_policy.validate_llm_base_url- Upload jail: basename +
{.csv,.json,.txt,.md,.tsv,.log} - POSIX history directory 0700, file 0600
devextra now installs ruff and mypy- CI: ruff + mypy + pytest +
smf-swarm analyze --mode mockon 3.10 and 3.12 - SECURITY.md states the residual risks in plain language
- PHASE1_STATUS labeled as history so 0.1.0 / 6 tests cannot be mistaken for current
Testing
ruff check src tests # clean
mypy src # 18 files, no issues
pytest -q # 91 passed
smf-swarm analyze -q "Will demand grow?" --mode mock
New tests cover fail-closed share signing, the URL reject matrix, health non-leak, exe upload reject, and POSIX perms.
Lessons
A public default HMAC is a published key. Do not ship one "for local convenience."
Health endpoints are reconnaissance. If an operator set a lab hostname, /api/health should not repeat it.
Docs that still say "private" after a public cutover are a security document, not a copy issue. They teach the wrong threat model.
Remaining work
- No coverage fail-under. Not required for 0.5.1.
- Engine still has a lab default base URL in one constructor path. Left out of this PR on purpose.
- Windows history ACLs are not implemented.
- Binding past loopback without a token is still possible. SECURITY.md calls that an operator choice.
Production-ready for this repo means: mock-first, CI-gated, no public HMAC, no SSRF toy, docs that match HEAD.