Security policy
Security Policy
cubby-network is an open-source NetOps control plane that, in production, holds credentials for real network devices and can change live network state. Vulnerability reports are taken seriously.
Reporting a vulnerability
Do not open a public GitHub issue for a security report. Instead:
- Use GitHub private security advisories: <https://github.com/cubby-network/platform/security/advisories/new>
- Include reproduction steps, the version / commit you tested, and the impact you believe the issue has.
- If the advisory flow is unavailable, contact the maintainers listed in
MAINTAINERS.mdand include[cubby-network security]in the subject or opening line. - We will acknowledge within 72 hours and aim to provide a remediation plan within 14 days for critical issues, 30 days for high severity.
Do not report vulnerabilities in Discord, public GitHub issues, pull requests, or community discussions.
When in doubt, report it. We would much rather see a non-issue than miss a real one.
Supported versions
Until the project reaches v1.0.0 we patch only the main branch. Once we cut a stable release, we will support the latest minor for security fixes.
Threat model summary
The harness is designed against the following classes of attack:
- Identity spoofing on the API. All routes require a validated bearer token. Request bodies cannot override
requested_by/actor_roles— seeapps/api/security.stamp_principal. - Tamper of audit evidence. Bundles are signed (HMAC-SHA256 by default, Ed25519 in production) and chained via
prev_sha256. Verify withapps/cli/verify_evidence.py. - Unauthorised / spoofed change approvals. Every medium- or high-risk change requires a quorum of cryptographically signed
SignedApprovalenvelopes evaluated against aChangeAdvisoryBoardchain. Signatures bind the approver to the canonical plan hash (canonical_plan_payload), so swapping the plan after sign-off fails verification. Approvals use a signer distinct from evidence — see the custody section below. - Credential leakage. Real credentials live in Vault dynamic secrets (
plugins/auth/vault_dynamic). Leases are scoped to the workflow and revoked on context exit. Credential bundles never enter evidence files. - Plugin contract drift. The registry rejects any plugin that does not inherit the right ABC or omits the
simulatedflag. - Agent escape. LLM-backed agents can only call read-only tools, only those listed in their per-role allow-list, and only via the runtime's
SafetyGate. Tools cannot be registered withoutread_only = True.
Things we explicitly do not protect against (yet)
- Compromise of the host running the harness. Treat the harness host the same way you'd treat a network management station: hardened, monitored, in a privileged management VLAN.
- Insider abuse with valid credentials and approval rights. Approval-chain enforcement and audit signing make abuse visible after the fact, but the harness is not a substitute for least-privilege role design.
Signing-key custody
The harness uses two distinct keys: one for evidence bundles, one for change approvals. They are intentionally separate so rotating or compromising one does not invalidate or forge the other.
Default custody (dev / demo): both keys are file-backed HMAC-SHA256 secrets auto-generated on first use under var/keys/ (0600 permissions, 32 random bytes). Deterministic across processes on the same host. Suitable for local development, CI, and single-operator demos — not production.
Production custody (recommended):
- Evidence signing — supply a strong secret via
NETOPS_EVIDENCE_HMAC_SECRET(orNETOPS_EVIDENCE_HMAC_KEY_PATH) managed by your secret store, or wireEd25519Signeragainst a Vault transit key. SetNETOPS_EVIDENCE_REQUIRE_CONFIGURED_KEY=1to disable the dev-key fallback and force explicit configuration. - Approval signing — HMAC is acceptable for single-tenant trust; configure via
NETOPS_APPROVAL_HMAC_SECRETorNETOPS_APPROVAL_HMAC_KEY_PATH. For multi-party trust, switch to per-approver Ed25519 keys: approver private keys live with the approver (HSM / YubiKey / Vault transit), only public keys are loaded into the server'sSignerKeyringat bootstrap. The server only verifies — it cannot forge.
The evidence_require_configured_key flag applies to both signers; one switch flips the whole harness into strict-keys mode.
Hardening checklist for production
NETOPS_API_AUTH_MODE=hmac(or OIDC, when wired) — neverdev.- Set
NETOPS_EVIDENCE_HMAC_SECRET(or key path) to a strong secret managed by your secret store, or wireEd25519Signeragainst a Vault transit key. - Set
NETOPS_APPROVAL_HMAC_SECRET(or key path) for single-tenant approvals, or load per-approver Ed25519 public keys into the harness's approval keyring at bootstrap. - Set
NETOPS_EVIDENCE_REQUIRE_CONFIGURED_KEY=1to disable the dev-key fallback for both signers. - Set
config.devices.iosxe.mode = "real"only when the Vault dynamic adapter is configured and the policy file has the right TTLs. - Run
verify_evidence.pyon a schedule and alert on any chain break. - Restrict the API behind a reverse proxy with mTLS where possible.