gestate guards the install step. Pair it with controls at other layers for defense in depth.
Stop bump PRs from landing fresh versions in the first place.
Added July 2025. Configured per ecosystem in .github/dependabot.yml:
version: 2
updates:
- package-ecosystem: npm
directory: /
schedule:
interval: daily
cooldown:
default-days: 7
semver-major-days: 14Supported on all Dependabot ecosystems. Different cooldowns per semver bump type are allowed.
See: https://github.blog/changelog/2025-07-01-dependabot-supports-configuration-of-a-minimum-package-age/
Renovate has shipped this for years. Set in renovate.json:
{
"minimumReleaseAge": "7 days"
}Applies to all managers Renovate supports (npm, pip, cargo, gomod, etc.).
Most supply-chain payloads execute via postinstall / preinstall hooks. Disable them unless explicitly needed.
- npm:
npm config set ignore-scripts true(global). Allow per-package via dedicated trusted lists. - pnpm:
onlyBuiltDependenciesinpackage.json— explicit allowlist for which packages may run install scripts. - bun:
trustedDependenciesinpackage.json.
- Lockfiles committed:
package-lock.json,pnpm-lock.yaml,bun.lock,uv.lock— pin exact resolved versions so a malicious republish under the same range can't slip in silently. - npm provenance:
npm publish --provenanceties published artifacts to a verifiable CI build. Consumers can checknpm view <pkg> --jsonfor thedist.attestationsfield. - Sigstore / SLSA: same idea, broader ecosystem coverage.
| Layer | Tool | Catches |
|---|---|---|
| PR creation | Dependabot cooldown, Renovate minimumReleaseAge |
Bump PRs for fresh versions |
| Install resolution | gestate (this repo) |
Direct + transitive + ad-hoc installs, CI without bots |
| Install scripts | ignore-scripts, onlyBuiltDependencies, trustedDependencies |
Lifecycle-hook payloads |
| Identity | Lockfiles, provenance, Sigstore | Republish / typosquat / impersonation |
No single layer is sufficient. The install-time guard in this repo is the broadest net; the others narrow specific attack paths.