Npm package provenance with Github Actions
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.
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.
-
You have to update your deployment libraries to the latest version(s). E.g. I had to upgrade
semantic-release
to the latest version. -
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
- 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 usingpackage.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
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.