Docs / Reference / Policy configuration

Policy Configuration

npmvc-policy.json controls what gets checked and how strictly.

Quick start: presets

Use npmvc install-hook --preset strict|balanced|permissive to generate a policy. The fields below are documented for hand-tuning.

Full schema

{
  "enforcement": "block | warn | off",
  "transitive": true,
  "minAge": "7d",
  "perPackage": { "left-pad": "30d" },
  "unattested": "warn | block | allow",
  "unattestedMinAge": "30d",
  "trustedIssuers": ["https://npmvc.com/trust-root.json", "did:key:z6Mk..."],
  "trustedAuditIssuers": ["did:key:z6MkSCANNER..."],
  "auditMaxAge": "180d",
  "attestationSources": ["local", "registry"],
  "requireAuditWithin": "90d",
  "registry": "https://npmvc.com",
  "allowPrivateRegistry": false,
  "publisherContinuity": {
    "required": true,
    "onUnauthorizedChange": "block | warn",
    "pinned": { "express": "did:key:z6Mk..." }
  },
  "revocation": {
    "required": true,
    "checkVia": "webvh | none",
    "registryUrl": "https://npmvc.com",
    "maxCacheAge": "10m"
  },
  "waivers": [{
    "package": "legacy-dep",
    "versionRange": "*",
    "reason": "reviewed manually",
    "expiresAt": "2027-01-01"
  }],
  "lifecycleScripts": {
    "postInstall": "forbidden | whitelisted | allowed",
    "whitelist": ["esbuild", "sharp"]
  },
  "licenses": {
    "allowed": ["MIT", "Apache-2.0", "ISC"],
    "denied": ["AGPL-3.0", "SSPL-1.0"]
  }
}

enforcement

block (default) — exit non-zero on any failure, sonpm install aborts. warn — report but allow. off — skip checks entirely.

minAge

Reject versions published less than this duration ago. Formats: 7d, 24h, 30m, 1y. Falls back to a verified PublishTimestampCredential when the public npm registry can't be reached.

unattested

Packages with no attestation bundle. allow accepts silently; warn logs (default); block fails. Block is only practical when every dep is attested.

trustedIssuers

Allowlist of DIDs that may sign Provenance / SBOM / Lifecycle credentials. Entries beginning with https:// are treated as signed trust-root URLs: the fetched document must carry an Ed25519 signature from the pinned root DID before its issuers are added.

trustedAuditIssuers + auditMaxAge

Audit credentials count toward coverage only if their issuer DID is in trustedAuditIssuers (empty = accept any) and they're no older than auditMaxAge.

attestationSources

Where to look up envelopes, in order. local reads node_modules/<pkg>/.npmvc/attestations.jsonld; registry fetches from policy.registry. Pre-install needs registry because node_modules doesn't exist yet.

publisherContinuity

Detect when a package's publisher DID changes. pinned maps package names to expected DIDs. did:webvh DIDs sharing the same SCID prefix count as the same identity (legitimate key rotation is allowed).

revocation

When required, the engine fetches the registry's revoked-credential list once per evaluation and refuses any envelope whose credential ID is on it.

allowPrivateRegistry

By default, policy.registry URLs must be https:// and not point at private IPs / metadata endpoints. Self-hosted setups flip this to true.

waivers

Explicit exceptions for reviewed packages. Downgrades failures to warnings. Supports expiresAt.

lifecycleScripts

forbidden — fail on any install script. whitelisted — allow named packages. allowed — no restriction.

licenses

SPDX license filtering. allowed is a whitelist; denied is a blacklist.

← previousPublisher setupnext →REST API