Repository navigation
sec(scripts): catch DSN credentials and register the full git-secrets set in CI - #83
Conversation
… set in CI git-secrets greps with -w, which needs a non-word character after the match. The DSN patterns ended in `@`, with the host right after it, so real postgres, mysql and mongodb DSNs were never flagged. End the pattern on the host instead, and cover postgresql and mongodb+srv. On macOS the --cached path uses git grep's POSIX regex, which has no \s, so the commit hook missed spaced account_id and aws_secret_access_key assignments. Register POSIX-class twins of the two upstream \s patterns. Delete the inverted 40-char pattern. Its `^` sits inside the bracket, so it matched 41 non-base64 characters (markdown table rows) and could never detect a key. CI registered only the AWS patterns. Run the setup script instead, so CI enforces the full set and scans the whole tree. Add must-catch and must-not-catch self-test cases. Split the one fixture that tripped the full set, and drop the .gitallowed entries that the old DSN lines needed to stop matching themselves. Closes #58 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reached
This review includes 4 billable files and costs up to $1.00.
Reviews can continue after your included limit without a manual trigger. An admin must approve usage-based billing. Or wait 29 minutes for your next included review. View limit details
Comment |
|
Merge-driver verdict: CLEAN at An independent adversarial reviewer (Sonnet, high effort, cold brief, not the author) reviewed the full diff. It found no blocking findings. All git-secrets registration ran in throwaway repos with a temporary HOME. The global Local verification (macOS, git 2.50.1, Homebrew git-secrets):
Non-blocking notes:
Gate items:
|
|
Gate met at |
Summary
This fixes the git-secrets gaps reported in #58. Every root cause was reproduced on macOS, and on Linux (debian:bookworm with git-secrets 1.3.0 built from the tag CI uses).
-w(git grep -nwHEIandgrep -nwHEI).-wneeds a non-word character after the match, but every DSN pattern ended in@with the host right after it. The regex was fine;-wdefeated it. The three DSN lines become one pattern that ends on a host character. It covers postgres, postgresql, mysql, mongodb and mongodb+srv.--cachedgoes throughgit grep -E, which uses libc POSIX regex with no\s. The local commit hook therefore missedaccount_id = "..."and spacedaws_secret_access_key = .... A plain file scan uses BSDgrep -E, which accepts\s. Those\spatterns come from--register-awsand can't be edited, so I added two POSIX-class twins. Linux CI was not affected.accountId:was already matched. The miss reported in sec(scripts): DSN detector coverage audit and git-secrets scan-path inconsistencies (#24 part 2) #58 was the same space problem. A test case now guards it.[^A-Za-z0-9/+=]{40}[^A-Za-z0-9/+=]has its^inside the brackets, so it matched 41 non-base64 characters. That is what flagged the markdown table rows, and it could never detect a key. The upstream AWS patterns and the quotedaws(...)pattern cover real keys.pre-commit.ymlnow runsscripts/setup-git-secrets.shinstead ofgit secrets --register-aws --global. CI now enforces the full set and scans the whole tree. The "at least one pattern" assertion moves to local config and fails on an empty pattern list.%40-encoded password, an IPv6 host, a quoted DSN, spacedaccount_id, camelCaseaccountId: "..."and spacedaws_secret_access_key.${DB_PASS},<password>, a DSN with no password, andhttps://user:pw@host..gitallowedentries that the old DSN lines needed to stop matching themselves are removed.Closes #58
If you already ran the setup script
Your
.git/configkeeps the old inverted and DSN patterns. Re-running the script fails on duplicate patterns; that's #79. Refresh with:This was verified in a scratch repo: the old patterns are gone and the script exits 0. It also drops any
secrets.allowedentries you added by hand.--register-awsre-adds the AWS example allowlist, and the versioned.gitallowedis untouched.Accepted false negatives
These DSN shapes are deliberately not caught, because the cost of covering them outweighs the value:
$,<or{(placeholders are excluded by design);/in the password;xpostgres://.Decisions
I made these as the driver. The owner can object on this PR:
The sibling repos share the setup script and likely have the same gaps. They're a follow-up after this lands.
Verification (local; macOS plus Linux via docker, no real secrets)
.gitallowed@-terminated DSN ending gives 14 FAIL (the 7 DSN cases), on Linux and macOS;git ls-files,scan -rand--cachedare all clean.pre-commit.yml, and all pre-commit hooks pass. shellcheck only repeats existing notes: SC2034 on unused colour variables, and an intentional SC2016 on the${DB_PASS}literal. No repo gate runs shellcheck onscripts/.Review
The plan had two independent passes (Sonnet, high effort, non-author). Pass 1 made three changes, all applied:
The diff then had two passes from the same reviewer, both with no actionable findings at the exact staged tree
56cc55e. The reviewer re-ran the fail-before, pass-after, mutation and whole-tree checks itself, on both platforms. It also confirmed that the--listassertion can't pass vacuously, that the step order is unchanged, and that the scan can't hang in Actions.CodeRabbit was not pinged because the org's CR quota is exhausted.
🤖 Generated with Claude Code