forgesworn/anvil

Supply-chain-hardened npm publish for JS/TS libraries. OIDC trusted publishing, SLSA provenance, secret scan, exports check, frozen-vector gate, action-pin auditing. Zero dependencies, pure bash, auditable in thirty minutes.

View on GitHub

Trust Signals

Scorecard Score
not yet scored
Maintenance Recency
Activelast commit Jun 3, 2026
License
MIT

Pinned Snippet

workflow.ymlSHA-pinned
uses: forgesworn/anvil@d4294e622932d93957d73e5b1af0267382b6af04 # v0.10.1

tags can be moved; commit SHAs can't. why a SHA?

namedescriptionrequireddefault
node-versionNode version used for npm operations (must ship with npm >= 11.5.x for OIDC trusted publishing)no24.11.0
registry-urlnpm registry URL for publishesnohttps://registry.npmjs.org
test-commandCommand that runs the full test suitenonpm test
vector-test-commandCommand for the frozen-vector gate (empty to skip)no""
changelog-filePath to CHANGELOG.mdnoCHANGELOG.md
package-jsonPath to package.jsonnopackage.json
audit-levelnpm audit level (low|moderate|high|critical)nolow
strict-action-pinsIf "true" (the default), verify-action-pins fails the release on any unpinned `uses:` reference in .github/workflows. Set to "false" for warn-only mode. forgesworn/anvil is exempt by name.notrue
lifecycle-scripts-policyHow verify-lifecycle-scripts handles preinstall/install/postinstall hooks in the published package. One of: - warn (default): unpermitted hooks are logged but publish continues. - strict: unpermitted hooks fail the release. - off: skip the gate entirely. Install-time hooks run on every consumer's machine when they `npm install` the package — the attack surface used in the April 2026 Bitwarden CLI compromise. Allow specific hooks via `allowed-lifecycle-scripts`. nowarn
allowed-lifecycle-scriptsJSON object mapping hook name (preinstall/install/postinstall) to the exact command string permitted. Anything else warns or fails depending on `lifecycle-scripts-policy`. Empty map (default) means no install hooks are allowed. Example: {"postinstall": "node-gyp rebuild"}no{}
version-strategyHow version bumps are validated. One of: - manual (default): you bump package.json and tag; the action verifies the tag matches and publishes. - verify: you bump manually, but the action parses conventional commits and fails if your bump is smaller than what the commit history implies (e.g. feat commits but only a patch bump). nomanual
dry-runIf "true", skip the real publish (for smoke-testing)nofalse
debugIf "true", run a diagnostic step before publish that dumps npm version, redacted .npmrc, OIDC env vars, and `npm config list`. Off by default. Useful for debugging trusted-publisher setup.nofalse

no outputs