89 lines
4.6 KiB
Markdown
89 lines
4.6 KiB
Markdown
|
|
---
|
||
|
|
type: plan
|
||
|
|
title: "credvault — OS isolation, backup, and recovery plan"
|
||
|
|
summary: "Security, backup, and recovery plan for credvault — deter-and-detect posture: hook-based guardrails, human-owned scheduled encrypted exports, bot-compromise/rotation runbook; OS isolation kept as a documented future hardening option."
|
||
|
|
tags:
|
||
|
|
- type/plan
|
||
|
|
- project/credvault
|
||
|
|
- tool/vaultwarden
|
||
|
|
- domain/credential-management
|
||
|
|
- domain/security
|
||
|
|
scope: project
|
||
|
|
date: 2026-07-09
|
||
|
|
last_updated: 2026-07-09
|
||
|
|
related:
|
||
|
|
- credvault-integration-master-plan
|
||
|
|
- credvault-vaultwarden-setup-plan
|
||
|
|
source: ruby-gems
|
||
|
|
---
|
||
|
|
|
||
|
|
# credvault — Security, Backup & Recovery Plan
|
||
|
|
|
||
|
|
## Posture (decided 2026-07-09): deter and detect, not prevent
|
||
|
|
|
||
|
|
Claude's Bash runs as the same OS user, so hooks and gem surface are advisory — a determined
|
||
|
|
bypass could read auth files or hit the Vaultwarden API directly. Accepted trade-off, because:
|
||
|
|
|
||
|
|
- **Blast radius is bounded by the collection**: the bot sees only `AI Managed Credentials`
|
||
|
|
(rotatable infra creds — n8n, Grafana, Portainer, etc.), never the human's personal vault.
|
||
|
|
- **Deletion is recoverable**: Vaultwarden trash (no auto-purge by default) + human-owned export.
|
||
|
|
- **Exfiltration is remediable**: rotation runbook (§3) — annoying but bounded, and largely
|
||
|
|
automatable with credvault itself.
|
||
|
|
|
||
|
|
## 1. Guardrails (v1)
|
||
|
|
|
||
|
|
- Auth material mode-600 under the user: bot master-password file, BW_CLIENTID/BW_CLIENTSECRET
|
||
|
|
env file, `~/.config/credvault/` (config + `BITWARDENCLI_APPDATA_DIR`), audit log dir.
|
||
|
|
- Plugin PreToolUse hooks (see [[credvault-cc-plugin-plan]]) block: raw `bw`/`bws`; Read/Bash
|
||
|
|
access to credvault auth/config paths; obvious env-dumping of credential values
|
||
|
|
(`echo $..._PASSWORD`, `env | grep`, `cat` of the password file) — with a reminder message
|
||
|
|
that agents must not inspect credentials directly.
|
||
|
|
- Skill instructions: credentials are accessed only through credvault; never read auth files.
|
||
|
|
- Audit log (every `get` recorded, gem-enforced) is the detection layer — review it when
|
||
|
|
anything looks off.
|
||
|
|
|
||
|
|
## 1a. Future hardening option (not v1): OS isolation
|
||
|
|
|
||
|
|
If the threat model changes (multi-user host, higher-value credentials in the collection),
|
||
|
|
the stronger design is a dedicated `bitwarden-agent` Linux user owning all auth material,
|
||
|
|
with `jared ALL=(bitwarden-agent) NOPASSWD: /usr/local/bin/credvault` as the sole sudoers
|
||
|
|
entry — making the gem surface enforced rather than advisory. Design retained here; ~20 min
|
||
|
|
of setup; red-team check: from Claude's user, cat the password file / run `bw` / read
|
||
|
|
appdata must all fail.
|
||
|
|
|
||
|
|
## 2. Backups (independent of the bot)
|
||
|
|
|
||
|
|
- Keep the existing daily Vaultwarden server backup (baseline).
|
||
|
|
- Add a scheduled encrypted org export (encrypted JSON) running under the **human's**
|
||
|
|
account credentials on a machine/account the AI has no access to (e.g. OVH cron similar to
|
||
|
|
the planka tick/digest pattern), shipped off-host. Principle: recovery must not depend on
|
||
|
|
the actor whose mistakes it recovers from.
|
||
|
|
- No per-operation backup gates (creates are non-destructive; explicit rejection of the
|
||
|
|
original backup-before-every-CUD idea stands).
|
||
|
|
- Vaultwarden trash: no auto-purge unless `TRASH_AUTO_DELETE_DAYS` set — deleted items are
|
||
|
|
recoverable from trash by the human; password history gives limited rotation rollback
|
||
|
|
(verify per Phase 0).
|
||
|
|
|
||
|
|
## 3. Bot-compromise runbook (written before go-live)
|
||
|
|
|
||
|
|
If the bot API key / master-password file / host is suspected compromised:
|
||
|
|
1. Web vault (human): remove bot from the organization (cuts collection access immediately).
|
||
|
|
2. Regenerate/rotate the bot's API key; reset its master password.
|
||
|
|
3. Audit `AI Managed Credentials` against the latest independent export — the bot CAN delete
|
||
|
|
and edit items, so diff for missing/modified entries.
|
||
|
|
4. Rotate any credentials the bot could read (all items in the collection) on the affected
|
||
|
|
services, worst-case.
|
||
|
|
5. Rebuild the bot auth files on the host; re-run Phase 0 CLI auth proof.
|
||
|
|
|
||
|
|
## 4. Residual risks (accepted, documented)
|
||
|
|
|
||
|
|
- Bot can delete within its collection (no server-side control exists in Vaultwarden) —
|
||
|
|
mitigated by wrapper + hooks + trash + independent export.
|
||
|
|
- Hooks/gem surface are advisory: an agent bypassing them could read bot auth material and
|
||
|
|
act directly against Vaultwarden — accepted because blast radius = one rotatable
|
||
|
|
collection; remedy is the rotation runbook; escalation path is §1a OS isolation.
|
||
|
|
- Prompt injection can still ask for keys the current task legitimately uses — mitigated by
|
||
|
|
audited `get`, skill hygiene rules, and (post-MVP) `ensure_and_inject` so secrets stop
|
||
|
|
returning to the model at all.
|
||
|
|
- Cross-host duplicate creation races — detected via `duplicate_managed_key`, human cleanup.
|