Security model
Bunfork reduces the runtime and fails closed at file, schema, route, and input boundaries. It cannot replace host isolation, TLS, identity, or operational discipline.
Production checklist
- Firewall port 3100.The default
0.0.0.0:3100listener is intentionally LAN-visible. - Terminate TLS at a trusted reverse proxy.Bunfork has no built-in TLS and should not face the public internet directly.
- Set the public HTTPS origin.Use
BUNFORK_PUBLIC_ORIGIN=https://app.example.comso browser mutations must match it. - Separate the database key and API token.Generate each independently and keep both readable only by the service account.
- Keep state outside releases.Never place keys, tokens, databases, or backups under
app/pages,public, or the deployment directory. - Back up the key separately.Database backups remain encrypted with the live database key.
- Stop writers before restore.Restore is a verified offline operation, not a distributed transaction.
Secret handling
keygencreates a 256-bit random value in a private file.- Secret files must not be accessible by group or others.
- File values take precedence over environment values.
- Decoded secret comparisons are constant-time, including the key/token inequality check.
- The explicit frontend build environment excludes
BUNFORK_DB_KEYandBUNFORK_API_TOKEN. - Page trees reject hidden entries, links, and special files; public assets reject sensitive paths; deploy inventory rejects recognized secret patterns.
Request boundary
| Surface | Control |
|---|---|
| Vector API | Bearer authentication; constant-time token comparison |
| Browser mutations | Origin must equal the configured public origin or current host |
| Request bodies | 1 MiB cap plus vector-specific validation and work budgets |
| Native pages | Auto-escaped template values and bounded multi-value query parsing |
| Hidden request paths | Rejected before routing |
| Health/readiness | Public and GET-only by design |
Response headers
Native responses set a self-only content security policy, deny framing, disable MIME sniffing, use a no-referrer policy, and disable camera, geolocation, and microphone access.
Static exports need same-origin browser code and may contain framework bootstrap inline scripts or styles. Bunfork's static policy permits those official export patterns. For a narrower policy, configure build-specific hashes or nonces at the trusted reverse proxy.
File and artifact boundary
Native routes, templates, and public assets reject hidden entries, links, hard links, special files, ambiguous routes, and unsafe paths. Production compiles routes and preloads assets before binding.
Static admission additionally records every byte length and digest in a strict manifest. Verification happens offline with doctor and again before the static server binds.
The smallest security surface
If an application only needs compiled browser files, use static mode. It does not open the database or require a key, token, tenant, model, migration, native template engine, or foreign server runtime.
./target/release/bunfork doctor \
--static frontend/out \
--manifest bunfork-static.json
./target/release/bunfork serve \
--static frontend/out \
--manifest bunfork-static.json