If you find a security issue in OperatorBoard, please do not open a public GitHub issue.
Email: blackboxinfo@proton.me
Response target: 48 hours
Include:
- A description of the issue and its potential impact
- Steps to reproduce or a proof of concept
- Any suggested remediation if you have one
We will acknowledge receipt, keep you informed as we investigate, and credit you in the changelog if you'd like.
| Version | Supported |
|---|---|
main branch |
✅ Active |
| Tagged releases | ✅ Patch fixes backported where feasible |
OperatorBoard is built around a specific threat model: the agent is untrusted, the operator is fallible under pressure, and defaults should be safe without additional configuration.
Current trust boundaries:
- Every agent action is validated against per-agent constraints before it is acted on
- Destructive database actions require independently-attested backup evidence, not just agent claims
- Network access, file write, and shell execution are off by default — agents must be explicitly granted each capability
- Replay protection is enforced on all signed integration endpoints
- Blocked actions cannot be approved — there is no override path at the approval UI
- Direct database shell access is blocked as a policy bypass, regardless of shell permission settings
- When
OPERATORBOARD_API_KEYis set, all routes exceptOPTIONSpre-flight and/healthrequire that key; running without a configured key is explicitly warned at startup and every unauthenticated request is audited — but the API will serve unauthenticated traffic if the env var is unset. Set the key in production.
The dashboard communicates with the Fastify API through a server-side Next.js
proxy route (apps/web/src/app/api/[...proxy]/route.ts). The proxy runs in
the Node.js process, never in the browser.
- What this means for operators: set
OPERATORBOARD_API_KEY(noNEXT_PUBLIC_prefix) on the web container. The key is read by the proxy at request time and injected into upstream calls. It does not appear in the Next.js bundle, browser DevTools, or network requests from the client. - What this means for agent SDK authors: the API is still a plain Fastify
HTTP server. Agent SDKs communicate directly with the API (port 4100) using
X-Operatorboard-Key. The proxy is only for the browser dashboard.
These are documented, intentional trade-offs in the current version — not undisclosed vulnerabilities:
Manual backup attestations are operator-controlled.
An operator can post a backup attestation with any timestamp. The system records the claim but does not independently verify the backup exists. Automated integrations via POST /backup-attestations/integrations/:provider provide stronger guarantees and should be preferred in production.
Agent-supplied risk metadata is presented as context, not fact.
Fields such as plainLanguage, estimatedAffectedRows, and backupReference in a proposed action are provided by the agent and displayed to the operator for decision context. They are not independently verified by OperatorBoard. Treat them as agent claims.
Cost reporting is agent-self-reported.
costUsd in a task response is added to the agent's running total without cross-verification. Budget enforcement is as reliable as the agent's honesty about its own spend.
Webhook URL validation blocks known private ranges by pattern. The SSRF guard blocks RFC-1918 ranges, localhost, link-local, and common cloud metadata addresses. It does not perform DNS resolution to catch hostnames that resolve to private IPs at request time.
Before running OperatorBoard in a production environment:
API service (apps/api)
- Set
OPERATORBOARD_API_KEYto a strong random secret (openssl rand -hex 32) - Set
OPERATORBOARD_CORS_ORIGINSto your dashboard's public URL (e.g.https://board.example.com). If unset in production, all cross-origin requests are blocked with a startup warning. - Set
OPERATORBOARD_ENABLE_DEV_ROUTES=false(default in Docker) - Configure
OPERATORBOARD_BACKUP_INTEGRATION_SECRETSwith provider-specific secrets - Set
OPERATORBOARD_SEED=falsein production (default)
Web service (apps/web)
- Set
OPERATORBOARD_API_KEYto the same value as the API service — noNEXT_PUBLIC_prefix (read by the server-side proxy, never sent to the browser) - Set
OPERATORBOARD_API_URLto the internal URL the web container uses to reach the API (e.g.http://api:4100in Docker, or your internal VPC DNS name) - Do not set
NEXT_PUBLIC_OPERATORBOARD_API_KEY— this env var was removed in v0.2.0
Infrastructure
- Run behind Caddy or equivalent TLS-terminating reverse proxy
- Review the included
Caddyfile— do not use theOPERATORBOARD_DOMAINdefault in production - Review agent
webhookUrlandendpointvalues — only HTTPS endpoints on known-public hosts are permitted - Review
databasePolicysettings for any agent withwrite_destructiveaccess - Enable backup attestation integrations for any agent performing destructive DB operations
OperatorBoard monitors security advisories for its core dependencies:
fastifyand@fastify/corsnextand Reactbetter-sqlite3zod
Dependencies use ^ range specifiers pinned in pnpm-lock.yaml. Update the lockfile and re-run pnpm -r typecheck && pnpm test after any dependency bump.