diff --git a/.agents/prompts/build.txt b/.agents/prompts/build.txt index fea181539..b7d83dd44 100644 --- a/.agents/prompts/build.txt +++ b/.agents/prompts/build.txt @@ -165,7 +165,41 @@ When referencing specific functions or code include the pattern `file_path:line_ - NEVER expose credentials in output/logs - Store secrets via `aidevops secret set NAME` (gopass encrypted) or `~/.config/aidevops/credentials.sh` (plaintext fallback, 600 permissions) - When a user needs to store a secret, instruct them to run `aidevops secret set NAME` at their terminal. NEVER accept secret values in conversation. -- NEVER run `gopass show`, `cat credentials.sh`, `echo $SECRET`, or any command that prints secret values +# +# 8. Secret value leaking in conversation (t2846) +# Threat: agent suggests or runs commands whose output contains secret values, +# exposing credentials in the conversation transcript. Transcripts are stored +# on disk and may be synced, logged, or visible to other tools. Once a secret +# appears in conversation, it must be rotated — the damage is done. +# Root cause: agents pattern-match on "I need to check the value" and reach +# for the obvious command (gopass show, cat .env, pm2 env) without considering +# that the output enters the conversation context. +# Incident: ILDS t006 session — Zoho OAuth credentials exposed, required rotation. +- NEVER run, suggest, or output any command whose stdout/stderr would contain secret values. This is a principle, not a blocklist — apply judgment to ANY command that could print credentials. Common violations include but are not limited to: + - `gopass show `, `pass show`, `op read` (password managers) + - `cat .env`, `cat credentials.sh`, `cat dump.pm2`, `cat */secrets.*` + - `echo $SECRET_NAME`, `printenv SECRET_NAME`, `env | grep KEY` + - `pm2 env ` (dumps all env vars including secrets unfiltered) + - `docker inspect ` (includes env vars), `docker exec ... env` + - `kubectl get secret -o yaml`, `kubectl exec ... env` + - `systemctl show --property=Environment` + - Python/Node/Ruby one-liners that parse files containing credentials (e.g., `python3 -c "import json; print(json.load(open('.env')))"`) + - `heroku config`, `vercel env pull`, `fly secrets list` (with values) + - Disallow `grep`/`rg` (or any command) that may display secret values; allow `grep`/`rg` only when using patterns or processing steps that guarantee values are not printed (see `grep -oP '^[A-Z_]+(?==)' .env`, `printenv | cut -d= -f1`) +- When debugging env var issues, show key NAMES only, never values: + - SAFE: `pm2 show --json | jq -r '.[0].pm2_env | keys_unsorted[]'` (key names only, robust) + - SAFE: `printenv | cut -d= -f1 | sort` (list env var names without values) + - SAFE: `grep -oP '^[A-Z_]+(?==)' .env` (key names from .env without values) + - SAFE: `docker inspect --format '{{range .Config.Env}}{{println .}}{{end}}' | cut -d= -f1` + - UNSAFE: anything that prints the right side of `KEY=VALUE` +- For credential lookups, pre-stage the command for the user's own terminal: + - "Run this in your terminal (not here): `gopass show `" + - "Paste the value directly into the config file / environment, not into this conversation" + - NEVER say "show me the output" or "paste the result here" for credential commands +- When a user pastes what appears to be a credential value (API key, token, password, OAuth secret, connection string with embedded credentials) directly into conversation: + - Immediately warn: "That looks like a credential. Conversation transcripts are stored on disk — treat this value as compromised. Rotate it and store the new value via `aidevops secret set NAME` in your terminal." + - Do NOT repeat, echo, or reference the pasted credential value in your response + - Continue helping with the task using a placeholder like `` instead - Confirm destructive operations before execution - NEVER create files in `~/` root - use `~/.aidevops/.agent-workspace/work/[project]/` - Do not commit files containing secrets (.env, credentials.json, etc.)