Skip to main content
Category: DevSecOps

Pre-commit Hooks

Also known as: Git Pre-commit Hooks, Commit Hooks
Simply put

Pre-commit hooks are scripts that run automatically on a developer's local machine before a code commit is finalized in a version control system. They check code for issues such as formatting errors, syntax problems, or policy violations before the commit is recorded. This gives developers fast, local feedback and helps prevent common mistakes from entering the codebase.

Formal definition

Pre-commit hooks are a category of Git hooks that execute as the first stage of the commit workflow, prior to the commit message prompt, on the developer's local working environment. They are typically implemented as shell scripts or managed through a framework such as pre-commit, which standardizes hook installation and execution across a team. Hooks at this stage can perform static analysis, linting, secret detection, and formatting validation against staged file content. Because they operate on local, pre-committed code rather than in a deployment or runtime context, their detection scope is limited to issues that are statically identifiable in source files; they cannot detect runtime behavior, environment-specific vulnerabilities, or issues that only manifest during execution. False negatives are possible when hooks are bypassed using the "--no-verify" flag, when hook configurations are incomplete, or when a check lacks coverage for a given file type or pattern. False positives may occur with overly strict linting or formatting rules. Pre-commit hooks complement but do not replace CI pipeline checks, as CI enforcement applies uniformly regardless of local hook configuration.

Why it matters

Pre-commit hooks shift security and quality checks as far left as possible in the development lifecycle, giving developers immediate feedback on their local machine before problematic code ever enters the shared repository. This early intervention reduces the cost of remediation: catching a formatting violation, exposed credential, or syntax error at commit time is faster and cheaper to fix than discovering it after it has been merged, reviewed, or deployed. Without local hooks, developers rely entirely on CI pipelines or code review to surface issues that could have been resolved in seconds during development.

Who it's relevant to

Software Developers
Developers are the primary users of pre-commit hooks and benefit most directly from the fast, local feedback loop. Hooks catch formatting errors, syntax problems, and policy violations at the moment of commit rather than minutes or hours later in a CI pipeline, allowing developers to fix issues without breaking their workflow or waiting for remote feedback.
Security Engineers and AppSec Teams
Security teams can use pre-commit hooks to enforce lightweight security checks, such as secret detection and static analysis, at the earliest possible point in the development cycle. However, they must recognize that hook coverage depends on correct configuration and can be bypassed with '--no-verify', so pre-commit hooks should be treated as a complement to, not a replacement for, centrally enforced CI pipeline security gates.
DevOps and Platform Engineers
Platform engineers who manage shared developer tooling are responsible for standardizing hook configurations across a team, typically through a framework such as pre-commit. Ensuring consistent hook versions and configurations prevents the situation where checks pass locally for one developer but not another, which undermines the reliability of the pre-commit layer.
Engineering Managers and Tech Leads
Tech leads and managers benefit from pre-commit hooks as a mechanism for enforcing team coding standards and reducing noise in code review. By automating style and quality checks locally, reviewers can focus on logic and design rather than mechanical issues, improving the quality and efficiency of the review process.

Inside Pre-commit Hooks

Hook Script
An executable script or configuration file placed in the repository's .git/hooks directory or managed via a framework, which the Git client invokes automatically when a developer runs a commit command.
Trigger Condition
The specific Git lifecycle event, in this case the moment before a commit is finalized, that causes the hook to execute. The hook runs locally on the developer's machine and can abort the commit if checks fail.
Static Analysis Integration
Calls to linters, SAST tools, or code formatters that inspect staged file contents at the code level without executing the code, identifying issues such as syntax errors, style violations, or known insecure patterns.
Secret Detection
Pattern-matching or entropy-based scanning of staged changes to identify credentials, API keys, or tokens before they enter the repository history. This operates statically on file contents and cannot detect secrets that are assembled or injected at runtime.
Dependency Manifest Checks
Inspection of package manifest files present in the staged changes to flag newly introduced or modified dependencies, typically by comparing against known-vulnerable version ranges using a local advisory database.
Hook Management Framework
A tool such as pre-commit, Husky, or Lefthook that standardizes hook installation, versioning, and sharing across a team, reducing reliance on each developer manually placing scripts in their local .git/hooks directory.
Exit Code Contract
The mechanism by which a hook signals success or failure to Git. A non-zero exit code causes Git to abort the commit and return control to the developer with an error message, while an exit code of zero allows the commit to proceed.
Staged File Scope
The boundary of what pre-commit hooks inspect, which is limited to files added to the Git index via git add. Unstaged changes in the working directory are typically not examined unless the hook explicitly scans the full working tree.

Common questions

Answers to the questions practitioners most commonly ask about Pre-commit Hooks.

Can pre-commit hooks replace my CI/CD pipeline security checks?
No. Pre-commit hooks run locally on a developer's machine and can be bypassed, skipped, or misconfigured. They are not a reliable enforcement boundary for security policy. CI/CD pipeline checks run in a controlled, centralized environment and serve as the authoritative gate. Pre-commit hooks are best understood as a developer convenience that provides early feedback, not as a substitute for server-side enforcement.
Do pre-commit hooks catch all security vulnerabilities before code is committed?
No. Pre-commit hooks operate on static, local code and cannot detect issues that require runtime or deployment context, such as authentication bypass, insecure session behavior, or runtime dependency resolution problems. They also cannot reliably detect complex logic flaws or vulnerabilities that span multiple services. Their coverage is limited to what static analysis, secret scanning, and linting tools can surface at the code level, and even within that scope they may produce false negatives depending on the tools configured.
How do I prevent developers from bypassing pre-commit hooks?
Pre-commit hooks can be bypassed locally using flags such as `--no-verify`. To mitigate this, organizations should enforce equivalent checks in CI/CD pipelines as a required gate, treat pipeline results as the authoritative signal, and use audit logging to flag commits that bypass hooks. Relying solely on pre-commit hooks for security enforcement is not appropriate given this bypass risk.
Which types of checks are most appropriate to run in a pre-commit hook?
Checks that are fast, low in false positives, and capable of running without external services or runtime context are most appropriate. Common examples include secret and credential scanning, basic linting, dependency manifest validation, and license header checks. Slower or noisier checks, such as comprehensive SAST scans or software composition analysis against live vulnerability databases, are typically better suited for CI/CD pipelines where execution time and network access are less constrained.
How do I ensure consistent hook behavior across a development team?
Consistency requires that all developers install the same hook configuration and tooling versions. Using a framework such as pre-commit (the tool) with a versioned configuration file checked into the repository helps standardize this. Onboarding documentation should include hook installation steps, and CI/CD pipelines should run the same underlying checks independently so that any developer who skips or misconfigures hooks does not create a gap in coverage.
What is the performance impact of adding security checks to pre-commit hooks?
Performance impact varies by tool and codebase size. Secret scanning tools are typically fast and add minimal latency. Comprehensive static analysis tools may add several seconds to minutes depending on scope, which can disrupt developer workflow if hooks are slow. A common mitigation is to scope hooks to changed files only rather than the full codebase, and to reserve deeper or slower scans for CI/CD pipelines. Teams should regularly review hook execution time and remove or relocate checks that create friction.

Common misconceptions

Pre-commit hooks are enforced by the repository server and cannot be bypassed by developers.
Pre-commit hooks run entirely on the developer's local machine. Any developer can bypass them by passing the --no-verify flag to git commit, or by deleting or modifying the hook scripts. Server-side controls such as CI pipeline checks or branch protection rules are required for enforceable policy.
A pre-commit hook that passes all checks guarantees the committed code is free of security vulnerabilities.
Pre-commit hooks operate statically on staged file contents and cannot detect vulnerabilities that depend on runtime behavior, deployment configuration, infrastructure context, or logic flaws that require execution to surface. They reduce risk at a specific point in the workflow but do not replace runtime testing, dynamic analysis, or thorough code review.
Pre-commit hooks are a sufficient substitute for a CI/CD pipeline security stage.
Pre-commit hooks provide early, fast feedback on individual commits but are bypassable, run only on staged changes, and typically execute a constrained subset of checks to keep latency low. A CI/CD pipeline runs in a controlled, consistent environment on the full codebase and is not subject to local machine configuration differences or developer bypass. Both layers serve distinct and complementary roles.

Best practices

Use a hook management framework such as pre-commit, Husky, or Lefthook to version and distribute hook configurations through the repository, so all team members run consistent checks without manual .git/hooks setup.
Keep hook execution time short, typically under 30 seconds, by limiting hooks to fast static checks on staged files only. Reserve comprehensive or slow scans for the CI/CD pipeline to avoid discouraging developers from committing frequently.
Treat pre-commit hooks as a convenience layer rather than a security enforcement boundary. Implement equivalent or more thorough checks in the CI/CD pipeline to catch issues that hooks miss or that developers bypass with --no-verify.
Scope secret detection hooks to staged changes and maintain an up-to-date set of detection patterns, but document to developers that hooks cannot catch secrets assembled dynamically at runtime or injected through environment variables.
Pin the versions of tools invoked by pre-commit hooks in the hook configuration to prevent silent behavior changes when tool versions update, and review those pins periodically as part of dependency maintenance.
Document the purpose and known limitations of each hook in the repository's contributing guide, including which categories of issues the hooks do not cover, so developers understand the scope of the checks they are relying on.