JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 99
  • Score
    100M100P100Q70305F
  • License Apache-2.0

Verifiable-credential supply chain compliance for npm. Sign attestations, verify dependencies, revoke compromised packages.

Package Exports

  • @ajna-inc/npmvc
  • @ajna-inc/npmvc/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@ajna-inc/npmvc) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

@ajna-inc/npmvc

Supply-chain credential system for npm. Sign attestations when you publish, verify every dependency when you install.

Pure TypeScript. Zero native dependencies. Works everywhere npm runs.

Quick start — consumer

npm install -g @ajna-inc/npmvc
npmvc install-hook              # default preset: "balanced"
# or:
npmvc install-hook --preset strict     # block on unattested too
npmvc install-hook --preset permissive # warn-only, never blocks

This adds a preinstall hook to your package.json and writes npmvc-policy.json. Every subsequent npm install then runs npmvc verify first.

What each preset does

Preset Bad signature Tampered bytes Revoked credential Unattested dep
strict block block block block
balanced (default) block block block warn
permissive warn warn warn warn

Most of npm is still unattested, so balanced warns on unattested deps but blocks the explicitly-bad ones. Flip to strict once your internal packages are all attested.

There is no env-var bypass. To temporarily disable, edit package.json#scripts.preinstall directly.

Quick start — publisher

npm install -g @ajna-inc/npmvc
npmvc init                                        # plaintext key
# or:
npmvc init --encrypt --passphrase "..."           # encrypted at rest

npm pkg set "publisher"="$(jq -r .did ~/.npmvc/wallet/key.json)"
npm pkg set scripts.prepack="npmvc attest --registry https://npmvc.com"
npm pkg set files='["dist", ".npmvc"]' --json

Every subsequent npm publish now runs attest first: signs Provenance + Lifecycle + SBOM credentials, binds them to the content of the tarball, and uploads to the npmvc registry.

To rotate the keys you sign with, see SECURITY.md.

What gets checked

  • Signatures — DSSE envelopes verified against publisher DID (Ed25519)
  • Tarball digest — installed bytes are hashed and compared to the signed claim
  • Revocation — credentials revoked by the publisher are refused
  • Age — versions younger than minAge (default 7d) are flagged
  • Publisher continuity — DID changes across versions block (did:webvh rotations are allowed via SCID-prefix matching)
  • Trust roottrustedIssuers URL fetched, Ed25519-signed by the pinned root DID
  • Lifecycle scriptspostinstall flagged unless whitelisted
  • Transitive deps — full lockfile tree (npm, pnpm, yarn)
  • Audit credentials — third-party scanner verdicts with trustedAuditIssuers + auditMaxAge
  • SBOM — CycloneDX SBOM signed and bundled

Policy

npmvc-policy.json, written by install-hook --preset <name>:

{
  "enforcement": "block",
  "transitive": true,
  "minAge": "7d",
  "unattested": "warn",
  "unattestedMinAge": "30d",
  "trustedIssuers": ["https://npmvc.com/trust-root.json"],
  "trustedAuditIssuers": [],
  "auditMaxAge": "180d",
  "attestationSources": ["local", "registry"],
  "registry": "https://npmvc.com",
  "allowPrivateRegistry": false,
  "publisherContinuity": {
    "required": true,
    "onUnauthorizedChange": "block",
    "pinned": { "express": "did🔑z6Mk..." }
  },
  "revocation": {
    "required": true,
    "registryUrl": "https://npmvc.com",
    "maxCacheAge": "10m"
  },
  "lifecycleScripts": { "postInstall": "whitelisted", "whitelist": [] },
  "waivers": []
}

Set allowPrivateRegistry: true if you point registry at an internal mirror or http:// host. By default the SSRF guards refuse private IPs.

CI/CD

Publish from GitHub Actions:

- name: Attest + Publish
  env:
    NPMVC_KEY: ${{ secrets.NPMVC_KEY }}                  # contents of ~/.npmvc/wallet/key.json
    NPMVC_KEY_PASSPHRASE: ${{ secrets.NPMVC_KEY_PASSPHRASE }}  # only if the key is encrypted
    NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
  run: |
    npm install -g @ajna-inc/npmvc
    mkdir -p ~/.npmvc/wallet && echo "$NPMVC_KEY" > ~/.npmvc/wallet/key.json && chmod 600 ~/.npmvc/wallet/key.json
    npm publish --access public

prepack runs npmvc attest automatically before npm packs the tarball.

See packages/github-action for a packaged action with the same behaviour.

Key management

npmvc wallet encrypt --passphrase "..."   # encrypt the in-use key at rest
npmvc wallet decrypt --passphrase "..."   # undo (back to plaintext)
npmvc wallet export  --passphrase "..." > key.enc      # portable encrypted backup
npmvc wallet import  --passphrase "..." --input key.enc  # restore from backup

# Recovery (lost key, guardians configured)
npmvc wallet add-guardian   --did did🔑z6MkFRIEND...
npmvc wallet set-threshold  --threshold 2
npmvc wallet recover        --old-did did🔑... --guardians did🔑a,did🔑b
npmvc wallet approve-recovery --request recovery-request.json
npmvc wallet apply-recovery --approvals approval-1.json,approval-2.json

# Rotation (did:webvh only)
npmvc wallet rotate

Commands

Command Purpose
init [--encrypt --passphrase ...] Create publisher DID
attest [--registry URL] Sign attestations + optionally sync to registry
verify Verify the installed dep tree
install-hook [--preset strict|balanced|permissive] Add preinstall hook + policy
policy init / policy show Manage the policy file
register Register your DID on an npmvc registry
audit publish / audit import Issue / import a third-party scanner credential
credential revoke Revoke a credential on the registry
credential handover Sign a maintainer-handover credential
wallet encrypt / decrypt Toggle at-rest encryption of the key file
wallet export / import Encrypted key backup
wallet rotate (did:webvh) Rotate to the pre-committed backup key
wallet add-guardian, set-threshold, guardians Recovery setup
wallet recover, approve-recovery, apply-recovery Recovery flow
anchor publish Build a transparency-log Merkle root

Threat model and trust root

See SECURITY.md for the pinned community trust-root DID, rotation policy, and known limitations.

Packages in this repo

  • @ajna-inc/npmvc (the CLI) — root package.json, sources in src/
  • packages/npmvc-web — the npmvc.com registry/UI
  • packages/github-action — GitHub Action wrapper
  • packages/verdaccio-plugin — early-stage stub, not for production use

License

Apache-2.0