Most teams think about supply chain risk as "did npm audit find anything bad?"
That is a small part of the problem.
A modern JavaScript delivery pipeline trusts:
- the packages you install
- the transitive packages they install
- the GitHub Actions you execute
- the tokens those workflows can access
That is a meaningful attack surface, especially once CI has permission to comment on PRs, publish packages, deploy infrastructure, or push to the default branch.
The First Easy Win: Pin External Actions
This is weaker than many teams realize:
uses: vendor/example-action@v2
The tag can move.
If you rely on third-party actions, pin to a full commit SHA and review updates intentionally:
uses: vendor/example-action@8f4b7f84864484a7bf31766abe9204da3cbe65b3
That does not make the action safe. It makes the trust decision explicit and reviewable.
Separate Untrusted Execution from Privileged Execution
One of the better workflow patterns is:
- run tests and build steps in an unprivileged workflow
- upload artifacts
- let a separate trusted workflow consume those artifacts if it needs secrets or write permissions
That reduces the chance that untrusted pull-request code executes with a token that can mutate the repository or deployment environment.
Minimize Token Scope
If a workflow only needs read access, give it read access.
If it needs to comment on a PR, do not also let it write contents, administer packages, or deploy infrastructure.
Too many pipelines fail the simplest rule in security engineering: make the blast radius small.
Package Security Is Still Part of It
You should also treat dependency hygiene as normal operational work:
- keep lockfiles committed
- review major dependency changes
- remove packages you do not need
- prefer established maintainers for critical paths
This is not glamorous work. It is how software stays defensible.
Further Reading