Most attacks on software no longer go after the application code itself. They go after everything around it: developer accounts, CI runners, dependency managers, package registries, cloud identities and the automated workflows that build and ship releases. Each of those is part of your software supply chain, and each one can be a way into production.
The wfx-loot campaign, disclosed by Aikido Security on November 12, 2026, is a textbook case. Starting on November 10, an attacker used stolen GitHub credentials to test write access to repositories, slip malicious steps into GitHub Actions workflows and pull secrets out of CI runners. Aikido counted 4,837 compromised accounts opening probe pull requests in 61,764 repositories, and found that the payload ran and sent credentials out of at least 1,835 of them.
The takeaway for DevSecOps and AppSec teams is not that GitHub Actions is unsafe. It’s that CI/CD is now a high-value identity and privilege boundary, and it deserves the same care you give production.
How the attack worked
There was no zero-day here and no direct attack on a build server. The attacker started with GitHub accounts that already had write access to repositories.
For each repository a stolen token could reach, the attacker opened a pull request titled docs: dependency audit notes from a branch called wfx-docs. It looks harmless, and that’s the point. The pull request was a probe: if it went through, the attacker knew the account could write to that repository. Many of these probes were still open when Aikido published its findings.
Where write access was confirmed, the payload went in through one of three routes:
- Workflow injection. A commit titled
ci: refresh build cacheadded roughly 1,500 lines to an existing GitHub Actions workflow. - Install hook. A commit titled
chore: add ci helperadded a.ci-xxxxxx.shscript and apostinstallhook topackage.json, so the script ran on anynpm install. - Throwaway branch. A commit titled
chore: add dependency audit workflowcreated a new workflow file on a short-lived branch.
Whichever route it used, the attacker reverted the change within about a minute and then deleted the workflow run and its logs. In a busy repository with frequent commits, automated dependency updates and lots of contributors, a change that lives for under a minute is very easy to miss. Often the only trace left is a gap in the workflow run numbers.
Why CI secrets are such a prize
A CI runner frequently holds more privilege than any single developer laptop. To do its job, a workflow may need source code, package registries, container registries, a secrets manager, cloud roles, deployment targets and signing keys. It can also inherit environment variables, OIDC tokens, cloud credentials and repository or organization secrets.
The wfx-loot payload took far more than repository secrets. According to Aikido, it collected:
- GitHub Actions secrets and variables, the
GITHUB_TOKEN, and OIDC and runtime tokens - Credential files for AWS, Azure, GCP, Docker, Kubernetes, npm, PyPI, Git, SSH, Vault and Terraform
- API keys and credentials for AI providers and coding tools
- Shell histories,
.envfiles, private keys and kubeconfig files - The process memory of the GitHub Actions runner itself
Everything was packed into a compressed archive and sent over HTTP to one of two attacker servers. It didn’t stop at collection either. The script used the runner’s OIDC tokens to move into AWS, GCP and Azure where trust relationships allowed it.
That’s the blast radius problem. A team may think a workflow can only push a container image. If that same workflow can assume a cloud role, read from a secrets manager or publish to a registry, an attacker who controls it gets all of that too.
Rotating the token isn’t enough
Credential theft is bad. What makes wfx-loot worse is that it was built to survive credential rotation.
Aikido describes three persistence techniques. The payload posted forged “success” status checks using the names of required checks, which lets later changes get past branch protection. It rewrote AWS role trust policies so that any AWS account could assume the role. And it added federated identity credentials named wfx-ci-… to Azure AD applications, pointing back at the compromised repository.
That last one matters a lot. Even after you revoke the stolen GitHub token, a malicious federated identity left on an Azure application means workflows in that repository can still authenticate, with no stored secret needed.
So incident response can’t end with “rotate the GitHub token.” You also need to review cloud trust relationships, OIDC configuration, IAM roles, service accounts, federated identities and every permission your CI workflows hold. That work happens in your cloud-native IAM controls, audit logs and CSPM/CIEM tooling, and it needs to be part of your plan before an incident, not after.
Why this reaches end users
It’s tempting to file this under engineering problems. But once malicious code gets into a build or release pipeline, it doesn’t stay inside the engineering team.
If a compromised workflow publishes a tainted package, container image, browser extension or app update, your users will install it through channels they trust: a package manager, an app store, auto-update or your own download page. To them it looks legitimate, because it came from your official release process. Aikido notes that at least 50 of the compromised accounts belong to people who publish packages to npm, Go, Packagist, PyPI or crates.io.
That’s what makes supply chain attacks so effective. The attacker doesn’t have to break into every customer’s machine. They only need one trusted point in your delivery chain, and your own distribution does the rest.
For end users, the fallout can include stolen browser sessions, cookies, passwords and tokens; exposed files and clipboard contents; extra malware or persistence on their machines; misuse of cloud or SaaS credentials stored locally; and silent redirection of traffic or updates. For the vendor, there’s the loss of trust that follows.
A strong program therefore has to reach past the build server. It needs to cover the packages developers install, the extensions they use, the CI environment that builds the software and the endpoints where people actually work.
Confirmed malicious packages
Aikido found two published packages tied to the campaign, though its main goal appears to have been stealing CI secrets rather than spreading through registries.
| Ecosystem | Package | Affected version(s) | Guidance |
|---|---|---|---|
| Packagist (PHP) | digitalelvis/neuronai-studio | 3.14.3 | Treat any machine that installed or opened this version as compromised. |
| Go | github.com/onuragtas/docker-env | v1.0.278, v1.0.280 | The payload sits only in a GitHub Actions workflow file. Go source and release binaries are unchanged, and Go builds don’t run workflow files. Aikido still recommends removing these versions. |
The advice is much stronger for the Packagist package than for the Go module. For the Go versions, consumers probably weren’t hit directly, since the payload never touched the code they compile. Removing them is still the right call: those tags show that the source repository or release pipeline was compromised, and downstream teams shouldn’t assume the damage stopped at CI.
The npm install path
Aikido didn’t report a malicious npm package version in this campaign. It did report that the attacker used an npm postinstall hook as one of its delivery routes inside affected repositories. Those are two different things:
- A malicious published package is a version on a registry that contains or delivers malicious code.
- A malicious repository hook is code added to a project’s repository or
package.jsonthat runs when someone installs dependencies in a developer environment or CI runner.
The second one still deserves attention, because it runs on laptops as well as runners. If a developer ran npm install on an affected repository while the hook was there, their machine and local credentials may be exposed.
Where traditional controls fall short
Most organizations already run vulnerability scanners, secret scanners, SAST and dependency audits. They’re useful, but this kind of attack slips between them.
A vulnerability scanner flags known CVEs, not a freshly injected postinstall script. A secret scanner catches credentials committed to a repository, but it won’t stop a workflow from shipping secrets out at runtime. Code review helps, but not when the malicious change is tiny, reverted within a minute or buried in an automated update.
The real gap is between policy and enforcement. Plenty of teams have a rule that only approved packages can be installed. Far fewer enforce it at the moment a developer runs npm install, a CI job resolves dependencies or an endpoint pulls down an extension.
That moment is where PexLens fits. In a campaign like wfx-loot, PexLens is most useful before the attacker gets anywhere near cloud credentials: when a malicious postinstall script, a suspicious dependency or an unsafe extension tries to run on a developer machine or CI runner, PexLens can flag or block it before it harvests anything.
How PexLens helps
PexLens is built to secure how teams build and use software, with controls on developer machines, CI pipelines, endpoints and AI-assisted workflows. PexLens Supplytrust evaluates package requests in real time and returns an allow, warn or block decision before anything is installed, instead of relying only on periodic scans or manual review.
| Risk | What can go wrong | How PexLens helps |
|---|---|---|
| Malicious dependencies | A package runs a malicious script during npm install, pip install or similar. | Real-time package-request checks block or flag suspicious packages before they reach a developer machine or CI runner. |
| Compromised dependencies | A legitimate-looking package is updated with malicious code. | Dependency intelligence and threat analysis surface suspicious components and known supply chain threats. |
| CI pipeline abuse | A workflow installs an unsafe dependency or runs attacker-controlled code. | The same package policy applies in CI, so a compromised build is less likely to become an exfiltration point. |
| Browser and IDE extensions | An extension gets access to source code, credentials or browser sessions. | Extension security covers browser and IDE extensions, including VS Code. |
| Endpoint exposure | A risky component lands on a developer machine and later reaches production or leaks data. | Endpoint software security discovers and assesses software components across your endpoints. |
| AI-assisted development | Developers paste secrets, source code or customer data into AI tools. | PexLens TrustGate inspects prompts and responses for secrets, source code and personal data, then allows, redacts or blocks them by policy. |
Where PexLens fits, and where it doesn’t
It’s worth being precise here. PexLens reduces the risk of credential theft and malicious code execution across developer endpoints, dependencies, extensions and AI workflows. By closing off the initial compromise paths that expose OIDC tokens, cloud keys and CI secrets, it makes it much less likely that an attacker ever gets the access needed to tamper with cloud identity trust.
What PexLens does not do is directly detect or block changes inside your cloud accounts, such as:
- AWS IAM role trust-policy changes
- AWS OIDC identity provider creation or modification
- Azure application federated identity credential changes
- GCP Workload Identity Federation configuration changes
- Cloud role assumption events
- IAM privilege escalation or policy drift
- Anomalies in cloud audit logs
Those belong to your cloud provider’s native identity and audit tooling, along with a CSPM or CIEM product, a SIEM, or a cloud detection and response platform. PexLens doesn’t replace GitHub security settings or cloud IAM either. It adds enforcement at the points where risky software and sensitive data first enter your environment: the workstation, the dependency request, the CI pipeline and the endpoint.
Detection opportunities
The attack was designed to be brief, but it still left signals behind. Look for behavior, not just static findings.
| Signal | Why it matters | What to watch for |
|---|---|---|
| Workflow file changes | Workflow edits can introduce arbitrary code execution in CI. | Alert on changes under .github/workflows/, especially new run: steps, curl, base64 or unfamiliar third-party actions. |
| New lifecycle scripts | Install hooks run automatically. | Watch package.json for new preinstall, install or postinstall entries and require review. |
| Short-lived branches and fast reverts | Ephemeral changes dodge review. | Flag branches created and deleted within minutes, and commits reverted almost immediately. |
| Missing workflow runs | Deleted runs and logs point to anti-forensics. | Look for gaps in run numbers and alert on workflow-run deletion. Keep audit logs outside GitHub. |
| Unexpected OIDC use | A workflow may be assuming a cloud role it shouldn’t. | Alert when the repository, workflow, ref or environment in a role assumption doesn’t match what you expect. |
| Cloud identity changes | Trust-policy edits and new federated identities provide persistence. | Detect changes to IAM trust policies, OIDC providers and federated credentials, including any named wfx-ci-…. |
| Suspicious installs | A malicious dependency can execute during installation. | Inspect package requests and lifecycle scripts before they run, on laptops and in CI. |
Hardening GitHub Actions
Start with least privilege for the token
Set the default GITHUB_TOKEN permission to read-only:
permissions:
contents: readGrant more only to the workflows that need it, and scope it as tightly as you can. Avoid organization-wide write defaults unless there’s a documented reason. Workflows that publish artifacts should use dedicated environments and protected secrets. A build workflow shouldn’t carry the same privileges as a release workflow.
Constrain OIDC trust
OIDC federation beats long-lived cloud keys, but only if the trust policy is tight. A policy that accepts any repository or any ref turns CI into a wide-open route into your cloud. Bind each role to the expected organization, the specific repository, the intended workflow, the right ref or environment, and the expected audience. A role should never be assumable by an arbitrary repository just because it sits in your organization.
Separate build trust from release trust
A routine test workflow has no business publishing packages, deploying infrastructure or touching production secrets. Use separate workflows, environments, approval gates and credentials for testing, container builds, signing, package publishing, staging and production. The more sensitive the step, the stronger the approval and attestation it should need.
Protecting the dependency path
Workflow injection was only one of the delivery routes. The .ci-xxxxxx.sh script and postinstall hook show how dependency installation itself becomes a way to run code.
This is a common blind spot. Static analysis reads source code but doesn’t see what an install actually does. Vulnerability scanners know CVEs, not a package published an hour ago or a lifecycle script nobody expected.
PexLens closes that gap by evaluating package requests in real time. PexLens analyzes more than 100,000 packages and 5,000 browser and IDE extensions every day, so the policy decision is made at the moment of risk:
- when a developer runs
npm installon a workstation, - when a CI job resolves dependencies during a build,
- when an endpoint installs a new browser or IDE extension,
- when an AI assistant adds a new package or changes a config.
Instead of finding malicious behavior after it has run, you can stop it before the package or extension touches source code, credentials or the local environment. In wfx-loot terms, that’s the difference between a blocked install hook and a stolen OIDC token.
Extending controls to developer endpoints
The endpoint is often where a supply chain attack actually starts doing damage. A malicious package on a developer machine may be able to read Git credentials, SSH keys, browser sessions, cloud CLI credentials, Kubernetes config and source code.
Several attack paths meet there. A compromised account pushes malicious code. A dependency runs during install. A browser extension reads cookies or tokens. An IDE extension reads workspace files or runs commands. An AI tool receives source code or secrets in a prompt.
A control that only scans repositories misses most of those. A control that only watches endpoints misses the upstream dependency decision. PexLens covers both: the package request and the machine where that software ends up running. Its endpoint software security discovers and assesses the components actually installed across your organization, which gives security teams visibility beyond the repository and CI.
Securing extensions and AI workflows
Today’s development environment is more than an editor and a terminal. Browser extensions, IDE plugins, AI assistants and local tools all handle sensitive context, often with very little visibility for the user.
PexLens secures browser and IDE extensions, including VS Code extensions. PexLens TrustGate inspects prompts and responses for source code, secrets, API keys and personal information, and depending on policy it allows, redacts or blocks the content and logs the decision.
Treat TrustGate as a data loss prevention and policy control, not a productivity add-on. Developers paste stack traces, config files, credentials, customer records and proprietary code into AI tools every day. If that leaves the organization unchecked, you can have a breach without any malware at all.
A layered control model
No single control stops every variant of this attack. The aim is overlap, so that a failure in one layer doesn’t become a full compromise of your supply chain.
| Layer | Goal | Examples |
|---|---|---|
| Identity | Prevent and detect account compromise | Phishing-resistant MFA, session monitoring, anomalous pull request detection |
| Repository | Limit write access and workflow changes | Branch protection, required reviews, workflow-change alerts |
| CI | Limit execution and credential exposure | Read-only tokens, isolated runners, scoped OIDC roles |
| Dependencies | Stop malicious packages from running | Real-time package-request checks, dependency intelligence, lifecycle-script controls |
| Endpoint | Limit execution and data exposure | Software component discovery, extension security, endpoint telemetry |
| AI tooling | Prevent data leakage and unsafe automation | Prompt and response inspection, secret and PII redaction, policy enforcement |
| Cloud | Prevent persistence after credential theft | OIDC subject conditions, trust-policy monitoring, IAM drift detection |
| Release | Keep tainted artifacts away from users | Signed builds, provenance attestation, registry monitoring, release approval |
PexLens is most relevant in the dependency, endpoint, extension and AI layers. The identity, cloud and release layers rely on your source control platform, cloud provider, CSPM/CIEM and SIEM/SOAR tooling.
Incident response
If you suspect a malicious workflow ran, move fast, but get the scope right. Don’t assume the incident is limited to the repository where it ran. Work through these questions:
- Which secrets were available to the runner?
- Which cloud roles could the workflow assume, and which OIDC trust relationships exist?
- Were any IAM trust policies or federated identities changed?
- Which packages or images were published during the exposure window, and who consumes them downstream?
- Which endpoints installed or ran the affected dependency?
- Which extensions or AI tools had access to sensitive developer context?
A simple rule helps here: if a workflow could reach it, assume the attacker did. Aikido also points out that finding no wfx-loot artifacts or cache entries doesn’t prove nothing was taken, because in this campaign data went straight to the attacker’s servers.
For the confirmed package indicators, the immediate steps are:
- Block
digitalelvis/neuronai-studioversion 3.14.3. - Block or quarantine
github.com/onuragtas/docker-envversions v1.0.278 and v1.0.280. - Pin the Packagist dependency to an earlier version only after you have checked that version yourself.
- Scan developer endpoints and CI caches for the affected versions.
- Rotate credentials on any machine that installed or opened the Packagist release.
What to prioritize
If you’re building or tightening a supply chain security program, these give the best return:
- Treat developer identities like production credentials. MFA, device posture, session controls and anomaly detection belong on GitHub and every other source control platform.
- Make CI permissions explicit and minimal. Drop broad defaults and keep routine builds apart from privileged release jobs.
- Use OIDC properly. Bind role assumptions to repository, workflow, ref and environment, not just the organization.
- Control dependency execution at install time. Static scanning isn’t enough; enforce policy when packages are requested and installed.
- Extend visibility to endpoints and extensions. The developer workstation is part of your production attack surface.
- Govern AI usage. Apply data loss and policy controls to prompts, responses, secrets, source code and PII.
- Watch cloud identity changes. A stolen CI token is serious. A modified trust policy or a rogue federated identity can be worse.
- Keep forensic evidence somewhere safe. Don’t rely only on workflow logs an attacker can delete.
The bottom line
wfx-loot didn’t need an exotic exploit or direct access to production. It used ordinary privileges: a developer account with repository access, a CI runner holding secrets and automated workflows trusted to build and release software.
The job for DevSecOps and AppSec teams is to make those privileges harder to abuse and easier to spot. That means less standing access, policy enforced at the moment packages run, close monitoring of identity and workflow changes, and security controls that reach the machines where developers actually work.
PexLens strengthens the first line of defense. It controls the dependencies, extensions, endpoints and AI workflows that can expose credentials in the first place, which cuts off the paths that lead to stolen OIDC tokens, cloud keys and CI secrets. It doesn’t replace cloud-native IAM monitoring. If credentials do get exposed, you still need cloud audit logging, IAM drift detection, CSPM/CIEM and SIEM/SOAR workflows to catch malicious OIDC trust changes and cloud identity persistence.
Want to see what’s being installed across your developer machines and pipelines today? Request a demo, or read more about software supply chain security and extension security.
Related reading from the PexLens Research Team: Extension Drift: The Supply-Chain Risk Hiding Inside Routine IDE Updates, Your AI Coding Assistant Is a Privileged Insider, and our latest security advisories.
Reference
- Aikido Security, wfx-loot campaign pushes CI secret stealer to tens of thousands of repositories (November 2026): aikido.dev




