From ed474801164770fc82ededdba9869d1dcdc74e3a Mon Sep 17 00:00:00 2001 From: gramps Date: Fri, 9 Oct 2026 08:48:53 -0700 Subject: [PATCH] =?UTF-8?q?Docs:=20never=20print=20CREDENTIALS.md,=20not?= =?UTF-8?q?=20even=20filtered=20=E2=80=94=20sudo-password=20exposure=20inc?= =?UTF-8?q?ident=20+=20safe=20patterns=20(Unit:=20secrets=20hygiene)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MyMistakes.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/MyMistakes.md b/MyMistakes.md index 7f12fdc..a6073ca 100644 --- a/MyMistakes.md +++ b/MyMistakes.md @@ -15,6 +15,30 @@ ## 🔬 Recipes registry +### ⛔ NEVER PRINT CREDENTIALS.md — NOT EVEN "FILTERED" (2026-10-09 incident) + +**What happened:** to look for an API key, a `sed -n '1,40p' CREDENTIALS.md` piped through a +redaction regex was run. The regex only matched `password: \`…\``; the **"Sudo pattern" +line stores the password inside `echo '…'`**, slipped past the filter, and the full sudo +password was printed into the session output (and so into local session logs and the model +provider's transcript). Owner had to rotate it. + +**Rule:** never `cat`/`sed`/`grep`/`read` CREDENTIALS.md (or any secrets file) in a way that +can print values. Redaction regexes are not a safety net — secrets hide in shapes you didn't +anticipate. +- **Need a secret for a command?** Load it into a variable, never echo it: + `PW=$(sed -n 's/.*password:.*\`\(.*\)\`.*/\1/p' CREDENTIALS.md | head -1)` then use `"$PW"`. +- **Need to know what's in the file?** List **keys only**, never values: + `grep -oE '^\s*- \*\*[^*]+\*\*' CREDENTIALS.md` (bold labels) — or ask the owner. +- **Looking for a specific secret?** Test for presence without printing: + `grep -qi 'gitea' CREDENTIALS.md && echo present || echo absent`. +- Secrets in source (e.g. the Google client secret) live in gitignored + `Helpers/OAuthCredentials.cs` — check with `git check-ignore -v`, don't open it. + +**Rotation (YunoHost user `gramps`):** YunoHost owns the password (LDAP) — plain `passwd` +may not apply. Owner rotates via web admin → Users → gramps, or +`sudo yunohost user update gramps -p` (prompts). Never route the new password through the AI. + ### YOUTUBE STATISTICS ARE JSON STRINGS; TryGetInt64 THROWS ON STRINGS (RECIPE) YouTube Data API v3 returns `statistics.subscriberCount / viewCount / videoCount` as