Skip to content

Security: postrv/sanctum-oss

Security

docs/SECURITY.md

Security Policy

Supported versions

Version Supported
0.3.x Current
0.2.x Supported
0.1.x Supported

Reporting a vulnerability

Do not open a public GitHub issue for security vulnerabilities.

Instead, please report vulnerabilities via one of:

  1. GitHub Private Advisory: Create a private advisory on this repository.

What to include

  • Description of the vulnerability
  • Steps to reproduce
  • Potential impact
  • Suggested fix (if you have one)

Response timeline

  • Acknowledgement: Within 48 hours
  • Initial assessment: Within 5 business days
  • Fix timeline: Depends on severity
    • Critical: patch within 72 hours
    • High: patch within 7 days
    • Medium/Low: next scheduled release

Disclosure policy

We follow coordinated disclosure. We will:

  1. Confirm the vulnerability and determine its scope
  2. Develop and test a fix
  3. Release the fix and publish a security advisory
  4. Credit the reporter (unless they prefer anonymity)

We ask that you give us reasonable time to address the issue before public disclosure.

Security considerations

Sanctum is a security tool with elevated filesystem access. We take its own security extremely seriously:

Code quality

  • Zero unsafe code in the entire codebase
  • No unwrap/expect/panic outside test code (enforced by workspace-level clippy lints)
  • Zero clippy warnings across ~1,800 tests
  • Rust toolchain pinned to 1.94.0 via rust-toolchain.toml for reproducible builds

Dependency management

  • cargo-deny enforced via deny.toml:
    • Known vulnerabilities denied
    • Yanked crates denied
    • Only permissive licenses allowed (MIT, Apache-2.0, BSD-3-Clause, ISC, Unicode-3.0, CC0-1.0)
    • Copyleft dependencies denied
    • Multiple versions of the same crate warned
    • C system dependencies (openssl-sys, libz-sys) explicitly banned -- pure Rust only
    • Only crates.io registry allowed; unknown registries and git sources denied
  • All dependencies audited and documented in docs/DEPENDENCY_AUDIT.md

Runtime security

  • Race-free PID file creation using O_CREAT | O_EXCL semantics (create_new(true)) to prevent TOCTOU races between checking for an existing daemon and starting a new one
  • AppleScript injection prevention in macOS notifications -- all user-controlled strings are sanitized before embedding in AppleScript literals to prevent code injection via osascript
  • IPC messages capped at 64KB (MAX_MESSAGE_SIZE) -- both read and write paths enforce the limit before allocating payload buffers
  • Unix socket permissions set to 0o600 -- only the owning user can connect to the daemon
  • Audit log with 0o600 permissions -- append-only NDJSON format; audit logging failures are logged but never crash the daemon
  • Budget state files persisted with 0o600 permissions

CEL policy evaluation

  • Non-Turing-complete: CEL expressions used in [[ai_firewall.mcp_cel_rules]] are guaranteed to terminate -- the language has no loops or recursion
  • No side effects: CEL evaluation is pure; expressions cannot perform I/O, modify state, or access the filesystem
  • Sandboxed context: Only three variables are exposed to expressions: tool_name (string), paths (list of strings), payload_size (int)

Testing

  • ~1,800 tests covering all eight workspace crates (unit, integration, E2E, loom concurrency)
  • Fuzz testing targets for security-critical parsers (PTH file analyser, config parser) in fuzz/fuzz_targets/
  • 9 property-based tests using proptest (6 sentinel + 3 budget) that verify invariants such as analyser totality, determinism, quarantine roundtrip identity, pricing overflow safety, and spend monotonicity
  • 9 Kani bounded model checking proofs for core algorithms (analyser panic-freedom, path classification, exec detection, quarantine state machine, ID traversal rejection, ceiling cost overflow, Shannon entropy panic-freedom, glob exact-match correctness, exfiltration counter overflow safety) -- integrated as #[cfg(kani)] modules with CI enforcement

Binary verification

Release binaries are signed with Sigstore using keyless OIDC signing via GitHub Actions. Each release includes .sig (signature) and .cert (certificate) files alongside the binaries, plus a signed SHA256SUMS file and a signed CycloneDX SBOM.

Verify a binary:

cosign verify-blob \
  --signature sanctum-x86_64-unknown-linux-gnu.sig \
  --certificate sanctum-x86_64-unknown-linux-gnu.cert \
  --certificate-identity-regexp "^https://github\\.com/postrv/sanctum-oss/" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  sanctum-x86_64-unknown-linux-gnu

Verify the checksums file:

cosign verify-blob \
  --signature SHA256SUMS.sig \
  --certificate SHA256SUMS.cert \
  --certificate-identity-regexp "^https://github\\.com/postrv/sanctum-oss/" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  SHA256SUMS
sha256sum -c SHA256SUMS

Checksum-only installs

When installing via scripts/install.sh without cosign available, binaries are verified using SHA-256 checksums only. This protects against download corruption and CDN-level tampering, but not against a compromised GitHub release where an attacker replaces both the binary and the SHA256SUMS file.

For production environments, we recommend installing cosign and enabling full Sigstore verification.

No private signing keys exist. The signing identity is the GitHub Actions release workflow itself, verified via Fulcio certificate and logged to the Rekor transparency log.

There aren’t any published security advisories