WFX Phantom uses stolen GitHub tokens to run a CI credential stealer
Attackers used stolen developer and bot tokens to plant a shell stealer in GitHub repositories, then reverted commits and deleted runs. The stealer can collect runner memory and exchange OIDC tokens for cloud access. Newer samples upload through Telegram.
- Disclosed
- Nov 11, 2026
- Public disclosure date
- Severity
- Septic Tank Blew
- No CVE: a breach, not a bug
- Splash zone
- GitHub repositories writable by stolen developer or bot tokens, where the injected workflow, script or package hook can run.
- GitHub Actions · CI/CD · credential theft
- In the wild
- Yes
- StepSecurity observed execution. WebdriverIO recorded unauthorized bot commits.
What happened
The campaign requires a valid token with repository write access and a path to execute the code. It modifies an existing workflow, creates a new workflow, appends to a script CI already calls, or adds a hidden script and hooks it into an npm lifecycle or build/test command. Workflow variants can explicitly pass secrets to the script. Script variants can read runner memory and credential stores when the job has access. Cloud escalation depends on the runner’s credentials and the permissions and trust attached to them. Required-check forgery exists in the payload but was disabled in the samples StepSecurity examined.
StepSecurity found some probe PRs attributed by GitHub to Fly.io’s GitHub App and identified the credentials as user-to-server tokens. It did not establish how they were obtained or find evidence of compromise of Fly.io infrastructure. The research identified overlaps with October GhostAction without attributing both campaigns to one actor.
Nextcloud Docker’s run 2675 executed the injected commit on a self-hosted runner and finished successfully. StepSecurity interpreted the log as evidence of a successful upload. The log does not enumerate the contents of the uploaded archive.
Release artifacts to check
- Packagist
digitalelvis/neuronai-studio3.14.3 contains the script and npm postinstall hook. The hook can execute if npm installs dependencies in the package directory with lifecycle scripts enabled. Composer does not invoke it on its own. StepSecurity recommends pinning 3.14.2 or earlier. - Go module
github.com/onuragtas/docker-envv1.0.278 and v1.0.280, andgithub.com/vkuznet/gocurlv0.0.0-20261111095532-8d5aad0cb0da, carry the payload in workflow files. Normal Go builds do not execute GitHub workflow files. Check go.mod and go.sum, including direct and transitive dependencies, and replace those versions with independently verified inputs. - StepSecurity reports no affected WebdriverIO package release. Verify other releases produced between an injected commit and cleanup using clean source and build records.
Indicators to correlate
- HTTP endpoints at
194.150.166[.]244:8080/exfil,18.143.168[.]96:8080/exfiland153.75.82[.]159:8080/exfil. The older193.32.204[.]199endpoint was still present in some previously implanted GhostAction workflows. HTTP callback values includedb42d70a7aab9140ca19e8249and15f44heehnax8jdf41yx. - Telegram
api.telegram.orgwithsendDocument, chat-1004340163187and bot IDs8708988906,9196217635,9180059428,8902935164,8876515636. Telegram-only samples set the HTTP callback to loopback. - Probe PR
docs: dependency audit notes, bodyRoutine dependency audit notes, branchwfx-docs, filedocs/wfx-audit.mdand blobee6e5addfe591923fc385553cb66cf0d25634a6b. - Commit messages
ci: refresh build cache,ci: restore,ci: cleanup,chore: add ci helper,chore: add dependency audit workflow, andchore: initial commitbefore the workflow in empty repositories. - Branch patterns
chore/[a-z0-9]{8}andci-check-[0-9]{4}; paths matching.ci-[a-z0-9]{6}.shand.github/workflows/build-audit-[a-z0-9]{6}.yml, or changes to existing workflow files, shell scripts orpackage.json. - Steps
Pass runtime,Restore cache <4 characters>orRun audit; variablesWF_CALLBACK,WF_CTOKEN,WF_EXFIL_*,WF_TG_BOTS; staging path.wfx-$$; log stringsmemscan_files,archive_bytes,deliver_retry. - Azure federated credentials named
wfx-ci-*; AWS trust changes granting a wildcard AWS principal, and AWS sessions namedwfx-*.
Crime-scene timeline
Nov 10, 2026
StepSecurity dates the start of the campaign
Stolen GitHub tokens are used to probe repositories and push malicious changes.
Nov 11, 12:30 UTC
WebdriverIO contributor publicly documents two malicious bot commits
The commits hook postinstall. Later the same day, a surviving Nextcloud Docker workflow log documents execution of another variant.
Nov 12, 01:10 UTC
Telegram appears as a backup in one sample
The sample also points to a third HTTP collector.
Nov 12, 2026
StepSecurity publishes its campaign analysis
It saw Telegram-only delivery from about 05:30 UTC and reported over 63,000 probe PR search results at 07:40 UTC. The search count does not measure successful compromises.
Who said what
We list each claim and who made it. Primary sources (the vendor, the researcher, the registry) are marked. Where reports disagree, we grade by the worst credible case.
- StepSecurity original WFX Phantom analysisPrimaryDocuments observed variants, public execution evidence, affected release artifacts, collection endpoints and cloud persistence features.
- WebdriverIO public revert PRPrimaryDocuments the bot’s unauthorized commits, the postinstall hook and proposed response.
- Nextcloud Docker repository commitPrimaryShows the injected change to update.sh.
- Nextcloud Docker workflow run 2675PrimaryRecords the run of update.sh on the injected commit at 12:52 UTC on November 11.