Pre-commit Hooks
CI pipelines catch threats after a push. By then the code is in git history, visible to collaborators, and potentially already deployed. A pre-commit hook stops the commit entirely — keeping your repository clean from the start, before anything leaves your machine.
Why pre-commit scanning matters
Section titled “Why pre-commit scanning matters”CI catches issues after a push, which means threats travel through git history and may be visible to collaborators before anyone acts on them. A pre-commit hook stops the commit entirely if threats are found, keeping your repository clean from the start.
Firmis is well-suited for pre-commit use because it is:
- Fast — most projects scan in under 3 seconds
- Zero-install — runs via
npxwith no prior setup - Offline — no network requests for the core scan (OSV check is optional)
Setup options
Section titled “Setup options”Husky is the standard pre-commit hook manager for Node.js projects.
-
Install Husky and configure it:
Terminal npx husky init -
Add the Firmis scan command to
.husky/pre-commit:.husky/pre-commit #!/usr/bin/env sh. "$(dirname -- "$0")/_/husky.sh"# Run Firmis on staged files — fail commit if high/critical threats foundnpx firmis scan . --severity high --quiet -
Make the hook executable:
Terminal chmod +x .husky/pre-commit -
Add Husky to your
package.jsonprepare script so it installs for all contributors:package.json {"scripts": {"prepare": "husky"}}
Scan only staged files
Section titled “Scan only staged files”For large projects, scanning only the files staged for commit reduces hook latency.
#!/usr/bin/env sh. "$(dirname -- "$0")/_/husky.sh"
# Get staged filesSTAGED=$(git diff --cached --name-only --diff-filter=ACM | head -50)
if [ -z "$STAGED" ]; then exit 0fi
# Write staged file list to a temp fileTMPFILE=$(mktemp)echo "$STAGED" > "$TMPFILE"
# Scan only the project root (firmis auto-discovers components)npx firmis scan . --severity high --quietEXIT_CODE=$?
rm -f "$TMPFILE"exit $EXIT_CODEIf your project uses the pre-commit framework (common in Python and polyglot projects), add Firmis as a local hook.
-
Ensure
pre-commitis installed:Terminal pip install pre-commit -
Add the Firmis hook to
.pre-commit-config.yaml:.pre-commit-config.yaml repos:- repo: localhooks:- id: firmis-scanname: Firmis Security Scanlanguage: nodeentry: npx firmis scan . --severity high --quietpass_filenames: falsealways_run: truestages: [pre-commit] -
Install the hooks:
Terminal pre-commit install
Full .pre-commit-config.yaml with other hooks
Section titled “Full .pre-commit-config.yaml with other hooks”repos: # Standard hooks - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.5.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml - id: detect-private-key
# Firmis security scan - repo: local hooks: - id: firmis-scan name: Firmis — AI Agent Security Scan language: node entry: npx firmis scan . --severity high --quiet pass_filenames: false always_run: true stages: [pre-commit] verbose: trueNo framework required. Drop a script directly into .git/hooks/.
-
Create the hook file:
.git/hooks/pre-commit #!/usr/bin/env shecho "Running Firmis security scan..."npx firmis scan . --severity high --quietEXIT_CODE=$?if [ $EXIT_CODE -ne 0 ]; thenecho ""echo "Firmis found high/critical threats. Commit blocked."echo "Run 'npx firmis scan .' to see full details."echo "To skip this check (not recommended): git commit --no-verify"exit 1fiexit 0 -
Make it executable:
Terminal chmod +x .git/hooks/pre-commit
Share manual hooks via a setup script
Section titled “Share manual hooks via a setup script”If you prefer manual hooks but want to share them, commit the hook to a .githooks/ directory and add a setup step.
#!/usr/bin/env shnpx firmis scan . --severity high --quiet{ "scripts": { "prepare": "git config core.hooksPath .githooks && chmod +x .githooks/pre-commit" }}What to scan: full project vs. staged files only
Section titled “What to scan: full project vs. staged files only”| Approach | Speed | Coverage | Recommended for |
|---|---|---|---|
| Full project scan | 1–5s | All agent components | Most projects |
| Staged files only | Faster | Only committed files | Large monorepos |
For most projects, scanning the full project is the right choice. Firmis auto-discovers AI agent components (Claude Skills, MCP servers, Cursor rules, etc.) and needs the full directory tree to find them. Scanning staged files individually can miss threats in component manifests that reference files not staged in the current commit.
Bypass hooks in exceptional cases
Section titled “Bypass hooks in exceptional cases”If you need to commit without running the hook (for example, to commit a work-in-progress or suppress a known false positive), use:
git commit --no-verify -m "wip: work in progress"Suppress known false positives
Section titled “Suppress known false positives”Rather than bypassing the hook, add false positives to .firmisignore.
# Suppress a specific rule on a specific filetest/fixtures/evil-server.ts # firmis-ignore: sd-015
# Ignore an entire directorytest/fixtures/See Ignoring Findings for full .firmisignore syntax.
What to do next
Section titled “What to do next”- GitHub Actions integration → — enforce the same gate in CI after commit
- GitLab CI integration → — CI enforcement for GitLab pipelines
- Ignoring Findings → — suppress false positives without disabling rules
firmis scancommand → — full CLI reference for the command powering this hook