npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

node-addon-slsa

v1.0.0

Published

Provenance verification for prebuilt native addons with GitHub attestations

Downloads

4,955

Readme

GitHub repo npm version API docs Ask DeepWiki CI status Test coverage Supply-chain score

node-addon-slsa

Verifies that an npm package and its prebuilt native addon binary were produced by the same GitHub Actions workflow run. Uses sigstore for npm provenance and the Rekor transparency log for binary verification. Aborts npm install with a SECURITY error if any check fails.

No authentication required. No GITHUB_TOKEN.

Private repositories: the attest-public action logs repository name, workflow paths, commit SHAs, and run URLs to the public Rekor transparency log. Source code stays private.

Threat model

Trusts GitHub Actions (build environment, attestation authority) and the sigstore public-good instance (Fulcio CA, Rekor). If either is compromised, verification may pass for malicious artifacts.

Protected

| Threat | Mitigation | | ----------------------------- | ------------------------------------------------ | | Tampered npm package | sigstore provenance verification | | Tampered GitHub release | Rekor transparency log + sigstore | | Mismatched artifacts | Same workflow run check via Run Invocation URI | | Man-in-the-middle on download | SHA-256 hash verified against signed attestation | | Path traversal via addon.path | Resolved path must stay within package directory |

Not protected

  • Compromised CI workflow — attestations will be valid for malicious code. This tool verifies provenance, not intent.
  • Compromised maintainer account — write access to the repository allows producing legitimately attested malicious builds.
  • Dependency confusion — verifies a single package, not its transitive dependency tree.
  • Version 0.0.0 — verification is skipped (local development). Never publish 0.0.0 to npm.

Setup

1. package.json

{
  "name": "my-native-addon",
  "version": "1.0.0",
  "repository": {
    "url": "git+https://github.com/owner/repo.git"
  },
  "type": "module",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "default": "./dist/index.js"
    }
  },
  "addon": {
    "path": "./dist/my_addon.node",
    "url": "https://github.com/owner/repo/releases/download/v{version}/my_addon-v{version}-{platform}-{arch}.node.gz"
  },
  "scripts": {
    "postinstall": "slsa wget",
    "pack-addon": "slsa pack"
  },
  "dependencies": {
    "node-addon-slsa": "0.7.1"
  }
}
  • addon.path — where the addon is installed (relative to package root)
  • addon.url — download template; {version}, {platform}, {arch} resolve at install time. Any origin is accepted — verification is hash-based against the sigstore/Rekor attestation, so the download host is a mirror, not a trust anchor. GitHub Releases is the usual choice; custom CDNs work the same as long as the bytes match.
  • postinstallslsa wget downloads, verifies, and installs the binary on npm install. Pair it with requireAddon: pnpm ≥ 10 blocks postinstall scripts by default, so consumers may never run this hook.
  • pack-addonslsa pack gzip-compresses the binary for release
  • repository — github.com URL (HTTPS, SSH, with or without .git). Determines the expected source repository for attestation checks.

2. CI workflow

jobs:
  build-addon:
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-24.04, macos-15, windows-2025]
    runs-on: ${{ matrix.os }}
    permissions:
      contents: write # release upload
      id-token: write # OIDC token for sigstore
      attestations: write # build provenance
    steps:
      - uses: actions/checkout@v6
      # ... set up toolchain, build native addon ...
      - name: Compress binary for release
        run: npx slsa pack
      - name: Attest binary provenance
        uses: vadimpiven/node-addon-slsa/attest-public@<commit-sha> # pin to SHA
        with:
          subject-path: dist/my_addon-v*.node.gz
      - name: Upload binary to release
        uses: softprops/action-gh-release@v2
        with:
          files: dist/my_addon-v*.node.gz

  publish:
    needs: build-addon
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write # npm provenance via OIDC
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          registry-url: https://registry.npmjs.org
      - run: npm ci
      - run: npm publish --provenance --access public

Pin the attest-public action to a commit SHA, not a mutable tag.

Each matrix runner produces a platform-specific binary. The {platform} and {arch} placeholders resolve to process.platform and process.arch at install time.

3. Loading the addon

import { requireAddon } from "node-addon-slsa";

type MyAddon = { greet(name: string): string };

export const addon = await requireAddon<MyAddon>();

Walks up from the caller's file to the enclosing package.json, then downloads and provenance-verifies the binary if missing. Subsequent calls are a stat plus require — safe to invoke at module load.

  • T defaults to unknown; supply the addon's type at the call site.
  • Pass { from: import.meta.url } when the caller lives outside the consuming package (e.g. a re-export wrapper).
  • RequireAddonOptions extends VerifyOptions; see error handling for failure modes.

API reference

CLI

| Command / Option | Purpose | | ---------------- | ---------------------------------------------- | | slsa wget | Download, verify, and install the native addon | | slsa pack | Gzip-compress the native addon for release | | --help, -h | Show usage information | | SLSA_DEBUG=1 | Debug logging to stderr |

Programmatic API

import {
  verifyPackageProvenance,
  verifyAddonProvenance,
  requireAddon,
  isProvenanceError,
  sha256Hex,
  semVerString,
  githubRepo,
} from "node-addon-slsa";
import type { PackageProvenance, VerifyOptions } from "node-addon-slsa";

// Verify npm package provenance via sigstore.
// Returns { runInvocationURI, verifyAddon() }.
const provenance: PackageProvenance = await verifyPackageProvenance({
  packageName: "my-native-addon",
  version: semVerString("1.0.0"),
  repo: githubRepo("owner/repo"),
});

// Verify the addon binary was produced by the same workflow run.
await provenance.verifyAddon({ sha256: sha256Hex(hexHash) });

// Standalone binary verification when you already have a URI.
await verifyAddonProvenance({
  sha256: sha256Hex(hexHash),
  runInvocationURI,
  repo: githubRepo("owner/repo"),
});

// Runtime loader: verify-on-demand, then require the addon.
// Supply the addon's type as T (defaults to `unknown`).
const addon = await requireAddon<MyAddon>();

Types

| Type | Constructor | Purpose | | ------------------ | ------------------------- | ---------------------------------------- | | GitHubRepo | githubRepo(value) | GitHub owner/repo slug | | SemVerString | semVerString(value) | Strict semver (no v prefix) | | Sha256Hex | sha256Hex(value) | Lowercase hex-encoded SHA-256 (64 chars) | | RunInvocationURI | runInvocationURI(value) | GitHub Actions run invocation URL |

Constructors validate at runtime and throw TypeError on invalid input.

Options

All options have sensible defaults. Pass only what you need:

await verifyPackageProvenance({
  packageName: "my-native-addon",
  version: semVerString("1.0.0"),
  repo: githubRepo("owner/repo"),
  // All below are optional:
  timeoutMs: 60_000, // per-request timeout (default: 30s)
  retryCount: 5, // retries after first attempt (default: 2)
  trustMaterial, // pre-loaded via loadTrustMaterial()
  dispatcher, // custom undici Dispatcher
});

Error handling

  • ProvenanceError — verification failed (tampered artifact, mismatched provenance). Do not retry.
  • Error — transient issue (network timeout, service unavailable). Safe to retry.
try {
  await provenance.verifyAddon({ sha256 });
} catch (err) {
  if (isProvenanceError(err)) {
    // Security failure — do not use this package version
  } else {
    // Transient — safe to retry
  }
}

Requirements

  • Node.js >=22.12.0
  • npm package published with --provenance
  • Binary attested with vadimpiven/node-addon-slsa/attest-public