SECURITY: canonical .gitignore misses common secret shapes (*.env, .envrc, *.p12/*.pfx, extensionless SSH keys) #38
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found while implementing #29, which fixed the equivalent gaps in
.dockerignore. Filed separately because the two files have different semantics and must be written to their own — the whole lesson of #29 is that deriving one from the other produces a file that is wrong in a way that looks careful.Problem
Canonical
.gitignore's secrets section is:Measured as reaching a build context in the #29 probes, and equally uncommitted-only-by-luck here:
prod.env/local.env— the<name>.envconvention is common and.env.*does not match it (.env.*matches.env.production, notprod.env)..envrc— direnv's config, a secrets file by convention, matched by nothing above.*.p12/*.pfx— certificate bundles that contain private keys.id_rsa,id_dsa,id_ecdsa,id_ed25519.deploy/secrets/id_rsa.keywas caught in the probes only because someone had given it a.keysuffix; the defaultssh-keygenoutput has none.REPO_POLICIES.mdstates "Never commit secrets..envfiles, credentials, API keys, and private keys must be in.gitignore. No exceptions." The current file does not deliver that for any of the shapes above.Why this is filed rather than fixed alongside #29
.dockerignoreneeded**/prefixes because it uses Gofilepath.Match..gitignoremust NOT get those prefixes — an unanchored.gitignorepattern already matches at any depth, so prefixing would be both redundant and, for anchored patterns, actively wrong (**/binarywould newly matchsub/binarywhere/binarydeliberately did not). Verified withgit check-ignoreduring the #29 review.That asymmetry is exactly why the two changes must not ride together: a single commit touching both invites the next reader to conclude the files are kept in sync.
Definition of done
.gitignorecovers the shapes above, written to gitignore semantics — no**/prefixes.git check-ignore -vagainst planted files at the repo root and nested at least two directories deep, plus a positive control (an ordinary source file that must remain trackable). Reading the patterns is not verification.*.envin particular should be checked against any file a repo might genuinely want committed, e.g. a checked-inexample.envorsample.env. If that conflict is real, prefer a negation (!example.env) over dropping the pattern, and record the decision..gitignore, so this needs the same propagation treatment. It can ride along with the #35 sweep as a separate commit, not merged into the.dockerignoreone.Note
This is parity with the pre-existing state rather than a regression — nothing got worse when #29 landed. But #29 tightened
.dockerignorepast what.gitignorecovers, so the two now disagree about what counts as a secret, and.gitignoreis the weaker of the two. A developer'sprod.envis currently onegit addaway from the repository.clawbot referenced this issue2026-08-09 18:36:36 +02:00
clawbot referenced this issue2026-08-09 18:44:00 +02:00
clawbot referenced this issue2026-08-09 19:08:20 +02:00
clawbot referenced this issue2026-08-09 19:15:47 +02:00
clawbot referenced this issue2026-08-09 19:22:26 +02:00
clawbot referenced this issue2026-08-09 20:10:32 +02:00
clawbot referenced this issue2026-08-09 20:52:45 +02:00