Pre-Commit & Scanning Cross-cutting defense

AI agents generate diffs faster than humans can review and routinely write secrets into config files. Pre-commit hooks, secret scanners, and CI gates are the primary control plane for agent-authored code — independent of which harness you run.

1

pre-commit Framework Setup

The pre-commit framework (pre-commit.com) is the universal harness — runs language-agnostic hooks defined in .pre-commit-config.yaml, pinned by SHA, isolated in per-hook virtualenvs. Pin every rev: so an agent cannot silently bump a hook to a malicious version.

repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 hooks: - id: detect-private-key - id: check-added-large-files - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/gitleaks/gitleaks rev: v8.21.2 hooks: - id: gitleaks
pipx install pre-commit pre-commit install pre-commit install --hook-type pre-push --hook-type commit-msg pre-commit run --all-files pre-commit autoupdate --freeze

Tip: mirror the same config in CI via pre-commit/action@v3.0.1 so local-skipped hooks (SKIP=gitleaks git commit) still fail the PR.

2

gitleaks — Fast Regex Scanner

Gitleaks scans git history and staged content against ~150 built-in regex rules plus your custom ones. Fast, deterministic first-line scanner; combine with a baseline file so legacy false positives don't drown real findings.

brew install gitleaks gitleaks protect --staged --redact -v gitleaks detect --baseline-path .gitleaks-baseline.json --redact
# .gitleaks.toml — agent-specific custom rules [[rules]] id = "anthropic-api-key" regex = '''sk-ant-[a-zA-Z0-9_-]{60,}''' keywords = ["sk-ant-"] [[rules]] id = "openai-project-key" regex = '''sk-proj-[A-Za-z0-9_-]{40,}'''

Tip: generate the baseline once with gitleaks detect --report-path .gitleaks-baseline.json, commit it, require any new finding (not in baseline) to fail CI.

3

trufflehog — Live Credential Verification

TruffleHog goes beyond regex — its --results=verified mode actively pings the provider API to confirm a credential is live. Use verified in CI to cut noise to zero; use unverified in nightly audits to catch dormant keys.

brew install trufflehog trufflehog git file://. --since-commit HEAD~50 --only-verified --fail trufflehog filesystem . --results=verified,unknown --no-update

Tip: run --only-verified on every PR (blocking), and a full-history --results=verified,unknown scan weekly via a scheduled GitHub Action. For repos >1 GB, prefer trufflehog filesystem on a checkout over trufflehog git.

4

detect-secrets (Yelp) — Auditable Baseline

detect-secrets takes a different approach — an auditable baseline of every potential secret, with entropy plus plugin heuristics. Ideal when you need a reviewable artifact showing what's been triaged.

pipx install detect-secrets detect-secrets scan --all-files --exclude-files 'package-lock\.json' > .secrets.baseline detect-secrets audit .secrets.baseline
- repo: https://github.com/Yelp/detect-secrets rev: v1.5.0 hooks: - id: detect-secrets args: ['--baseline', '.secrets.baseline']

Tip: require a human (not an agent) to be the git author of any commit touching .secrets.baseline — enforce via CODEOWNERS.

5

AI-Agent-Specific Scanners (Prompt Injection & Rules Files)

Agent rule files (.cursorrules, .clinerules, .opencode/agents/*.md, CLAUDE.md, AGENTS.md, .github/copilot-instructions.md) execute as system prompts — treat them as code.

Real incidents CamoLeak (Oct 2025, CVSS 9.6): hidden markdown comments in PRs/issues prompt-injected GitHub Copilot Chat into reading private repo secrets and exfiltrating them character-by-character via 1×1 Camo image fetches. GitLab Duo (May 2025, CVE-2025-6945): base16/Unicode/KaTeX-hidden prompt injections in MR descriptions exfiltrated private source via base64 <img> URLs. Gemini CLI (Jul 2025): instructions hidden in README context files (padded off-screen) triggered silent shell execution.
  • promptfoonpx promptfoo@latest redteam init / promptfoo redteam run
  • NVIDIA garakpipx install garak; LLM vulnerability scanner with 100+ probes
  • Mindgard CLIpipx install mindgard; commercial red-team runner
  • Lasso Security — commercial runtime/CI scanner
npx promptfoo@latest scan --paths '.cursorrules,.clinerules,.opencode/agents/**/*.md,CLAUDE.md' garak --model_type test.Blank --probes encoding.InjectBase64,promptinject.HijackHateHumans

Tip: add a local pre-commit hook that greps rule files for suspicious tokens (ignore previous, system:, base64 blobs, fenced <|im_start|>) and require a security-team CODEOWNER review for any change under .cursor/, .opencode/, .clinerules, CLAUDE.md.

6

Repository Hygiene — .gitignore for Agent Config Dirs

Agent IDEs and CLIs scatter credentials across well-known paths. Most are project-local and will end up in git status unless ignored.

# AI agent config & credentials .env .env.* !.env.example # Cursor .cursor/mcp.json .cursor/rules/*.local.mdc # Cline / Roo .cline/ .clinerules.local .roo/ # opencode .opencode/auth.json .opencode/local/ .opencode/.cache/ # Claude Code .claude/settings.local.json .claude/.credentials.json .claude/projects/ # Pi / OpenHands / n8n .pi/ .openhands/ .n8n/credentials/ # MCP server configs commonly carry tokens **/mcp.json **/mcp.local.json .mcp.json

Tip: keep .env.example committed; add a pre-commit hook that hard-fails on any path matching *credentials*, *auth.json, or mcp.json regardless of .gitignore (defense against git add -f).

7

CI Gates — Block Secrets, Gate Agent-Authored Commits

Two gates: (a) secret scan on every PR, (b) human-review requirement on commits whose trailers identify an AI agent.

on: [pull_request] jobs: secrets: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: { fetch-depth: 0 } - uses: gitleaks/gitleaks-action@v2 - uses: trufflesecurity/trufflehog@main with: extra_args: --results=verified --fail - uses: pre-commit/action@v3.0.1 agent-authored-review: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: { fetch-depth: 0 } - name: Require human reviewer on AI commits run: | if git log --no-merges origin/main..HEAD --format='%(trailers:key=Co-Authored-By)' \ | grep -qiE 'claude|cursor|cline|opencode|copilot|openhands'; then echo "AI co-authored commits found — human approval required." gh pr view ${{ github.event.pull_request.number }} --json reviews \ | jq -e '.reviews | map(select(.state=="APPROVED")) | length >= 1' fi

Tip: enforce branch protection requiring secrets + agent-authored-review checks; maintain a git log --author= allowlist of trusted committers.

8

Hidden-Unicode / Bidi Detection

"Trojan Source" attacks (CVE-2021-42574) hide logic in U+202A–U+202E bidi controls and U+200B–U+200F zero-widths — devastating in agent-authored code because reviewers skim.

rg --pcre2 '[\x{200B}-\x{200F}\x{202A}-\x{202E}\x{2066}-\x{2069}\x{FEFF}]' \ --files-with-matches && exit 1
# Custom gitleaks rule [[rules]] id = "bidi-control-chars" regex = '''[\x{202A}-\x{202E}\x{2066}-\x{2069}]''' [[rules]] id = "zero-width-chars" regex = '''[\x{200B}-\x{200F}\x{FEFF}]'''

Additional tools: bidiscan, npm i -g anti-trojan-source, cargo install trojan-source-finder.

Tip: add the regex above as both a pre-commit local hook and a gitleaks rule — belt-and-suspenders, since agents sometimes echo invisible chars from web-fetched content.

9

Pre-Push & Post-Checkout — Inspect Third-Party Repos

Before pointing an agent at a freshly-cloned repo, scan it. A malicious .cursorrules or .opencode/agents/*.md can hijack the agent on first invocation.

# .git/hooks/post-checkout #!/usr/bin/env bash prev=$1; new=$2; flag=$3 [ "$flag" = "1" ] || exit 0 for dir in .cursor .opencode .claude .cline .pi .roo .openhands; do [ -d "$dir" ] || continue echo "Scanning $dir for injection markers..." rg -n --pcre2 \ -e 'ignore (all )?previous' \ -e '<\|im_start\|>' \ -e '[\x{202A}-\x{202E}\x{200B}-\x{200F}]' \ -e 'base64,[A-Za-z0-9+/]{200,}' \ "$dir" && { echo "Suspicious content in $dir — review before launching agent." exit 1 } done gitleaks detect --no-git --source . --redact

Tip: for any cloned repo, run git log --diff-filter=A --name-only -- '.cursor*' '.opencode*' '.claude*' '.cline*' to see who introduced agent configs — then audit each before invoking an agent.

10

Supply-Chain Scanning for Agent Extensions & Plugins

Cursor/Cline/opencode/Pi marketplaces and MCP server registries have shipped weaponized packages (typosquats, dependency-confusion, post-install scripts exfiltrating ~/.aws). Treat every agent extension and MCP server like an npm dep.

Real incidents Nx s1ngularity (Aug 2025): poisoned nx postinstall invoked locally-installed Claude/Gemini/Q CLIs to scan filesystem for secrets, leaked 1,000+ GitHub tokens. huggingface-cli (Mar 2024): Lasso registered an LLM-hallucinated package name; 30,000+ installs in three months. n8n community-node attack (Jan 2026): eight rogue npm packages exfiltrated decrypted OAuth tokens. MaliciousCorgi VS Code extensions (Mar 2026): 1.5M installs exfiltrating source code.
# Node / MCP servers npm audit --audit-level=high npx socket@latest npm install <pkg> npx better-npm-audit audit # Cross-ecosystem osv-scanner --recursive . snyk test --all-projects snyk monitor # Audit lockfiles npx lockfile-lint --path package-lock.json --allowed-hosts npm \ --validate-https --validate-integrity
- uses: google/osv-scanner-action@v1.9.1 with: { scan-args: |- --recursive --skip-git ./ } - run: npx --yes socket-security-cli ci

Tip: pin every MCP server and agent extension by integrity hash (npm ci with committed lockfile, or uvx --from 'pkg==X.Y.Z'); run osv-scanner + socket on every PR; subscribe to Dependabot + Socket advisories.

References & further reading