If you discover a security vulnerability in nbox, please report it responsibly:
- Do not open a public GitHub issue
- Email lance@lance0.com or use GitHub's private vulnerability reporting
- Include steps to reproduce the issue
- Allow reasonable time for a fix before public disclosure
Security issues of interest include:
- Leakage of the NetBox API token (in logs, error messages, or output)
- TLS verification bypass or weakening
- Memory-safety issues in API response parsing
- An unintended write, or a write that bypasses the configured write gate and plan/confirmation lifecycle (ADR-0001/0002)
- Token storage. nbox resolves the API token in order: the env var named by the profile's
token_env, thenNBOX_TOKEN, then the profile'stokenvalue inconfig.toml. There is no OS keyring. If you prefer to keep the token out of the config file, usetoken_env/NBOX_TOKENand store only the env-var name in the file. When a token is saved toconfig.toml, the file is written owner-only (0600on Unix) and the value is redacted fromconfig show/--json/Debug. The token is never logged — request logging shows only the auth-scheme marker. Inspect the active source withnbox config token status(never prints the value). - Read-first. Reads are the default everywhere. Writes are a small set of safe, opt-in commands, each gated by
--allow-writesAND confirmation (--confirm, or a TTY prompt), with an explicit--dry-runpreview (ADR-0001). Therawcommand staysGET-only. Use a read-scoped NetBox token for defense in depth, and grant write scope only where you mean to allow the gated writes. - TLS verified by default.
verify_tls = falseis supported for labs with self-signed certs but must not be used against production. - Clean stdout. Data goes to stdout; logs and errors go to stderr — safe for piping and for the
nbox serveJSON-RPC stream.
nbox serve exposes the read-only tools to an MCP client by default. The two write tools (nbox_plan_write / nbox_apply_write) stay opt-in:
- local stdio writes require
[serve].local_writes = trueor--local-writesand use the active profile token under the MCP host's local approval prompt; - shared HTTP/OIDC writes require
[serve].allow_writes = trueor--allow-writes, callernbox:write, and a[serve.vault]entry mapping the caller's OIDCsubto a per-user NetBox token; - HTTP/static-bearer profile-token writes are rejected.
Its network surface:
- stdio by default — no network listener; the host launches nbox as a subprocess.
- HTTP is loopback-only unless OIDC is configured.
nbox serve --http <addr>binds loopback and validatesOrigin/Host(a DNS-rebinding guard). An optional static bearer (--http-token/NBOX_SERVE_TOKEN— a secret; prefer the env var) gates/mcp. - A routable deployment is an OAuth 2.1 resource server. A non-loopback bind requires
--oidc-issuer+--audience: nbox validates inbound IdP JWTs on/mcp(signature via JWKS;iss/aud/expchecked;alg: nonerejected) and advertises Protected Resource Metadata (RFC 9728). Terminate TLS in front (a reverse proxy). - Accountability, not per-user RBAC for reads. Reads use the single profile token, so scope that token read-only for shared deployments. Shared HTTP writes execute under a per-user vault identity keyed by the caller's OIDC
sub. Local stdio writes are a single-user exception: they use the active profile token only when--local-writes/[serve].local_writesis explicitly set. An audit log (nbox::audit) records callers, and an optional per-caller rate limit (--rate-limit) bounds abuse.
See docs/MCP.md for the full security model.
Only the latest release receives security updates. Upgrade to the most recent version before reporting a vulnerability.