critical

CVE

Not assigned

CWE

CWE-506, CWE-494, CWE-829

Affected Surface

  • GitHub Actions workflows that referenced `actions-cool/issues-helper` by tag, including `@v2.2.1`, between 2026-09-16 and the second disablement reported on 2026-09-25
  • GitHub Actions workflows that referenced `actions-cool/maintain-one-comment` by tag during the same window
  • GitHub-hosted and self-hosted runners that executed the re-enabled action code while `GITHUB_TOKEN`, cloud credentials, or other `${{ secrets.* }}` values were in scope
  • Repositories whose issue or pull-request housekeeping jobs flipped from `Error: Repository access blocked` failures to long successful runs after 2026-09-16

The most useful new supply-chain story from the last three days is not a fresh npm publish or a new PyPI wheel. It is the moment two already-compromised GitHub Actions came back online with their bad tags still in place.

Socket reported on September 24 that actions-cool/issues-helper and actions-cool/maintain-one-comment had become reachable again on September 16. StepSecurity’s May analysis had already shown what those tags pointed to: imposter commits that download Bun, read Runner.Worker memory, and exfiltrate decrypted workflow secrets. GitHub disabled both repositories again on September 25, but the exposure window still matters. Any workflow that referenced one of those actions by tag and ran between September 16 and that second disablement should be treated as a CI secret-exposure event.

The operational detail that makes this incident different is that the attacker did not need to do anything new in September. No fresh package upload was required. No new tag move was required. Making the repositories downloadable again was enough.

What was affected

The affected actions were:

  • actions-cool/issues-helper
  • actions-cool/maintain-one-comment

StepSecurity’s original May investigation found that every tag in both repositories had already been repointed to imposter commits:

  • issues-helper: 53 compromised tags
  • maintain-one-comment: 15 compromised tags

One concrete example from the September reactivation is the tag many downstream workflows still used:

uses: actions-cool/issues-helper@v2.2.1

According to Socket, when that workflow ran after September 16, the runner resolved @v2.2.1 to:

a0c53dd42fc842d2f9276c5a1d4f9a26abe8713d

That matters because GitHub Actions resolves tag references at job setup time. A mutable tag is not a pin. It is a lookup.

Socket also notes that issues-helper alone had roughly 15,000 dependent repositories in GitHub’s dependency graph. That does not mean 15,000 confirmed September victims. It does mean the blast radius was large enough that routine issue-maintenance jobs could restart the malware across a wide slice of public repositories without any maintainer changing their workflow file.

Why September did not need a new compromise

The September event was a reactivation, not a new intrusion. The attacker had already poisoned the tags in May. GitHub’s earlier containment step was to disable repository access. While the repositories stayed disabled, jobs that depended on the actions failed before any third-party code could run.

Socket’s before-and-after runner history is the clearest proof:

Before re-enablement:
Getting action download info
Error: Repository access blocked

After re-enablement:
actions-cool/issues-helper@v2.2.1 -> a0c53dd42fc842d2f9276c5a1d4f9a26abe8713d
oven-sh/setup-bun
bun run $GITHUB_ACTION_PATH/index.js

That transition is the whole story. The workflow file in the downstream repository did not have to change. The action tag did not have to move again. As soon as GitHub allowed the repository to be fetched, the next scheduled or event-triggered run pulled the same malicious code that had been sitting behind the tag since May.

This is why the September incident belongs in the same response bucket as a new supply-chain publish. For the consumer, old malicious content becoming reachable again is functionally the same as a new malicious release.

What the action ran on the runner

StepSecurity’s May teardown remains the best technical reference for the payload that September reactivated. The important path is compact:

tag reference
  -> imposter commit index.js
  -> Bun downloaded to the runner
  -> child python3 process reads /proc/<Runner.Worker PID>/mem
  -> memory filtered for "isSecret":true
  -> exfiltration to t.m-kosche.com

The runner-side markers StepSecurity captured were concrete enough to hunt directly:

/home/runner/.bun/bin/bun
/proc/<Runner.Worker PID>/mem
gh auth token
tr/grep "isSecret":true
t.m-kosche.com:443

The Runner.Worker memory read is the detail AppSec teams should focus on. GitHub Actions decrypts secrets for the job, and the runner process holds that material in memory while the job is live. The malicious action does not need a bug in your application. It runs inside the same trusted automation context that already has your GITHUB_TOKEN, cloud credentials, registry tokens, and whatever else the workflow exposes.

That is also why the affected actions were dangerous even though they looked low-impact on paper. These are issue and comment housekeeping actions. Many teams treat them as harmless automation because they do not build artifacts or deploy code. The payload did not care. It only needed a job with secrets.

Why this still matters after the packages were cleaned up

The same Mini Shai-Hulud campaign family already produced package-registry incidents that public vulnerability records now track under CVE-2026-45321 and CVE-2026-46421. Those records cover malicious @tanstack/* and @cap-js/* publishes that followed GitHub Actions trust failures earlier in the year.

September cut one step out of that chain.

In the earlier package cases, the attacker used CI compromise to publish bad artifacts into npm. In the actions-cool reactivation, there was no need to republish anything. A stale tag on a third-party action was enough to recover execution. That makes the lesson broader than “watch your package manager.” Your CI dependency graph includes GitHub Actions, and a disabled action is not safe forever if its tags still point at bad code.

What to look for in real repositories

Start with workflow references:

rg -n 'actions-cool/(issues-helper|maintain-one-comment)@' .github/workflows

Then inspect historical logs or exported run artifacts for the reactivation markers:

rg -n \
  'Repository access blocked|a0c53dd42fc842d2f9276c5a1d4f9a26abe8713d|oven-sh/setup-bun|bun run \\$GITHUB_ACTION_PATH/index\\.js|t\\.m-kosche\\.com' \
  actions-logs/ . 2>/dev/null

If you archive workflow telemetry, the September window to review is:

2026-09-16 through 2026-09-25

The strongest runtime signal is a job that used to die in seconds during setup and then started succeeding for several minutes without a corresponding workflow change in the repository. Socket documented exactly that pattern in public workflow histories.

Also audit for workflows that expose more than they need. Jobs triggered by issues, issue_comment, pull_request, or daily schedules often carry more secrets than their task justifies. A compromised housekeeping action turns that convenience into attacker inventory.

Response guidance

  1. Remove both affected actions from workflows, or replace them with a reviewed in-repo implementation.
  2. If you must keep equivalent functionality, pin only to a verified clean full commit SHA. Do not switch from one tag to another tag.
  3. Rotate every secret that affected workflows could access between September 16 and September 25, including GITHUB_TOKEN scopes, cloud credentials, registry tokens, SSH keys, and chat or AI-tooling credentials present in the job.
  4. Review repository history and downstream artifacts produced during the window, especially if the workflow had write access back to the repository.
  5. Preserve runner logs before cleanup. In this incident the logs are often more useful than the repository tree because the dangerous transition happened during action resolution and job setup.

The main lesson from the actions-cool reactivation is simple. Supply-chain incidents do not always begin when new malicious code is published. Sometimes the dangerous event is that old malicious code becomes reachable again.

From research to remediation

Check whether this pattern exists in your codebase

Turn this research into a remediation workflow. Scan dependencies and package manifests for similar supply-chain risk, then prioritize fixes with reachability context.

References