Safeguard
Software Supply Chain•

How do you publish a modern npm package securely?

Commit your lockfile, publish from CI with provenance or trusted publishing, and say what provenance does not prove. A short guide for package authors.

Safeguard Security Team
4 min read

To publish a modern npm package securely, build it in cloud CI, publish with provenance or trusted publishing so users can trace it to source, keep your own lockfile committed, and keep dependencies few. Provenance proves where a package was built. It does not prove the code is safe.

What does provenance actually give a user?

npm lets you generate provenance statements for packages you publish. There are two kinds of attestation. The provenance attestation links the package to its source code and build instructions from the build environment. The publish attestation is generated by the registry when an authorized user publishes.

Packages published with provenance are signed using Sigstore public good servers and recorded in a public transparency log. A user can then check where and how the package was built before installing it.

The npm documentation is direct about the limit: provenance does not guarantee a package has no malicious code. It gives a verifiable link to the source and build, which developers can then audit and decide whether to trust. Say the same in your own README if users ask what the badge means.

What do you need in place?

The npm docs list prerequisites. Use npm CLI 9.5.0 or later. Make sure the repository field in package.json points to a public repository and matches, case sensitive, where you publish from. Build on a supported cloud CI provider with a cloud hosted runner, which today means GitHub Actions or GitLab CI/CD.

Trusted publishing goes a step further. When you use it, provenance attestations are generated automatically without a flag, and you do not need a long-lived publish token sitting in your CI secrets. That token is the thing attackers most want to steal from a maintainer.

Do you commit package-lock.json?

For an application, yes. The npm docs say the lockfile describes the exact tree so teammates, deployments and CI install the same dependencies, and that it is meant to be committed.

For a library, the picture differs. A package-lock.json cannot be published and is ignored anywhere except the root project. So your lockfile protects your own build and tests, not your users. They resolve your declared version ranges on their own. A file called npm-shrinkwrap.json can be published, but npm says that is not recommended unless you ship a command line tool or use publishing to produce production packages.

The practical consequence for a library author is to keep your dependency list short, because every dependency you declare lands in every user's tree.

A constructed example

A maintainer has a small date helper library with eleven dependencies, two of which are only used for one formatting function. A user reports an advisory in one of those two. Every downstream project now has to deal with it. The maintainer removes both, writes thirty lines of code instead, and the advisory disappears from the library's tree. Fewer declared dependencies meant less exposure for everyone who installs it.

How to check or apply this

  1. Move publishing out of laptops and into a supported cloud CI job.
  2. Turn on trusted publishing, or publish with provenance, and confirm the attestation shows on the package page.
  3. Match the repository field exactly to the publishing repository.
  4. Commit package-lock.json for your own builds and install in CI with npm ci.
  5. Audit every declared dependency and remove those you can replace cheaply.
  6. Protect the maintainer accounts with multi-factor authentication.
  7. Document in your README what provenance does and does not tell users.

Safeguard can scan a package's dependency tree before you publish and show which flagged code is reachable. The free scan at gold.safeguard.sh/scan covers up to 100 dependencies.

Quick check

Does a provenance badge mean the package is safe?

No. It shows where and how the package was built. You still decide whether to trust the source and the maintainers.

Should a library publish its lockfile?

Generally no. package-lock.json cannot be published, and npm discourages shrinkwrap except for command line tools and similar cases.

Sources

Last reviewed: 18 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.