Skip to content

Use NPM provenance to improve supply chain security #2676

Open
@paulmillr

Description

@paulmillr

Most package pages on the npm registry have a link to a source repository, but this information isn’t verified and doesn’t point at any specific commit. With the code explorer you can view the contents of a package before you install it, but this doesn’t help you determine where it came from.
What we need is a way to draw a direct line from the npm package back to the exact source code commit from which it was derived. Much like an art historian tracking the chronology of ownership for a painting, we need a statement of provenance for a package which provides a verifiable record of the originating source and the build steps which were used to assemble the final artifact.

How do we ensure the compiled code published to NPM is the same that has been generated from building it by hand? There are two ways:

  1. Store compiled JS code in the repository. Cons: Messes-up diffs, git logs. A huge pain.
  2. Use publicly verifiable transparency logs and CI. NPM started providing it in Apr 2023! The blog post.

Check out bottom of README of https://www.npmjs.com/package/micro-eth-signer, there's new section:

shot

Steps I took:

  1. Create granular NPM access token. It's granular, meaning, it's limited to specific packages and can't touch anything else.
  2. Add this NPM_PUBLISH_TOKEN to GitHub repository secrets.
  3. Add publish-npm.yml to .github/workflows for GitHub Actions CI.
  4. Create new GitHub Release, by hand.

What happened immediately after step 4:

  1. GH CI ran an action that followed steps specified in publish-npm.yml.
  2. It set up a VM, installed node.js of specific version, executed npm install, execute npm run build
  3. It published the output to NPM
  4. It added signed logs to append-only ledger, which allows to verify the build was done properly

This was done manually - but I see our monorepo uses some automated way to generate github releases. It can be combined with software like changesets, which will automatically generate pull requests. Take a look at how sigstore-js did it.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions