The incidents arrived in rapid succession. TeamPCP compromised Aqua Trivy's GitHub Action tags, scraping secrets from /proc memory. Days later, the same group hijacked Checkmarx KICS, exfiltrating CI credentials to a typosquat domain. They used stolen tokens from the Trivy breach to push backdoored LiteLLM versions to PyPI — a .pth auto-execution payload that harvests IMDS credentials, Kubernetes secrets, and API keys from 50+ categories. Then Telnyx on PyPI, reusing the same RSA key and exfiltration headers. And finally, the axios npm compromise — a self-deleting postinstall dropper that erases filesystem evidence of the breach.
Five incidents. Three ecosystems. Two distinct threat actors. One pattern.
The pattern
Every attack followed the same operational shape:
- Compromise a trusted package or action — via stolen credentials, account takeover, or mutable tags.
- Execute a payload inside a high-trust CI environment — runners with secrets access, cloud credentials, signing material.
- Leave minimal post-hoc evidence — self-deleting scripts, in-memory payloads, or process trees that look normal unless you recorded them.
Scanners and lockfiles address step one. Pinning commits and enforcing minimumReleaseAge reduce the window. But once malicious code starts executing inside the runner, those controls go silent. The payload runs with the same privileges as the legitimate build. It touches the same files. It uses the same network. Without kernel-level instrumentation, the only record is what it chose to leave behind — which, in the case of axios, was nothing.
What runtime visibility changes
For each of the five incidents, we detonated the compromised package or action inside a GitHub Actions runner instrumented with Garnet's eBPF sensor. The sensor records every process spawn, file access, and network connection at the kernel level — not from logs, not from the application layer.
The results are consistent:
| Incident | Ecosystem | What the runner profile reveals |
|---|---|---|
| Axios npm | npm | postinstall → sh → curl → python3 chain to sfrclak.com, self-deleting dropper leaves zero disk evidence |
| LiteLLM | PyPI | .pth auto-execution spawns credential harvest across IMDS, Kubernetes, and 50+ secret categories |
| Trivy Action | GitHub Actions | /proc/mem credential scrape — the deepest runtime layer any vendor has published for this attack |
| KICS Action | GitHub Actions | Tag hijack → credential theft lineage to reviewdog[.]dev typosquat domain |
| Telnyx | PyPI | Base64 payload spawn, C2 egress, process orphaning — same RSA key as LiteLLM campaign |
Every profile shows the behavioral split between clean and compromised installs: zero signals on clean, multiple critical signals on compromised. The delta is unambiguous in every case. No tuning required.
The structural gap
The industry response to this wave has focused on prevention: pin commits, audit dependencies, enforce release age. Those are good defaults. They reduce the attack surface.
But they do not answer the question that matters most when prevention fails: what actually happened on the runner?
Which process chain led from install to execution? What files were touched? What network connections were made, and from which ancestor process? Was there evidence of attempted exfiltration, or only potential access?
Those questions require a runtime record. Not inference from package metadata. Not reconstruction from incomplete logs. A kernel-level audit trail of what code actually did during the build.
The evidence trail
Each field note linked below contains the full execution lineage for one incident — the interactive run profile, the process tree, the network connections, the behavioral signals. They are the evidence behind this argument.
- Axios npm Compromise — highest-profile incident, OpenAI connection, self-deleting dropper
- LiteLLM PyPI Compromise — IMDS credential harvesting, deepest technical finding
- Aqua Trivy Action Compromise —
/proc/memcredential scrape - Checkmarx KICS Compromise — tag hijack credential theft
- Telnyx PyPI Compromise — RSA key reuse across campaigns
Explore any run profile above, or start observing your own workflows with Garnet.