DOCS CANONICAL · GENERATED FROM REPO RELEASE v0.2.0-beta.1 SOURCE github.com/cubby-network/platform

Security policy

Security · Source: SECURITY.md

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:

  1. Use GitHub private security advisories: <https://github.com/cubby-network/platform/security/advisories/new>
  2. Include reproduction steps, the version / commit you tested, and the impact you believe the issue has.
  3. If the advisory flow is unavailable, contact the maintainers listed in MAINTAINERS.md and include [cubby-network security] in the subject or opening line.
  4. 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 — see apps/api/security.stamp_principal.
  • Tamper of audit evidence. Bundles are signed (HMAC-SHA256 by default, Ed25519 in production) and chained via prev_sha256. Verify with apps/cli/verify_evidence.py.
  • Unauthorised / spoofed change approvals. Every medium- or high-risk change requires a quorum of cryptographically signed SignedApproval envelopes evaluated against a ChangeAdvisoryBoard chain. 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 simulated flag.
  • 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 without read_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 (or NETOPS_EVIDENCE_HMAC_KEY_PATH) managed by your secret store, or wire Ed25519Signer against a Vault transit key. Set NETOPS_EVIDENCE_REQUIRE_CONFIGURED_KEY=1 to disable the dev-key fallback and force explicit configuration.
  • Approval signing — HMAC is acceptable for single-tenant trust; configure via NETOPS_APPROVAL_HMAC_SECRET or NETOPS_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's SignerKeyring at 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) — never dev.
  • Set NETOPS_EVIDENCE_HMAC_SECRET (or key path) to a strong secret managed by your secret store, or wire Ed25519Signer against 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=1 to 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.py on a schedule and alert on any chain break.
  • Restrict the API behind a reverse proxy with mTLS where possible.