title: "GhostAction Is Harvesting CI Secrets Right Now: A 15-Minute Self-Audit"
tags: security, github, devops, ci
publish: false
Since October 7, a campaign Socket calls GhostAction has been injecting fake "security audit" workflows into legitimate repos via compromised maintainer accounts. GitGuardian counts a second wave hitting 772+ more repositories. StepSecurity puts the tally at 3,000+ secrets stolen. The attack is not a GitHub zero-day — it's the abuse of automation you already trust.
If you run GitHub Actions, you have 15 minutes of homework tonight.
What the attacker actually does
- A compromised maintainer account commits
.github/workflows/security-audit.yml(orgithub_actions_security.yml) with the message "Add security audit workflow". - That workflow runs in your trusted CI, with your secrets in scope. It checks out with
fetch-depth: 0and walksgit log -p --all— meaning secrets you deleted years ago are still in play. - Harvested values (AWS keys with ±2 lines of context, Anthropic/OpenAI/OpenRouter keys, GitHub/GitLab/Google API tokens, Slack, SendGrid, PyPI credentials) are POSTed cleartext over plain HTTP to a single attacker IP.
No exploit. No privilege escalation. Just a workflow file that looks boring and reads everything.
The audit (in this order)
1. Find injected workflow files (2 min):
git log --diff-filter=A --name-only --format=%ci -- \
.github/workflows/security-audit.yml \
.github/workflows/github_actions_security.yml
Any file added on/after 2026-10-07 by a human you can't confirm: guilty until proven innocent.
2. Walk your Actions run history (3 min). Any run you can't tie to your team? Archive the logs before deleting the workflow. The run history is your forensic record.
3. Rotate what was a secret at injection time (5 min). Cloud keys, PATs, PyPI/npm tokens, AI provider keys. Critical nuance: rotating current secrets does not revive history-leaked ones. If it was ever committed and never revoked, revoke it now.
4. Scan history, not HEAD (3 min). gitleaks git . or trufflehog against the full history. A clean working tree proves nothing.
5. Check egress (2 min). Grep network telemetry for past connections to the observed exfil endpoint (193.32.204.199, plain HTTP — a detection gift), then block it.
The structural lesson
CI runners are secret readers by design. Every repo where a pull_request-triggered workflow gets shell access to secrets, or where a maintainer commit lands straight on the default branch, is a GhostAction-shaped hole. The cheap fixes that would have made this campaign starve:
- Per-workflow minimal
permissions:(not the org default of "write everything") - Require review before commits land on the default branch
- No secrets on fork-triggered runs, and never interpolate secrets into
run:strings where PR-controlled code can echo them back
That last one is the quiet sister of GhostAction: your secrets don't need to be stolen by a botnet if a fork's PR code can print them from inside the runner. Same hole, smaller burglar.
I write about collection-layer scraping and CI security from the audit side; the methodology posts are free on my dev.to. If this saved you a bad Friday, tell a teammate who ships workflows on autopilot.
Free tooling from the same pipeline: GhostAction event brief ($ PWYW) · Telegram OSINT bundle sample (PWYW) · full methodology posts free here on dev.to.
Top comments (0)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.