Safeguard
Developer Tools•

Should Husky git hooks install in CI and Docker builds?

Husky hooks belong on developer machines. Set HUSKY to 0 in CI and Docker so the prepare script installs nothing and the build runs less install time code.

Safeguard Security Team
4 min read

No. Git hooks are for developer machines. In CI and Docker builds, set the HUSKY environment variable to 0 so the prepare script installs nothing. Husky's own documentation recommends this, and it removes one more script that runs during install on a machine that holds build secrets.

Why a hook installer runs at install time

Husky is configured through a prepare script in package.json. The Husky get started page says its init command creates a pre-commit script in the .husky folder and updates the prepare script. The npm scripts documentation says prepare runs on a local npm install without any arguments, and also runs before a package is packed or published.

So the sequence on a laptop is: you run npm install, npm runs prepare, Husky points Git at your hook scripts. That is a convenience, and it is a script that executes during install.

Why CI and Docker do not need it

A CI job checks out code and runs a build. It never makes a commit through your developer workflow, so pre-commit and commit-msg hooks have nothing to do. A Docker build is the same. Installing hooks there only adds noise and, in some cases, a failure.

Husky's documentation covers both cases:

  • To avoid installing hooks on CI servers or in Docker, use HUSKY=0. The docs show setting it as an env value in GitHub Actions.
  • If you install only dependencies and not devDependencies, the prepare script can fail because Husky is not installed. The docs offer a prepare script that never fails, or a small install script that exits early when NODE_ENV is production or CI is true.

A safe pattern

# GitHub Actions job env
env:
  HUSKY: 0
"prepare": "node .husky/install.mjs"

with the install script exiting when running in production or CI, as in the Husky how-to guide.

Table of where hooks should run

PlaceInstall hooks?Reason
Developer laptopYesCatch lint and format issues before commit
CI build and test jobNoNo commits happen, fewer install time scripts
Docker image buildNoProduction install should have no dev tooling
Release or publish jobNoKeep the credential holding job minimal

The security angle

Hooks themselves are code from your repository, so they go through your normal review. The point here is narrower. Every script that runs at install time is a place where a changed dependency can run code. If prepare is not needed on a machine, make it do nothing there.

Two related habits help. Install in CI with a lockfile and npm ci, and consider disabling dependency install scripts, as described in how to disable install scripts. Note that ignoring scripts also stops the repo's own prepare script from running, which is what you want for Husky in CI and a surprise if you rely on prepare to compile code.

Keep hooks fast and honest. A hook is a developer aid, not a control. Anyone can skip hooks with the no verify flag on most Git commands, which Husky documents, so the same checks must run again in CI where they cannot be skipped. A scan that matters should be a required status check on the pull request.

Safeguard's policies and gates can enforce dependency checks at the pull request, which is where a skipped local hook gets caught. You can try a free scan at gold.safeguard.sh/scan.

Quick check

What does the prepare script do on npm install?

Per the npm docs it runs on a local npm install with no arguments, which is how Husky installs its hooks.

Can developers bypass Husky hooks?

Yes. Most Git commands accept a no verify option and Husky documents the HUSKY=0 switch. Repeat important checks in CI.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.