almessadi.
Back to Index

Treat Your Dependency and CI Pipeline as an Attack Surface_

Supply chain security is not just about vulnerable packages. It also includes action pinning, token scope, artifact trust, and separating privileged workflows.

PublishedApril 22, 2024
Reading Time8 min read

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:

  1. run tests and build steps in an unprivileged workflow
  2. upload artifacts
  3. 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