I Audited Our GitHub Actions and Now I Can't Sleep
A look at the supply chain risks hiding in your CI/CD pipelines. Spoiler: it's worse than you think.
On this page
Last month I decided to actually look at what third-party GitHub Actions we use across our repos.
I wish I hadn’t.
The Audit
Started simple: just list all the third-party Actions used in our workflows.
# Find all GitHub Actions across repos
grep -r "uses:" .github/workflows/ | grep -v "actions/" | sort -u
Found 47 distinct third-party Actions across 23 repositories.
Then I asked some questions about each one:
- Who maintains it?
- When was it last updated?
- Is it pinned to a SHA or a mutable tag?
- What permissions does it request?
- Do we actually need it?
The answers were… not great.
What I Found
1. Mutable Tags Everywhere
# What most of our workflows looked like
- uses: some-action/thing@v1
# What they should look like
- uses: some-action/thing@a1b2c3d4e5f6...
Out of 47 Actions, 41 were pinned to tags like v1, v2, latest.
This means: the maintainer can push a malicious update, and next time our workflow runs, we execute their code with no review.
2. Abandoned Projects
Several Actions we depended on:
- Last updated 2+ years ago
- Maintainer hadn’t responded to issues in 18 months
- Had open security issues with no fixes
We were running this code in CI with access to our secrets.
3. Excessive Permissions
Found an Action we used for “formatting checks” that requested:
contents: writepull-requests: writeissues: write
For formatting checks. Why?
Turns out it had some auto-fix feature nobody used that required write access. But every workflow run was granting these permissions whether the feature was used or not.
4. Dependency Chains
One Action I investigated:
Our workflow
→ uses action-a
→ internally uses action-b
→ internally uses action-c
→ runs npm install with package.json that pulls 200 packages
We were implicitly trusting hundreds of packages through a single uses: line.
5. Fork of Fork of Fork
Traced one Action’s history:
- Original project abandoned in 2021
- Fork created, maintained briefly, abandoned 2022
- Fork of fork created, that’s what we used
- Fork of fork’s maintainer: anonymous GitHub account with no other activity
We were running code from an anonymous stranger with access to our deployment secrets.
Why This Matters
GitHub Actions run in your CI/CD environment. Depending on your setup, they might have access to:
- Source code
- Deployment credentials
- AWS/GCP/Azure keys
- NPM/PyPI publish tokens
- Production secrets
- Customer data (if tests use real data)
A compromised Action can:
- Steal all of the above
- Inject code into your builds
- Modify your releases
- Persist access through compromised dependencies
This isn’t theoretical. We’ve seen it happen:
event-streamincident (2018)ua-parser-jscompromise (2021)node-ipcmalicious code (2022)tj-actions/changed-filescompromise (2023)
What We’re Doing About It
1. SHA Pinning
Every Action now pinned to full SHA:
# Before
- uses: actions/checkout@v4
# After
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
Yes, it’s ugly. Yes, you have to update it manually. Yes, it’s worth it.
We use Dependabot to propose updates, then review before merging.
2. Vendoring Critical Actions
For critical workflows (releases, deployments), we forked and vendored the Actions:
# Instead of external
- uses: some-org/deploy-action@sha
# Use our fork
- uses: our-org/vendored-actions/deploy@sha
We control the code. We review changes. It’s extra work, but these workflows have production access.
3. Permission Minimization
Every workflow now has explicit, minimal permissions:
permissions:
contents: read
# Only add more if actually needed
Most Actions work fine with read-only access. The ones that don’t need scrutiny.
4. Action Allowlist
Implemented an allowlist of approved Actions. Workflows using non-approved Actions fail in CI.
This forces a review process for new Action additions.
5. Regular Audits
Quarterly review of:
- What Actions are in use
- Whether they’re still maintained
- Whether we still need them
What You Should Do
If you haven’t audited your Actions recently:
Step 1: Inventory
find . -name "*.yml" -path "*/.github/workflows/*" -exec grep -l "uses:" {} \;
Step 2: Check pins
Are you using SHAs or tags? Tags are mutable.
Step 3: Review permissions
What can each workflow do? What can each Action access?
Step 4: Assess maintainers
Who are you trusting? Are they trustworthy?
Step 5: Minimize
Do you need that Action? Could you use a built-in alternative?
The Uncomfortable Truth
Modern software development requires trusting a lot of strangers.
Every npm install, every pip install, every uses: is an act of trust. We trust that:
- The code does what it claims
- The maintainer isn’t malicious
- The maintainer’s account isn’t compromised
- The dependencies are also trustworthy
Usually this trust is justified. But “usually” isn’t “always.”
The Codecov bash uploader incident, the SolarWinds compromise, the countless npm package hijacks - these aren’t anomalies. They’re the inevitable result of software supply chains built on implicit trust.
My Current Paranoia Level
After this audit:
- Critical workflows (deployments, releases): Vendored Actions only, reviewed quarterly
- Standard workflows (tests, linting): Approved Actions only, SHA-pinned
- Development workflows (convenience stuff): Minimal permissions, monitored
Is this overkill for most organizations? Probably.
Is the alternative “hope nobody compromises the random Action you found on the marketplace”? Yes.
Pick your risk tolerance.
The uses: keyword is powerful. So is rm -rf /. Both deserve respect.
Related Articles
Authentication Attacks: Passwords, Sessions, and Tokens
How login systems break - brute force, credential stuffing, session hijacking, token flaws, and MFA bypass. The complete beginner's guide to auth attacks.
Cybersecurity Career Paths: Finding Your Direction
Offensive, defensive, GRC, cloud security, AppSec - the major cybersecurity career paths explained. What each role does, what skills you need, and how to choose.
Certifications, Learning Resources, and Next Steps
A practical guide to cybersecurity certifications, free and paid learning resources, communities, and building a plan for your first year in security.