The WFX Phantom campaign shows how stolen developer tokens, legitimate CI permissions and deleted workflow runs can make a compromised repository appear clean.
A GitHub repository can look perfectly normal after an attacker has used it to steal credentials.
That is the central problem exposed by WFX Phantom, a large-scale campaign documented by StepSecurity and Aikido Security on November 12, 2026.
The attackers did not need to exploit a new vulnerability in GitHub Actions.
They already possessed valid GitHub credentials.
They used those credentials to modify repositories, run malicious code through CI and remove the visible execution records.
The result is a difficult incident-response problem: how do you investigate an attack when the attacker also deletes the logs normally used to investigate it?
- The initial probe Aikido Security identified 4,837 compromised accounts involved in probing 61,764 repositories.
The campaign began on November 10.
The attacker’s initial pull request was designed to appear harmless.
Its title was:
docs: dependency audit notes
Its branch was:
wfx-docs
The PR added a small documentation file.
This was not the credential-stealing payload.
It was a way to test whether the compromised account could write to the repository.
That distinction is important.
The presence of the probe is evidence that the relevant account or token was abused.
It does not establish that a malicious workflow subsequently ran.
- The payload used ordinary development permissions Where the attacker had sufficient access, a malicious shell script was inserted into a workflow or a script executed by that workflow.
StepSecurity identified several delivery methods.
One added steps directly to an existing workflow.
Another appended the payload to a shell script that the workflow already ran.
Other variants added a hidden .ci-*.sh file or created a new workflow on a temporary branch.
Common commit messages included:
ci: refresh build cache
chore: add ci helper
chore: add dependency audit workflow
The script was designed to collect credentials available to the workflow environment.
It targeted GitHub tokens, repository secrets, process environment variables, files containing credentials and memory from the GitHub Actions runner.
That runner memory is particularly important.
Secrets used by a job may exist in decrypted form while the job executes.
A script that gains access to the runner environment may therefore obtain information even if it was not directly referenced by the malicious step.
- The cleanup created a false sense of normality After a malicious run started, the attacker pushed a restoring commit.
Where possible, it then deleted the workflow execution record.
StepSecurity documented a case involving drunomics/nuxtjs-drupal-ce.
A malicious commit appeared at 09:17:23 UTC on November 11.
Twelve seconds later, a restoring commit followed.
The visible GitHub Actions history skipped from run #1963 to run #1965.
Run #1964 had been deleted.
This example illustrates why the current contents of a repository are not enough to establish whether it was compromised.
The malicious code may no longer exist on the default branch.
The corresponding workflow run may no longer be visible.
But the original commit may still be recoverable from Git history, audit records or other monitoring systems.
And credentials already collected during execution remain at risk.
- The attacker changed exfiltration methods Early samples sent collected data to external servers using HTTP.
StepSecurity identified additional versions on November 12 that used Telegram.
By approximately 05:30 UTC, new samples were observed sending data exclusively through Telegram rather than the earlier collection IP addresses.
Become a Medium member
This means a search limited to the original known IP addresses may miss later activity.
It also illustrates the importance of investigating behavior rather than relying entirely on one network indicator.
Unusual outbound connections, reads of runner memory and suspicious workflow modifications may provide stronger evidence when the payload evolves.
- Cloud credentials increased the impact The payload’s objectives extended beyond GitHub.
It attempted to obtain credentials for AWS, Azure, GCP and other services.
StepSecurity also found logic intended to create persistent access.
Examples included changes to AWS trust policies and the creation of additional Azure federated identity credentials.
These were capabilities present in the malicious code; the investigation does not establish that every attempt succeeded.
However, they matter for response planning.
Rotating a GitHub token may not be enough if the malicious workflow also obtained credentials for a cloud account.
Similarly, replacing one cloud secret may not remove unauthorized trust relationships created during the attack.
The investigation must cover the systems that the compromised workflow could reach.
- A practical investigation checklist Begin with repositories that your organization owns or can modify through collaborator, organization or automation accounts.
Review pull requests created on or after November 10.
Search for the known probe title and branch.
Inspect Git history for the suspicious commit messages, including commits that were later reverted.
Review workflow files, package scripts and shell scripts that CI executes.
Check GitHub Actions run history for unusual missing or deleted runs.
A missing run number is a reason to investigate, not conclusive proof on its own.
Where a suspicious workflow ran, establish which secrets and cloud permissions were available to it.
Review the organization’s audit logs and external monitoring records.
Investigate the cloud environment for unauthorized role changes, access keys and federated identities.
Revoke abused GitHub tokens and rotate potentially exposed secrets.
If a self-hosted runner was involved, inspect the runner host itself as a potentially compromised system.
Do not rely on finding one specific file hash. StepSecurity observed that payload copies varied, so the same hash will not identify every instance.
- This was not a GitHub platform vulnerability The attack involved stolen legitimate credentials.
That is different from demonstrating a vulnerability in GitHub’s core infrastructure.
The compromised identities included both human developers and automation accounts.
In one examined WebdriverIO case, a bot account with permissions to bypass branch protection was used to push unauthorized changes.
The account’s legitimate permissions became the attacker’s permissions.
This is why identity and permission boundaries are so important in CI/CD systems.
A valid signature of who performed an operation cannot by itself establish that the operation was authorized by the real account owner.
- The deeper engineering problem Most software teams use current code, Git history and workflow logs to investigate unexpected behavior.
WFX Phantom targeted all three.
It modified the code.
It executed through legitimate workflow mechanisms.
It restored the code.
And it removed the execution log where possible.
Other evidence can survive.
But it may exist outside the place a developer normally looks.
That creates a practical design requirement: important audit evidence needs to be available independently of the account or workflow being investigated.
Otherwise, an attacker with sufficient permissions can change both the system and the record of what happened.
A repository that looks clean is not proof that no malicious code executed.
The technical question is not simply how to detect an injected script.
It is how to establish trustworthy evidence of execution when the attacker can restore the source and delete the run.
Sources
StepSecurity — WFX Phantom investigation, November 12, 2026
https://www.stepsecurity.io/blog/wfx-phantom-the-github-actions-secret-stealer
Aikido Security — Compromised GitHub accounts push CI secret stealer to tens of thousands of repositories, November 12, 2026
