Mini Shai-Hulud's Actions Came Back: A Tag Runs Whatever It Points To

Written by the Rafter Team

As of September 25, 2026.
A workflow line like uses: actions-cool/issues-helper@v2.2.1 does not name code.
It names a tag, and a tag runs whatever it points to when the job starts.
From September 16 to September 24, the tags on two popular actions pointed at malware from May, and nobody had to push anything new for it to run.
What happened
On September 24, Socket reported that two GitHub Actions compromised in the May wave of Mini Shai-Hulud had come back online.
- May 18, 2026: malicious code was introduced into
actions-cool/issues-helperandactions-cool/maintain-one-comment. - May 19: GitHub disabled both repositories.
- September 16: both repositories became reachable again. Their release tags had not been cleaned up and still pointed to the May 18 content.
- September 24: Socket published its findings and reported the actions to GitHub support.
- By September 25: Socket's update says GitHub has disabled both repositories again.
Socket says it could not determine why the repositories were re-enabled, and that a request from the legitimate maintainers is one possibility it has not confirmed.
Both actions do routine housekeeping: labeling and commenting on issues, keeping a single bot comment up to date.
GitHub's dependency graph lists about 15,000 repositories that depend on issues-helper alone.
What the payload could reach
According to Socket, the compromised tags run a wrapper that installs the Bun runtime, runs an obfuscated index.js, and only then hands off to the normal action logic.
The job looks like it did its usual work.
That code runs inside the workflow, so it has the workflow's GITHUB_TOKEN and any secrets the workflow exposes.
Socket's May analysis of the same campaign lists what Mini Shai-Hulud goes after: GitHub and npm tokens, AWS credentials, Kubernetes service-account material, Vault tokens, SSH keys, Docker auth files and database connection strings.
Timing made the exposure worse.
Socket notes that workflows calling these actions "usually run on a daily schedule or whenever someone opens an issue or pull request," so most affected repositories probably ran the payload within a day of September 16.
In a public repository, a workflow triggered on issues: opened runs when anyone opens an issue, a pattern we looked at in the GitHub issue as an attack surface.
Why the tags still worked
A Git tag is a movable pointer.
When the attacker rewrote the tags in May, every workflow that referenced @v2.2.1 or any other release tag followed them.
Disabling the repositories stopped the downloads, but it did not move the tags back.
When the repositories came back, the tags resolved to the May code again.
It is the same weakness behind March's Trivy compromise, where force-pushed tags turned trusted version numbers into a credential stealer.
A team that read "pinned to v2.2.1" as a fixed version had pinned a label.
A disabled action is also a trap of its own. A workflow that referenced either action between May 19 and September 16 most likely failed to fetch it. A team that left that failing reference in place, or only noticed red builds, got green builds back on September 16, running the May payload.
Socket's own conclusion is the useful one: "A workflow pinned to a known-clean commit SHA would not have been affected by either the May compromise or the September re-enablement."
What to do now
- Search every repository you own for
actions-cool/issues-helper@andactions-cool/maintain-one-comment@in.github/workflows/. Include forks that still run scheduled workflows. - Check the runs. For any match, look at the workflow's runs from September 16 onward, and from May 18 to 19 if it ran then. Any run on a tag reference in those windows executed the payload.
- Rotate every secret those workflows exposed. The
GITHUB_TOKENexpires when the job ends, but anything it could write during the run could have changed, so review recent pushes, tags, releases and packages in those repositories for changes you did not make. - Remove the actions or replace them. If you still need one, Socket advises pinning to the full commit SHA of a release you have verified predates May 18. Both repositories are disabled again, so a tag reference will fail for now; do not wait for it to start working.
- Pin every third-party action to a full commit SHA. Keep the version as a comment (
uses: owner/action@<sha> # v2.2.0) so updates stay readable, and let Dependabot or Renovate propose new SHAs as pull requests you review. - Enforce pinning. Organization and enterprise admins can require full-SHA pinning in the allowed-actions policy, so an unpinned reference fails, and can block a specific action with a
!entry. - Check that a SHA belongs to the real repository. GitHub can resolve a commit from anywhere in a repository's fork network, so confirm the SHA is a tagged release on the original repository.
- Give workflows the least they need. Set
permissions:explicitly, and pass secrets only to the jobs that use them. A housekeeping job that labels issues needsissues: writeand nothing from your cloud account.
More on hardening the pipeline itself is in our CI/CD security guide.
A takedown is not a cleanup
Disabling a repository is a pause. Whatever state it was in when it went dark is the state it comes back in, and nobody downstream gets a notice when it does. The only reference that cannot change underneath you is a commit SHA, and the only cleanup you can count on is the one you do in your own workflows.