Security model
Technical deep dive: encryption, fail-closed Shield, canary tokens, and audit findings — for teams evaluating Prune.
Quick answer
Prune protects provider API keys with AES-256-GCM encryption for vaulted provider API keys and key separation in the vault. Shield spend caps and rate limits run before every upstream call and fail closed — if policy cannot be verified, the request is blocked, not passed through.
AES-256-GCM vault encryption with key separation
When you store an OpenAI or Anthropic key in the Prune vault, we encrypt it with AES-256-GCM before writing to the database.
Key separation means the key that encrypts your provider credentials is not stored next to the ciphertext. The master key lives in a separate secrets manager; the database holds only encrypted blobs and metadata. A database-only breach does not expose plaintext API keys.
Prune API keys (prune_…) are never stored in recoverable form — only SHA-256 hashes, so a leak cannot be replayed.
Fail-closed Shield
Shield enforces rate limits, daily spend caps, model allowlists, and IP restrictions on every proxied request. Enforcement uses Redis-backed counters with atomic operations to prevent spend-cap race conditions.
Fail closed means: if Shield cannot load your policy (database timeout, Redis unavailable), the request returns an error — it does not bypass caps and call the provider. Spend caps enforced in under 10ms, before the provider call
Rejected requests include X-Prune-Shield-Code so your app can distinguish spend caps from auth failures.
Canary token injection (OWASP LLM07:2025)
Optional per-request canary tokens are embedded in system context. If the model echoes the canary in its output, Prune flags a possible system-prompt leakage event. Enable with X-Prune-Shield-Canary: true; block responses with X-Prune-Shield-Canary-Block: true.
Receipt fields: shield_canary_injected, shield_canary_leaked.
PII tokenization
When enabled, emails, phone numbers, and names are replaced with reversible placeholders before the request leaves Prune for the upstream provider. The model never sees raw PII; your app can detokenize responses if needed.
Spend cap race condition fix
Daily spend tracking uses atomic Redis INCRBYFLOAT operations so concurrent requests cannot overshoot a cap between read and write. Caps are checked before the upstream LLM call fires.
Pre-beta security audit
Before private beta, we ran an adversarial security pass across proxy routes, vault handling, and Shield enforcement. Findings included:
- Pre-beta audit: 4 of 6 routes had Shield gaps — all fixed before private beta
- Invalid Prune keys rejected before any upstream LLM call
- Monthly plan limits fail closed in production on database errors
- Constant-time API key hash verification
- Provider keys excluded from logs and error responses
All identified Shield gaps were closed before beta users were onboarded. Report vulnerabilities to security@withprune.com.