Npm package provenance with Github Actions

Published on April 25, 2023

Introduction

Npm has added a really nice signing feature to the registry for the first time! Package authors can sign package builds for free and clients can verify the how a particular package version was built.

Why use it?

Npm and Github have an issue where if your npm credentials leak, dodgy people can publish packages to npm that look legit. This introduces malicious code into the ecosystem and it’s difficult to detect.

If a package creator signs their builds at the CI/CD source then you can verify that the package was built by the package author and not a malicious actor.

npm signed package ui
npm signed package ui

This solution mostly applies to packages that are included in other packages but tool is a start at improving the supply chain in the javascript ecosystem so I was keen to check it out!

How to configure signing

The Github and npm docs on adding provenance to your package are pretty good so I won’t repeat them here.

There were some issues I came across that I’ll document here.

  1. You have to update your deployment libraries to the latest version(s). E.g. I had to upgrade semantic-release to the latest version.

  2. In your github action you have to set permissions to allow signing. The issue is that if you add one permission to a workflow you have to add all permissions required by the workflow.

    If you’re using semantic release and are tagging your repo or changing any code in your repo as part of the deploy then you’ll need to add the content:write permission to your workflow.

# your workflow
publish:
  permissions:
    id-token: write
    content: write
  1. Add provenance=true to your .npmrc file to enable signing. Make sure the file is not ignored by git. If you keep credentials in your .npmrc file then you should consider using package.json instead.
# package.json
{
  "publishConfig": {
    "provenance": true
  }
}

Wait for npm to process your package. This is much slower with signing than before. It took 10-15 minutes to process my package release on npm.

How to verify a package

You can use the npm UI. There is a prominent badge on the package page that shows if the package is signed or not.

You can see the badge by the version or at the bottom of the package page here on my NestJS ESLint plugin: https://www.npmjs.com/package/@darraghor/eslint-plugin-nestjs-typed

npm signed package ui
npm signed package ui

You can use npm audit signatures to verify any packages that are published with signatures.

Conclusion

It’s pretty easy to setup signing if you use Github Actions and it’s free!

Software supply chain is a huge area of concern for anyone building software so it’s great to see npm and Github working together to improve the situation.

Package provenance is in beta right now but I’d recommend adding signing to any public packages you publish to npm.

Darragh ORiordan

Hi! I'm Darragh ORiordan.

I live and work in Sydney, Australia building and supporting happy teams that create high quality software for the web.

I also make tools for busy developers! Do you have a new M1 Mac to setup? Have you ever spent a week getting your dev environment just right?

My Universal DevShell tooling will save you 30+ hours of configuring your Windows or Mac dev environment with all the best, modern shell and dev tools.

Get DevShell here: ✨ https://usemiller.dev/dev-shell


Read more articles like this one...

List of article summaries

#engineering

How to add canonical meta tag in NextJs

It’s important to add a canonical meta tag to your pages to improve SEO or to avoid issues with query params in crawled pages.

You can easily add a canonical meta tag in NextJs by using the next/head component.

#engineering

Open Telemetry in NextJs and NestJs

I wrote about how to use open telemetry with NestJs and React previously.

I wanted to add open telemetry to my NextJs app that calls a NestJs backend. The paradigm of SSR preferred by NextJs is a bit different than the CSR paradigm of React.

I’ll describe the differences and how I added open telemetry to NextJs that propagates to other backend APIs.

#engineering

Comparing next start and next standalone with docker

I wrote about how to use nextjs with docker.

I wanted to compare using next standalone like in the article and just using next start.

#engineering

Force RSA key support for Azure DevOps Git SSH

If you’re using Azure DevOps Git SSH you have to use an RSA key. This is because Azure DevOps doesn…

Comments