Nano Solutions

The Supply Chain Attackers Lived Down the Road

8 min read Petr Cervenka Petr Cervenka
cybersecurity perth business-tips software-development
The Supply Chain Attackers Lived Down the Road
Photo by Corey Serravite on Unsplash
On this page 7 sections
  1. What happened
  2. What TeamPCP allegedly did
  3. The numbers, and who they hit
  4. Why the postcode matters
  5. What this actually asks of you
  6. The uncomfortable version
  7. Sources

The short version

  • Two men, 21 and 23, appeared in Perth Magistrates Court on 27 August charged with 14 offences between them over TeamPCP, the group behind this year's run of open-source supply chain attacks.
  • Search warrants were executed in Cottesloe, Hamilton Hill and Mandurah. The closest is about 4km from our office.
  • The FBI says the code potentially compromised more than a thousand organisations worldwide. The AFP estimates 500,000+ stolen credentials and 300+ GB exfiltrated.
  • Nobody was targeted. The poisoned code arrived through npm install, a Docker pull and a GitHub Action — the ordinary way software gets built.
  • The two controls that would have blunted it are unglamorous: pin your dependencies to hashes, and stop letting build pipelines hold long-lived credentials.

Everything below is sourced. Dates link to the document they come from.

What happened

On the Australian Federal Police and the WA Police Force executed search warrants at three properties — Cottesloe, Hamilton Hill and Mandurah — and seized electronic devices for forensic analysis. The next day two men appeared in Perth Magistrates Court. The ABC named them as Ruben Ian Thomson, 21, of Cottesloe, and Louis Michael Gaebler, 23, of Mandurah. Prosecutors called them the masterminds of TeamPCP. Both are charged, not convicted.

The investigation opened in April 2026, after threat intelligence firms flagged a syndicate inserting malicious code into open-source packages. It ran jointly with the FBI.

The charges

Cottesloe, 21 Mandurah, 23
Possessing data with intent to commit a computer offence 1 count (max 3 yrs) 1 count (max 3 yrs)
Unauthorised modification of data 4 counts (max 5 yrs each) 4 counts (max 5 yrs each)
Supplying data with intent to commit a computer offence 1 count (max 3 yrs) 1 count (max 3 yrs)
Failing to comply with a s.3LA order 1 count (max 10 yrs)
Dealing with proceeds of crime, $100,000+ 1 count (max 20 yrs)

A s.3LA order compels a person to hand over a password or assist in accessing a device. Refusing carries ten years — more than any single charge relating to the attacks themselves.

The 21-year-old's bail application was withdrawn after the magistrate raised concerns about evidence tampering. The 23-year-old made no application and was remanded until 18 September. Investigators have extracted 100 terabytes from the seized devices and expect further arrests.

What TeamPCP allegedly did

This is the part worth reading if you build or buy software. The group did not break into a thousand companies. It broke into a handful of publishers and let the world's build pipelines do the distribution.

When What
Trivy — Aqua Security's vulnerability scanner — and the Checkmarx KICS GitHub Action are compromised. Poisoned releases ship through GitHub Actions and Docker Hub. Tracked as CVE-2026-33634, CVSS 9.8.
Late March Publishing tokens stolen in the Trivy compromise are used to reach LiteLLM's PyPI pipeline. Backdoored versions 1.82.7 and 1.82.8 ship to a package with 95 million monthly downloads.
The group open-sources its worm framework.
A fresh npm wave. The keyv maintainer's account is taken over; a self-propagating worm backdoors every package that account can publish. 444 packages and 2,212 versions in under four hours, then on into @qlik, @servicetitan and other corporate SDK namespaces.
Three-step diagram: step one, one maintainer account compromised via a stolen publishing token; step two, the poisoned release ships through GitHub Actions, Docker Hub, npm, PyPI and OpenVSX, 444 packages in under four hours; step three, the next install runs the payload with your CI runner's privileges, 1,000-plus organisations affected. A dashed arrow loops back from step three to step one, labelled: and your stolen credentials become step one.
The loop is the point. Each compromise pays for the next one.

The payload was consistent across waves: harvest cloud credentials, Kubernetes tokens, SSH keys and .env secrets; attempt lateral movement across clusters; install a systemd backdoor that polls for more. It moved through five ecosystems — GitHub Actions, Docker Hub, npm, PyPI and OpenVSX.

Two details deserve emphasis.

The first targets were security tools. Trivy and KICS are what you run to check your pipeline is clean. They run early, with broad read access, on every build. SANS called it weaponising the protectors. A scanner is an excellent place to hide, because nobody audits the auditor.

Each compromise funded the next. Credentials stolen from Trivy opened LiteLLM five days later. That is the structural problem with a build pipeline that holds long-lived tokens: one poisoned dependency does not just breach you, it converts you into the next distribution channel.

The numbers, and who they hit

Per the AFP, FBI and vendor telemetry:

  • 1,000+ organisations potentially compromised worldwide
  • 500,000+ credentials stolen
  • 300+ GB of data exfiltrated; 16 victims published on a leak site
  • Affected CI platforms, per StepSecurity's analysis: GitLab 1,064 organisations, GitHub Actions 618, Azure DevOps 233, Jenkins 105, Bitbucket Pipelines 94, CircleCI 15
  • The August npm wave alone touched package versions representing roughly 2 billion monthly downloads

Named victims reported so far include OpenAI, the AI recruitment firm Mercor, and European Commission cloud infrastructure. Oligo Security traced the group's infrastructure back to 2020.

Why the postcode matters

The comfortable story about cybercrime is that it happens somewhere else, to someone with more to steal, by people you will never meet. This one was allegedly run from Cottesloe and Mandurah by two men in their early twenties, and it reached the European Commission.

WA Police Acting Commander Peter Foley said it plainly:

"It shows the prevalence of cybercrime in our community and that cybercriminals live amongst us."

AFP Commander Graeme Marshall added that it is rare to have cybercriminals of this calibre domestically, and that the ages involved are "unfortunate, but not unusual."

Distance rail showing the Nano Solutions Fremantle office at 0km, then Hamilton Hill at 4km, Cottesloe at 7km and Mandurah at 53km, with the alleged reach of the campaign beneath: 1,000-plus organisations, 500,000-plus credentials, 300-plus gigabytes exfiltrated, 100TB extracted from seized devices
Straight-line distances from Phillimore Street. Charge counts and custody status from the AFP release and ABC court reporting.

There is no comfort in the geography, and no extra threat in it either. The point is narrower and more useful: this was not a nation-state, a zero-day budget or a targeted campaign against your business. It was two people, ordinary tooling, and the assumption — held almost universally, including by us until we go and check — that a package resolving to a floating version tag will be the same package tomorrow.

What this actually asks of you

Nothing here needs a security program. Most of it is an afternoon.

Check your lockfiles. Start with whether you were exposed at all. I ran this against this website while writing the post:

npm ls keyv cacheable flat-cache file-entry-cache cache-manager
# └── (empty)

Clean, in this repo. file-entry-cache and flat-cache ship as transitive dependencies of ESLint, so a lot of front-end projects are not. Do the same for trivy in your CI images and litellm==1.82.7 or 1.82.8 in your Python requirements.

Pin to hashes, not tags. The FBI's own advice after these charges was to pin GitHub Actions workflows to a verified commit SHA rather than a floating version tag. uses: some/action@v4 re-resolves on every run; uses: some/action@a1b2c3… does not. Same principle in composer.lock, package-lock.json and pinned Docker digests. This is the single change with the best ratio of effort to protection.

Rotate the credentials your pipeline holds, then reduce them. Publishing tokens, cloud keys, deploy secrets. Rotation is the response to this incident; the durable fix is short-lived, scoped credentials — OIDC to your cloud instead of a stored access key — so a poisoned build step gets minutes of narrow access rather than a permanent key.

Assume the build environment is hostile. A CI runner that can reach your production database, your S3 buckets and the open internet is an excellent place for someone else's code to land. Least privilege and network egress control did more to limit this campaign than any scanner.

If you buy software rather than build it, ask two questions. Ask your vendor whether their dependencies are pinned by hash, and how quickly they can tell you which third-party packages are in the product you bought. A vendor who cannot answer the second question inside a day does not have a software bill of materials, and will not be able to tell you whether you were affected by the next one of these either.

Where the Essential Eight lands

If you are working towards the Essential Eight, this campaign sits mostly in patch applications and restrict administrative privileges — and it exposes the limits of both. Patching assumes the new version is safer than the old one. Here the new version was the attack: teams who patched Trivy promptly in March were the ones who got the backdoor. Application control and least privilege held up better, because they constrain what the code can do regardless of where it came from.

That is not an argument against patching. It is an argument that "keep everything current" is not a security strategy on its own, and that the supply chain needs its own control — provenance — which the Essential Eight does not really cover. We wrote about the maturity model's evolution and about what the ASD's own numbers say if you want the wider frame.

The uncomfortable version

Six weeks ago we wrote about AI agents that broke out of a sandbox and compromised Hugging Face on their own, without an attacker. Every entry point in that incident was ordinary: a default API key, an unauthenticated endpoint, over-permissioned service accounts, a published kernel bug.

This story has the same shape from the other direction. Two people, in Perth, using stolen publishing tokens and floating version tags. The entry points were ordinary again.

The pattern in both is that the exotic part is never the way in. It is always a credential that lived too long, a permission nobody scoped, or a version number that meant less than everyone assumed.


If you want a second pair of eyes on what your build pipeline can reach, that is a conversation we are happy to have.

Photo credits. The two diagrams in this post are our own work. The header photograph is used under the Unsplash License — free for commercial use, attribution appreciated:

Sources

The charges

The attacks

Petr Cervenka

Petr Cervenka

Petr is the founder and lead developer at Nano Solutions, a Perth-based custom software firm. With over a decade of experience building enterprise platforms for government and private sector clients, he leads delivery of complex projects across Australia.

Connect on LinkedIn