Conversation
Adds two layers of defense against real-engagement names landing in this public repository's prose, YAML samples, or pack identifiers (continuation of the 91d5e27 / c6c6167 / f4365c6 de-leak series). Layer 1 — agent awareness (primary): AGENTS.md gains a 9th MUST NOT rule covering real client / collection / vendor / family names. Uses only fictional placeholders in the rule text so the file itself never names a real engagement. Layer 2 — mechanical backstop: lefthook pre-commit and commit-msg hooks gain a `client-names` step that scans staged content and commit messages against patterns loaded from $DENY_PATTERNS_CLIENT_NAMES. The patterns themselves live in a gitignored .private-deny-list file sourced by .lefthookrc (already loaded for PATH setup). A committed .private-deny-list.example documents the shape. Fresh clones without a local patterns file get only the behavioral defense in AGENTS.md — acceptable trade-off, since putting the actual names in the public hook config would defeat the scrub. Files: - .gitignore ignore .private-deny-list - .lefthookrc source .private-deny-list if present - .private-deny-list.example shape doc with placeholder names - lefthook.yml add client-names step to pre-commit + commit-msg - AGENTS.md add MUST NOT #9 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: da1639edb2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| found=0 | ||
| for file in {staged_files}; do | ||
| if [ ! -f "$file" ]; then continue; fi | ||
| if grep -inE "$DENY_PATTERNS_CLIENT_NAMES" "$file" 2>/dev/null; then |
There was a problem hiding this comment.
Reject invalid deny-list regex instead of passing commits
The new client-names hook treats any non-match from grep -E as safe, which means an invalid or unsupported pattern in $DENY_PATTERNS_CLIENT_NAMES silently disables this protection and lets commits through. In pre-commit this is especially hidden because stderr is redirected away, so regex parse errors (or platform-specific incompatibilities) are indistinguishable from “no hit.” This undermines the mechanical backstop exactly when local patterns are misconfigured; the hook should fail closed when grep exits with an error status.
Useful? React with 👍 / 👎.
| # case-insensitive. Join multiple patterns with `|`. Use `\s` for | ||
| # whitespace, `\.` for a literal dot, `\b` for word boundary. |
There was a problem hiding this comment.
Avoid GNU-only escapes in POSIX regex guidance
This example labels the pattern syntax as “POSIX extended regex” but then recommends \s and \b, which are GNU extensions rather than POSIX ERE constructs. Contributors following this guidance on non-GNU environments (e.g., BSD/macOS default grep) can end up with patterns that do not match as intended, reducing or nullifying the deny-list check. Use POSIX character classes/word-boundary-safe alternatives in the example (or explicitly require GNU grep).
Useful? React with 👍 / 👎.
Summary
Two-layer hardening against real-engagement names landing in the public repo (continuation of the 91d5e27 / c6c6167 / f4365c6 de-leak series).
Layer 1 — agent awareness (primary): AGENTS.md adds a 9th MUST NOT rule covering real client / collection / vendor / family names. The rule text uses only fictional placeholders so the file itself never names a real engagement.
Layer 2 — mechanical backstop: lefthook gets a
client-namesstep in both pre-commit and commit-msg that scans against patterns loaded from$DENY_PATTERNS_CLIENT_NAMES. The patterns themselves live in a gitignored.private-deny-listfile sourced by.lefthookrc; a committed.private-deny-list.exampledocuments the shape. Fresh clones without a local patterns file fall back to the AGENTS.md behavioral defense — acceptable since putting actual names in the public hook config would defeat the scrub.Files
.gitignore.private-deny-list.lefthookrc.private-deny-listif present.private-deny-list.examplelefthook.ymlclient-namesstep to pre-commit + commit-msgAGENTS.mdTest plan
client-namescheck doesn't false-positive on its own files).private-deny-listcorrectly marked as ignored (!!ingit status --ignored)🤖 Generated with Claude Code