6.1 KiB
6.1 KiB
Secret rotation plan — 2026-11-11
Why: the compromised GIMP container had /home/sam mounted read-only for 5 days
(2026-11-06 → 2026-11-11) and ran as uid 1000 (sam). Everything below was readable,
and LMMS additionally had a reverse shell giving arbitrary command execution as root inside
a container with a write mount into /home/sam/Docker/Containers/music.
Treat every credential listed here as compromised. See incident-2026-11-11.md.
Exposure inventory (what was readable)
| Store | Contents | Volume |
|---|---|---|
~/.ssh/id_ed25519, id_ed25519_rsync, id_ed25519_school_scan |
3 private keys | full host/remote access |
~/.config/environment.d/10-secrets.conf |
47 keys (API keys, tokens, passwords) | see table below |
…10-secrets.conf.bak* |
12 historical copies — old AND current secrets | doubles the exposure |
~/.aws-credentials.local |
AWS access keys | cloud billing |
~/.secrets (1.5 KB) |
misc credentials | varies |
~/.gemini/mcp-oauth-tokens-v2.json |
OAuth tokens | Google account scope |
~/.npmrc |
npm registry token | supply-chain publish risk |
20 .env files (~200 keys total) |
per-project service secrets | see counts below |
Largest .env files: sams-home-network (43 keys), wherewoof-admin (28), voice-agent (21),
family-home-lab (19), langfuse (14), outline (12).
Priority 1 — rotate TODAY (direct access or money)
| Credential | Why urgent | Rotate where | Then |
|---|---|---|---|
id_ed25519, id_ed25519_rsync, id_ed25519_school_scan |
Attacker can SSH as you | ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_new; remove old pubkeys from authorized_keys on every target |
Update .ssh/config, rsync targets, school-scan host |
GITHUB_TOKEN |
Code push/steal, supply chain | github.com → Settings → Developer settings → Tokens | gh auth login to refresh |
GITEA_TOKEN |
Same, self-hosted repos | Gitea → Settings → Applications → regenerate | update 10-secrets.conf |
HUB_TOKEN_ADMIN, HUB_TOKEN_DSH, HUB_TOKEN_CONSOLE, HUB_TOKEN_PHONE, HUB_TOKEN_ESP32, HUB_PROJECT_*_TOKEN |
Full control of your hub/API layer | hub admin UI → revoke + reissue per client | update ESP32 firmware + phone config |
SC_TOKEN |
Service-controller = start/stop anything | regenerate in 10-secrets.conf |
also family-home-lab/.env, restart controller |
OPENROUTER_API_KEY, OPENAI_API_KEY, DEEPSEEK_API_KEY, GEMINI_API_KEY, MOONSHOT_API_KEY, MINIMAX_API_KEY (+_GROUP_ID,_SUBSCRIPTION_KEY), OPENCODE_API_KEY, TOKENROUTER_API_KEY, OMNIROUTE_API_KEY, STITCH_API_KEY, JEV_API_KEY, MOUSE_API_KEY, OL_API_KEY, TYPESAFE_API_KEY, TAVILY_API_KEY |
Billing — check usage dashboards for abuse | each provider console | update 10-secrets.conf + dsh configs |
GMAIL_APP_PASSWORD, EMAIL_AGENT_PASSWORD, EMAIL_AGENT_SESSION_SECRET |
Mailbox takeover, spam/phishing from your address | Google account → App passwords → revoke all | update voice-agent + email_agent |
COMPASS_PASSWORD, PASEO_PASSWORD |
Account takeover | respective apps | update .env/conf |
MQTT_USER/MQTT_PASS |
Control smart-home devices | Mosquitto passwd file |
update all ESP/HA clients |
AWS keys in ~/.aws-credentials.local |
Cloud spend, data | IAM → deactivate access key → create new | update profile |
~/.npmrc token |
Publish malicious packages under your name | npmjs.com → Access Tokens → revoke | npm login |
~/.gemini/mcp-oauth-tokens-v2.json |
Google scope | revoke at myaccount.google.com → Security → Third-party access | re-auth |
VIKUNJA_TOKEN, N8N_API_KEY, N8N_MCP_TOKEN, PAPERCLIP_API_KEY, PAPERCLIP_BOARD_KEY, APPRISE_URLS |
Task/automation control; apprise URLs embed tokens | each app's settings | update consumers |
Priority 2 — rotate this week (internal blast radius)
POSTGRES_PASSWORD/POSTGRES_USER/POSTGRES_DB(family-home-lab)SESSION_SECRET,ADMIN_PASSWORD(portal — invalidate all sessions, log everyone out)GARAGE_RPC_SECRET,GARAGE_ADMIN_TOKEN,GARAGE_METRICS_TOKEN,S3_ACCESS_KEY,S3_SECRET_KEYRABBITMQ/REDISpasswords if set in.envlangfuse,outline,worldmonitor,omniroute,wherewoof-*DB/API keysWEBTOP_PASSWORD(new, created after the incident — not exposed, no action)
Priority 3 — no action (not secrets)
MOZ_ENABLE_WAYLAND, GITEA_URL, GMAIL_USER, COMPASS_USERNAME, HUB_PROJECTS,
PASEO_HOST, PI_NTFY_TOPIC (topic name only), ports/paths.
Hygiene fixes (do alongside rotation)
- Delete the 12
10-secrets.conf.bak*files — they hold superseded secrets and multiply exposure. Keep one encrypted backup instead. chmod 600every file under~/.config/environment.dand confirm~/.ssh/id_*are600(currently correct;.pubfiles at 644 are fine).- Never mount
/home/saminto a container again — removed from GIMP already. Mount only the specific directory needed. - Consider
sops-nix/agenixso secrets are encrypted at rest, and so a read-only home mount can never expose them in plaintext. - Audit
.envfiles for values that don't need to be secrets at all.
Rotation order that avoids downtime
- Revoke first (kills attacker access), even if it breaks things for a few minutes.
- Regenerate + write into
10-secrets.conf. systemctl --user daemon-reload/ re-login forenvironment.dto apply.- Restart consumers (portal, controller, dsh, voice-agent, n8n, worldmonitor…).
- Verify each service health endpoint, then update the
.envcopies. - Only then delete the old
.bakfiles.
Verification checklist
ssh -T git@github.comworks with a new key; old key rejected on target hosts- Gitea push works with new token
- Portal login works; old sessions invalidated (forced logout)
- Service-controller
/healthOK with newSC_TOKEN - dsh + models respond (new AI provider keys)
- MQTT devices reconnect (new broker creds)
- Email agent sends a test message
- No unexpected spend on provider billing dashboards for 2026-11-06 → 11-11