actions-cool GitHub Actions Tag Hijack Credential Theft
All 53 reviewed tags for actions-cool/issues-helper and all 15 tags for actions-cool/maintain-one-comment were moved to dangling imposter commits that scraped GitHub Actions runner memory and exfiltrated credentials. GitHub now blocks access to both repositories.
On this page 0% read
Executive Summary
On 2026-05-18, an attacker moved every reviewed tag in actions-cool/issues-helper and actions-cool/maintain-one-comment to unique commits outside each repository’s normal branch history. Workflows resolving those mutable tags executed payloads that downloaded Bun, used Python to read Runner.Worker process memory, extracted secret values, and sent them to t[.]m-kosche[.]com StepSecurity.
As of 2026-06-10, GitHub returns Repository access blocked for both repositories, and unauthenticated Git and API access is disabled issues-helper maintain-one-comment. Blocking prevents new resolution from those repositories but does not remediate credentials exposed by earlier workflow runs, cached action content, or self-hosted runner persistence.
Key Facts
Threat Type: GitHub Action tag hijack and CI credential theft
Affected Actions:
- actions-cool/issues-helper
- actions-cool/maintain-one-comment
Affected Refs:
- 53 issues-helper tags moved to unique imposter commits
- 15 maintain-one-comment tags moved to unique imposter commits
Issues Helper Window: 2026-05-18T19:10:24Z to 2026-05-18T19:13:40Z
Maintain One Comment Window: 2026-05-18T19:30:30Z to 2026-05-18T19:31:09Z
Payload: Bun and Python runner-memory credential scraper
Exfiltration Domain: t[.]m-kosche[.]com
Current Repository Status: blocked by GitHub as of 2026-06-10
Known Good Versions:
Fixed Or Safe Versions:
Confidence: high
Last Verified: 2026-06-10
Evidence Assessment
- confirmed: StepSecurity lists 53
issues-helperand 15maintain-one-commenttag-to-commit mappings, all created in narrow windows and unreachable from the default branch. - confirmed: Controlled execution observed Bun,
gh auth token,sudo python3, reads from/proc/<Runner.Worker PID>/mem, filtering for"isSecret":true, and HTTPS egress tot[.]m-kosche[.]com. - confirmed: GitHub currently blocks both repositories. Current tag targets therefore cannot be independently re-fetched from GitHub.
- unknown: Public reporting does not identify the initial repository-control mechanism or enumerate downstream victims with successful exfiltration.
- corrected: SHA-1
8064d4e...and MD56e79ae...previously listed here belong to the unrelatedart-templatebrowser payload and have been removed.
Impact Determination
| Classification | Criteria | Required evidence | Required action |
|---|---|---|---|
| Confirmed compromise | A run resolved a listed imposter commit and runner telemetry shows the memory-read or exfiltration behavior. | Run metadata, resolved action SHA, process telemetry, DNS/proxy logs, and job permissions. | Disable affected workflows, isolate self-hosted runners, revoke all reachable credentials, and audit downstream use. |
| Presumed exposed | A run used either action by mutable tag in the reported windows and had secrets, privileged GITHUB_TOKEN, deployment credentials, or id-token: write. | Workflow and run history, permissions, environment, and secret/OIDC availability. | Rotate reachable credentials even if egress telemetry is unavailable. |
| Potentially exposed | Affected references exist but run timing, resolved SHA, or permissions are incomplete. | Historical workflow files and Actions run exports. | Block the actions and complete run-level scoping. |
| Not exposed | No affected run occurred, or every relevant run used a verified known-good full SHA and had no affected cached content. | Workflow history, run metadata, and resolved SHA evidence. | Preserve the negative search and enforce full-SHA pinning. |
Timeline
- 2026-05-18T19:10:24Z to 19:13:40Z: The 53 reported
issues-helperimposter commits were created. - 2026-05-18T19:30:30Z to 19:31:09Z: The 15 reported
maintain-one-commentimposter commits were created. - 2026-05-18: StepSecurity publishes the initial report and updates it with the second affected action.
- 2026-06-10: Both GitHub repositories return
Repository access blocked.
Technical Analysis
The compromise abused mutable Git tags as trust pointers. Each affected tag was moved to a separate dangling commit with a plausible build-style commit message. A victim repository did not need a workflow-file change: its next run fetched the attacker-selected commit behind the familiar tag. [1]
The payload downloaded Bun, obtained the current GitHub token, spawned Python with elevated privileges, searched Runner.Worker memory for decrypted secret values, and transmitted encoded results over HTTPS. This can expose credentials that would remain masked in GitHub Actions logs because masking does not prevent the runner process from holding the cleartext value. [1]
Indicators of Compromise
The following indicators of compromise (IOCs) can be used to scope exposure across local repositories, systems, and telemetry exports:
Hashes
- 1c9e803c80cc7fed000022d4c94f4b5bc2e90062
- 147337a919d92f4bf42f02843682d694650f1e22
- 7f6120bb10c870b9fde146961a18e5bf0b3d4401
- c43d668894bebbeea688878ab6774fa405f22251
Domains
- t[.]m-kosche[.]com
Process Patterns
- Bun under /home/runner/.bun/bin/bun
- python3 reading /proc//mem
- gh auth token followed by sudo python3
- tr or grep filtering for isSecret:true
Detection and Hunting
Hunt Manifest: actions-cool-github-actions-tag-hijack-hunt-1
- Title: local repository and exported telemetry scope
- Question: Does the telemetry scope contain patterns associated with actions-cool GitHub Actions Tag Hijack Credential Theft?
- Telemetry Family: process
- Telemetry Context: host filesystem or log export
- Positive Signal: Indicators of compromise matched in telemetry: local repository and exported telemetry scope
#!/usr/bin/env python3
import os
import sys
from pathlib import Path
ROOT = sys.argv[1] if len(sys.argv) > 1 else "."
LOG_ROOT = os.environ.get("LOG_ROOT", "")
OUT = Path(os.environ.get("OUT", "hp-actions-cool-github-actions-tag-hijack-scope"))
DOMAINS = ["t.m-kosche.com"]
HASHES = ["1c9e803c80cc7fed000022d4c94f4b5bc2e90062","147337a919d92f4bf42f02843682d694650f1e22","7f6120bb10c870b9fde146961a18e5bf0b3d4401","c43d668894bebbeea688878ab6774fa405f22251"]
# Collect unique indicators
indicators = set()
for group in [DOMAINS, HASHES]:
for val in group:
if val:
indicators.add(val)
with open(indicators_file, "w") as f:
for ind in sorted(indicators):
f.write(ind + "\n")
print(f"[+] Written unique selectors to {indicators_file}")
# Walk local directory
print(f"[+] Scanning directory: {ROOT} for selectors...")
matches = []
exclude_dirs = {"node_modules", "vendor", "dist", ".git"}
for root, dirs, filenames in os.walk(ROOT):
dirs[:] = [d for d in dirs if d not in exclude_dirs]
for filename in filenames:
filepath = Path(root) / filename
try:
content = filepath.read_text(errors="ignore")
for ind in indicators:
if ind in content:
matches.append(f"{filepath}: found '{ind}'")
except Exception:
pass # pass # return or raise not needed here # pass # return or raise not needed here
if matches:
(OUT / "repository-indicator-matches.txt").write_text("\n".join(matches) + "\n")
print(f"[!] Found {len(matches)} matches in codebase!")
# Optional Log Scanning
if LOG_ROOT and os.path.exists(LOG_ROOT):
print(f"[+] Scanning telemetry log directory: {LOG_ROOT}...")
log_matches = []
for root, _, filenames in os.walk(LOG_ROOT):
for filename in filenames:
filepath = Path(root) / filename
try:
content = filepath.read_text(errors="ignore")
for ind in indicators:
if ind in content:
log_matches.append(f"{filepath}: found '{ind}'")
except Exception:
pass # pass # return or raise not needed here # pass # return or raise not needed here
if log_matches:
(OUT / "exported-telemetry-indicator-matches.txt").write_text("\n".join(log_matches) + "\n")
print(f"[!] Found {len(log_matches)} matches in logs!")
if PACKAGES:
registry_dir = OUT / "registry"
registry_dir.mkdir(exist_ok=True)
print(f"[+] Wrote scope artifacts under {OUT}")
Downstream Abuse Audits
Compromised workstations expose active API credentials, requiring immediate rotated revocation. The following platforms are at risk:
- GitHub OIDC and PATs: Attackers harvested SSH private keys and Git Personal Access Tokens. Auditors must inspect recent action runs and release logs during the exposure window.
- Cloud IAM Credentials: AWS, Azure, and GCP session tokens. CloudTrail and Activity Logs should be queried for AssumeRole or write operations originating from unexpected IP addresses.
- NPM and Package Registries: Publishing tokens and credentials. Registry profiles must be audited for unauthorized version publishes or token additions.
Remediation and Closure
- Remove both actions from all current and historical reusable workflows.
- Replace third-party action tags with reviewed full commit SHAs and dependency-update automation.
- Rotate every credential reachable by a presumed or confirmed exposed run from a clean environment.
- Disable or narrow affected cloud OIDC trust policies before issuing replacement credentials.
- Close only after action references are removed, credentials are replaced, downstream audit results are reviewed, and runner rebuild decisions are documented.
Sources
- StepSecurity: actions-cool GitHub Action compromise - Role: PRIMARY_RESEARCH - Impact: Complete tag-to-commit list, windows, payload behavior, domain, and controlled-run evidence.
- StepSecurity Incident Center - Role: PRIMARY_RESEARCH - Impact: Incident scope and campaign tracking.
- GitHub: actions-cool/issues-helper - Role: DIRECT_SOURCE - Impact: Repository access is blocked as of 2026-06-10.
- GitHub: actions-cool/maintain-one-comment - Role: DIRECT_SOURCE - Impact: Repository access is blocked as of 2026-06-10.
IOC Clipboard
5 IOCst.m-kosche.com t[.]m-kosche[.]com 1c9e803c80cc7fed000022d4c94f4b5bc2e90062 1c9e803c80cc7fed000022d4c94f4b5bc2e90062 147337a919d92f4bf42f02843682d694650f1e22 147337a919d92f4bf42f02843682d694650f1e22 7f6120bb10c870b9fde146961a18e5bf0b3d4401 7f6120bb10c870b9fde146961a18e5bf0b3d4401 c43d668894bebbeea688878ab6774fa405f22251 c43d668894bebbeea688878ab6774fa405f22251