pre-commit-audit
Skill150 starsChanged 9 days agoMITView on GitHub
Deliver a fast pre-commit safety scan: file size, anonymity (author / affiliation strings in tex/bib), hardcoded secrets, and invisible-Unicode carriers. Use when the user requests a fast pre-commit safety scan: file size, anonymity (author / affiliation strings in tex/bib), hardcoded secrets, and invisible-Unicode carriers. Triggers: 'audit before commit', 'check before push', 'pre-commit scan', 'safety check'.
- Reads credentials
In this repository89 other files it gives its agents.
- AGENTS.mdAGENTS.md
- docs/agents.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- beamer-deckSkill
- bib-coverageSkill
- bib-filterSkill
- bib-parseSkill
- brief-compliance-checkSkill
- camera-readySkill
- causal-designSkill
- checkpointSkill
- code-archaeologySkill
- compile-knowledgeSkill
- computational-experimentsSkill
- cross-language-checkSkill
- data-analysisSkill
- devils-advocateSkill
- docs-consistencySkill
- docxSkill
- experiment-designSkill
- grill-meSkill
- handoffSkill
- ideasSkill
- init-project-courseSkill
- init-project-lightSkill
- init-project-orchestrationSkill
- init-projectSkill
- insights-deckSkill
- interview-meSkill
- knowledge-lintSkill
- latex-diffSkill
- latex-health-checkSkill
- latex-polishSkill
- latex-postersSkill
- latex-scaffoldSkill
- latexSkill
- latex-templateSkill
- lean-checkSkill
- math-proofSkill
- mcp-builderSkill
- method-auditSkill
- multi-perspectiveSkill
- numerical-checkSkill
- pdfSkill
- pipeline-manifestSkill
- playwright-cliSkill
- postmortemSkill
- pre-submission-reportSkill
- project-deckSkill
- project-safetySkill
- proof-readabilitySkill
- proofreadSkill
- python-envSkill
- quarto-deckSkill
- reorgSkill
- replication-auditSkill
- replication-packageSkill
- retarget-journalSkill
- review-clusterSkill
- review-responseSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
11 rules. About 0 are common, 7 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈7
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 18
Secrets pass uses an entropy heuristic + known-prefix list: No regex-only matching that misses high-entropy keys.
- Distinctive: line 26
Always show the file path and line number when flagging — make it copy-paste-fixable.
- Distinctive: line 30
Before any git commit on a paper / project repo
- Distinctive: line 32
Before pushing to anonymous-artifact repo (the highest-risk anonymity surface)
- Distinctive: line 33
After a sub-agent has written files (verify before committing their work)
- Very specific: line 38
Before commits on infrastructure-only changes (skills, hooks, rules) — anonymity scan would false-flag README author lines.
- Very specific: line 40
When the change is purely metadata (.gitignore, LICENSE, etc.)
- Very specific: line 160
If any BLOCK rows: ask the available structured-question mechanism:
- Distinctive: line 165
If only WARN rows: ask whether to proceed.
- Distinctive: line 166
If all OK: print "Pre-commit clean ✓" and exit silently.
- Very specific: line 186
Don't: run Phase 4's --apply as part of the audit.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Pre-Commit Audit — File Size, Anonymity, Secrets
Three-pass safety scan before commit. Blocks pain-points: oversized commits (1.3GB parquet incident), CCS-style anonymity breaches, leaked credentials. Each pass is a hard gate; user OKs proceed.
Hard Rules
Existential — block proceed
- Size pass blocks anything >10MB unless gitignored OR user explicitly approves. Threshold matches
block-large-files.shhook for consistency. - Anonymity pass runs only on paper-relevant paths:
paper-*/,*.tex,*.bib,*.mdinside paper directories. Scope is data-driven — we don't false-flag README authorship. - Secrets pass uses an entropy heuristic + known-prefix list. No regex-only matching that misses high-entropy keys. Block on confirmed secret; warn on suspicious-but-uncertain.
- All four passes run on the same file set (default: staged for commit). Don't mix staged-only size check with all-files anonymity check.
- The Unicode pass is the one pass that is always in scope, including infra-only commits. It is identity-blind — it reads codepoints, never names — so it cannot false-flag authorship the way the anonymity pass can.
Format — catch in review
- Output a single consolidated table (file × pass × verdict) — not four separate reports.
- Severity tiers: BLOCK (must fix), WARN (proceed with confirm), OK.
- Always show the file path and line number when flagging — make it copy-paste-fixable.
When to Use
- Before any
git commiton a paper / project repo - Pre-submission checklist (research projects)
- Before pushing to anonymous-artifact repo (the highest-risk anonymity surface)
- After a sub-agent has written files (verify before committing their work)
- Wired as a
session-closePhase 4 sub-step (alternate path to running the hook)
When NOT to Use
- Before commits on infrastructure-only changes (skills, hooks, rules) — anonymity scan would false-flag README author lines. Exception: Phase 4 (Unicode) stays valid there and can be run alone:
pre-commit-audit --unicode-only - Auto-generated commits (CI, dependabot) — they don't need the scan
- When the change is purely metadata (
.gitignore,LICENSE, etc.)
Modes
| Invocation | Scope |
pre-commit-audit | Staged files (default) |
pre-commit-audit --staged | Same as default |
pre-commit-audit --unstaged | Modified-but-not-staged files |
pre-commit-audit --all | Working tree + staged |
pre-commit-audit --unicode-only | Phase 4 only — safe on infra commits |
Architecture
Phase 1 (size) → find files >10MB; check .gitignore status
Phase 2 (anonymity) → grep paper paths for author/affiliation/email
Phase 3 (secrets) → entropy + prefix heuristics on all staged files
Phase 4 (unicode) → invisible-carrier scan via check_invisible_unicode.py
Phase 5 (consolidate) → single table; user OK to proceedPhase 1: Size
THRESHOLD_BYTES=$((10 * 1024 * 1024))
git diff --cached --name-only --diff-filter=ACM | while read f; do
if [ -f "$f" ]; then
size=$(stat -f%z "$f" 2>/dev/null || stat -c%s "$f" 2>/dev/null || echo 0)
if [ "$size" -gt "$THRESHOLD_BYTES" ]; then
ignored=$(git check-ignore "$f" 2>/dev/null && echo "ignored" || echo "tracked")
echo "$f|$size|$ignored"
fi
fi
doneVerdict: BLOCK if any tracked file >10MB. WARN if gitignored but staged anyway.
Phase 2: Anonymity
Single source of truth: skills/_shared/double-blind-anonymity-checklist.md holds the authoritative pattern list (paper-side P1-P8, artifact-side A1-A6) plus the CCS 2026 #1328 incident report that motivates the checks. Both pre-commit-audit (this skill) and anonymous-artifact reference it; do not duplicate the patterns inline.
Scope for pre-commit-audit: only files staged for commit at paths matching paper-*/, **/*.tex, **/*.bib, **/*.cls, **/*.sty. The full checklist also covers structured-metadata files (pyproject.toml, package.json, Cargo.toml, CITATION.cff, etc.) — those are checked by anonymous-artifact since they only matter when pushing the artifact, not on every commit.
Apply checks P1-P8 from the shared checklist:
- P1 — title page authors blinded
- P2 — no
\thanks{}/\acknowledgements/\funded/\grantrevealing identity - P3 — first-person self-reference uses third person (no "our prior work")
- P4 — self-citation bib entries blinded if author overlap
- P5 — body text doesn't name authors of self-cited works
- P6 — no identifying URLs (personal sites, lab pages, repos with handles)
- P7 — PDF metadata sanitized (
pdfinfo paper.pdf) - P8 — figures contain no identifying watermarks/captions
For each match: print path:line and the matched text (truncated). Verdict: BLOCK on any match in a path containing paper-*/. WARN on matches outside paper directories.
Exception: a frontmatter-style Made by the user in friends-repo / public-repo READMEs is allowed (intentional attribution).
Phase 3: Secrets
Patterns by category:
| Category | Detection |
| API keys with prefix | sk-, sk-proj-, sk-ant-, hf_, gh[a-zA-Z]_, xoxb-, AIza |
| AWS | AKIA[0-9A-Z]{16}, aws_secret_access_key |
| Generic high-entropy strings | length ≥32, base64-ish character set, no whitespace |
.env-style assignments | ^[A-Z_]+=[a-zA-Z0-9+/=_-]{20,} outside .env.example/.env.template |
Skip .env.template, .env.example, *.example, comment lines starting with #.
Verdict: BLOCK on any match in a non-template file.
Phase 4: Invisible Unicode
Catches characters that are invisible on screen but change what a machine reads — zero-width carriers, bidi overrides, tag characters, and space homoglyphs. These arrive by paste (Word, PDF, web page, LLM output) and fail silently: a U+200B inside a citekey makes BibTeX drop the entry with no error, a U+00A0 makes an exact-match string edit fail on a line that looks identical.
Deterministic — delegate to the script rather than grepping by hand:
git diff --cached --name-only --diff-filter=ACM \
| while read -r f; do [ -f "$f" ] && printf '%s\n' "$f"; done \
| xargs -r uv run --no-sync python "<skill-dir>/scripts/check_invisible_unicode.py" --format jsonMap the script's severities onto this skill's tiers:
| Script severity | Meaning | Verdict |
critical | Zero-width / bidi / tag char, or any invisible inside a citekey, crossref, path, url, bib_entry_key, bib_doi | BLOCK |
warning | Space homoglyph or soft hyphen in prose — renders fine, breaks exact-match editing and grep | WARN |
rescued | Legitimate emoji ZWJ / VS16 sequence | not reported |
Report path:line:col, the U+XXXX label, and the containing construct when the JSON carries a context. The context is most of the signal: the same U+00A0 is a WARN in prose and a BLOCK inside \ref{}.
Fixes are mechanical, so offer them — but never apply silently (Anti-Patterns below):
uv run --no-sync python "<skill-dir>/scripts/check_invisible_unicode.py" <path> --diff # preview
uv run --no-sync python "<skill-dir>/scripts/check_invisible_unicode.py" <path> --apply # write--apply refuses Overleaf-canonical paths unless given --yes-live-surface, per reconcile-before-rewriting.md; if a flagged file is a live Overleaf surface, surface the finding and let the user fix it in the editor rather than passing that flag on their behalf.
Phase 5: Consolidate + ask
Single table:
File Size Anon Secrets Uni Verdict
────────────────────────────────────────────────────────────────────────────
paper-ccs/paper/main.tex 5KB OK OK OK OK
paper-ccs/paper/references.bib 12KB FAIL OK FAIL BLOCK (line 23: the user; line 8: U+200B in bib_entry_key)
data/raw/results.parquet 1.3GB N/A N/A N/A BLOCK (size; not gitignored)
scripts/sync-creds.sh 2KB OK FAIL OK BLOCK (line 15: hf_<...>)
notes/from-word.md 4KB OK OK WARN WARN (4x U+00A0)If any BLOCK rows: ask the available structured-question mechanism:
- Fix the issues and rerun — recommended
- Override and proceed — risky, requires explicit confirmation
- Cancel commit — abort
If only WARN rows: ask whether to proceed. If all OK: print "Pre-commit clean ✓" and exit silently.
Cross-References
| Skill / Hook / Rule | Relationship |
block-large-files.sh hook | Runtime enforcement of Phase 1 (this skill is the manual / verbose counterpart) |
scripts/check_invisible_unicode.py | Bundled deterministic engine behind Phase 4. Codepoint tables adapted from guillaumemeyer/watermarks-remover (MIT); severity tiers, LaTeX-context detection, and emoji rescue are local |
reconcile-before-rewriting.md rule | Governs Phase 4's --apply on live Overleaf surfaces |
anonymous-artifact | The anonymity-on-publish workflow; this skill is the pre-commit equivalent |
session-close Phase 4 | Can invoke this skill as part of pre-commit verification |
mark-unverified.md rule | Verbal counterpart for content claims; this skill handles file content |
Anti-Patterns
- Don't scan binary files for anonymity strings — false positives on PDFs, images.
- Don't rely solely on regex for secret detection — entropy heuristics catch keys with novel prefixes.
- Don't auto-fix issues — surface them for the user to handle. Auto-replacement of names risks breaking acknowledgements.
- Don't skip the .gitignore check — large gitignored files staged anyway are a signal of
git add -Amistakes. - Don't require this skill on infra-only commits. Add a path filter or let the user opt out for those — but
--unicode-onlyremains safe and useful there. - Don't run Phase 4's
--applyas part of the audit. The audit reports; the user decides. Auto-rewriting bytes in a file the user is mid-edit on is the exact failurereconcile-before-rewriting.mdexists to prevent. - Don't flag visible non-ASCII. Accented names (
López-Ibáñez), em dashes, and→are legitimate and the script deliberately ignores them; a pass that flags them will be muted within a week.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

