A researcher called Chaotic Eclipse tried to do the right thing. They found a zero-day in Windows Defender — a SYSTEM write through the antivirus’s own remediation engine. They reported it. Someone violated the disclosure agreement. So they published. Full PoC. Working exploit. No patch.

Their note read: “I never wanted to reopen a blog and a new GitHub account to drop code. But someone violated our agreement and left me homeless with nothing.”

That sentence is the frame for everything that follows. Not because of the dramatic circumstances — though they are dramatic — but because of what it reveals about the system. A researcher found that the security tool watching your pipeline can be turned into the attack. The institution responsible for fixing it didn’t. So here we are.

That’s not an isolated story. That’s the story of 2025 and 2026.

What Defenders Think They’re Protected Against

The mental model most organizations are operating on goes like this: an attacker finds a vulnerability, exploits it to get a credential, uses that credential to do something bad. The defenses are authentication-shaped: enforce MFA, require strong passwords, detect unusual logins, rotate secrets. The defender’s job is to make sure only the right people can prove they’re the right people.

This model is not wrong. It’s just aimed at the wrong surface.

None of the six incidents I’m about to describe involved a stolen password. Not one. No phishing. No brute force. No credential stuffing. What they involved was the appropriation of credentials that distribution systems already trusted unconditionally — publish tokens, session cookies, automation accounts, service identities. The credential was legitimate. The context was the only thing wrong, and the distribution system doesn’t check context.

npm doesn’t ask why you’re publishing a new version at 2am. GitHub Actions doesn’t ask why a tag pointer moved. Windows Defender doesn’t ask whether the path it’s writing to is expected given the file it’s remediating. Trust was granted once, at provisioning time or login time, and it doesn’t expire, doesn’t narrow, and doesn’t question itself.

This is an authorization problem. The security industry is still selling authentication solutions.

Six Incidents, One Method

The pattern becomes visible when you put the incidents on a timeline.

March 2025 — tj-actions. Git tags are mutable pointers. Everyone using tj-actions/changed-files@v45 in their workflow files trusted that v45 pointed to what it pointed to when they reviewed it. An attacker compromised the maintainer account, moved the tag to a malicious commit, and 23,000 repositories ran attacker code. Nobody’s workflow file changed. The trust was in the tag. The tag moved. The pipeline didn’t notice.

September 2025 — Shai-Hulud. The npm worm didn’t need novel infrastructure. It used npm’s own publish mechanism — postinstall hooks plus ambient publish tokens that developers leave in their environments. Five hundred packages propagated the payload geometrically by using each compromised maintainer’s token to publish infected versions of every package they maintained. The worm’s distribution channel was npm. npm was behaving exactly as designed.

Early 2026 — XRPL SDK. Not a typosquat. Not a transitive dependency buried six levels deep. The canonical XRP Ledger JavaScript SDK — the official package, maintained by the official account, listed on the official documentation page — carried a credential harvester in versions 4.2.1 and 4.2.2. Developers who did everything right got compromised. The official package was the threat.

March 2026 — TeamPCP. This is where the targeting logic becomes explicit. They didn’t go after the CI pipeline directly. They went after Trivy first, then Checkmarx KICS four days later. Two security scanners in five days. The exfiltration was already operational before the compromised tools could have flagged anything downstream. They came for the scanners because the scanners are the trust anchors — compromise the tool that issues “clean” verdicts and every subsequent verdict is meaningless.

April 2026 — axios. Seventy million weekly downloads. One maintainer account. North Korean state actor. Versions 1.14.1 and 0.30.4 carried a cross-platform RAT. The install count isn’t noise — it’s a yield calculation. Sapphire Sleet wasn’t looking for one target. They were looking for a multiplier. axios was the multiplier.

April 2026 — RedSun. Chaotic Eclipse’s find. CVE-2026-33825. Windows Defender’s remediation engine, running as SYSTEM, follows a path through an attacker-controlled sync root directory stamped with a mount point reparse to System32, and writes there. The security tool is the privilege escalation vector. The scanner is the payload delivery mechanism. No patch as of this writing.

Naming the Problem

There are three structural conditions that make this methodology work. They’re worth naming precisely because unnamed problems don’t get fixed.

Trust inheritance. When a credential authorizes access to a distribution channel, every action taken with that credential inherits the channel’s full trust level. A compromised npm token doesn’t get partial trust — it gets the same unconditional publish rights as the legitimate maintainer. A compromised GitHub account doesn’t get a probationary period on tag rewrites. The trust inheritance is total and immediate, which is why the attack window is so short and the blast radius is so large.

The revocation gap. Between credential compromise and detection, every action the attacker takes with that credential is trusted. The tj-actions tag moved. In the hours before anyone noticed, thousands of workflows ran. The XRPL SDK was live on npm for thirteen hours. axios 1.14.1 was available for distribution before anyone pulled it. There is no mechanism in any of these distribution systems to retroactively untrust what already ran. The damage from a credential compromise scales linearly with how long it takes to notice, and detection is slow because the actions look legitimate — because the credential is legitimate.

The authorization vacuum. Authentication confirms identity. Authorization should confirm that a given identity is permitted to take a given action in a given context. npm authenticates that you hold a valid publish token. It doesn’t check whether publishing axios@1.14.1 at 3am from an IP in a new geography is an action this identity should be taking right now. GitHub authenticates that you’re logged into the account. It doesn’t check whether rewriting a stable tag on a project with 23,000 dependent workflows is what this account normally does. The authorization layer is either absent or trivially permissive. Authentication gates are locked. The authorization floor is open.

MFA didn’t fix any of this, and it couldn’t have. None of these attacks compromised the authentication step — they operated after it. Signed commits don’t help when the signing key belongs to a compromised account. Package scanning doesn’t help when the scanner is the compromised component. These are authentication controls applied to an authorization surface. They’re necessary. They’re not sufficient. They address a different threat.

The Escalation Arc

Look at the six incidents as a progression, not a list.

The early incidents hit packages — software that runs in the context of whatever runs it. High reach, limited privilege. Then Shai-Hulud demonstrated that the reach could be self-amplifying if you used the distribution mechanism’s own propagation logic. The XRPL attack collapsed the distinction between “official” and “safe” — the canonical source became the threat.

TeamPCP marks the inflection point. When the attackers started targeting security scanners specifically, the pattern became structural. A compromised package is dangerous. A compromised scanner that calls a package “clean” is dangerous plus invisible. The value of compromising a security tool isn’t just the access it has — it’s the fact that it issues trust certificates for everything downstream. Compromise the trust issuer, and the downstream trust is meaningless.

RedSun is the logical endpoint of that reasoning, made literal in code. The security tool doesn’t just run privileged — it runs as SYSTEM and it takes action. Defender’s remediation engine is a write primitive. The Cloud Files API and a mount point reparse turn that write primitive into an arbitrary SYSTEM write. The attacker didn’t need to escalate privilege separately. The privilege escalation tool was Defender. The attack surface isn’t the application layer anymore. It’s the security layer.

Security tooling is now a higher-value target than the systems it protects. That sentence should be uncomfortable to read if you’re in the business of selling or deploying security tooling.

Am I Affected / What To Do

tj-actions. If your CI workflows pinned tj-actions/changed-files@v45 without a commit SHA, you were potentially affected during the compromise window in March 2025. Audit your workflow run logs for that period. Pin by SHA going forward — uses: tj-actions/changed-files@<specific-commit-sha> — because tags are not immutable references and never were.

Shai-Hulud. The worm propagated through npm packages with postinstall hooks during September 2025. If your npm install output from that period shows unexpected postinstall scripts from packages you didn’t modify, treat those environments as compromised. The full package list is in the detailed post.

XRPL SDK. If you used xrpl versions 4.2.1 or 4.2.2, any wallet private keys or seed phrases that passed through that code should be rotated immediately. The credential harvester targeted those specifically. Rotate, don’t reuse.

axios. Versions 1.14.1 and 0.30.4 contained a cross-platform RAT. Check your lock files and your build artifacts. If either version appears, the machine that ran that code should be treated as compromised — not just the code, the machine. The RAT established persistence.

TeamPCP. If you ran Trivy between March 12–16, 2026, or Checkmarx KICS between March 16–20, 2026, audit what those scans had access to. Both tools run with elevated filesystem access by design. Assume they could see your secrets, tokens, and environment variables.

RedSun. No patch exists as of April 16, 2026. RedSun requires local code execution first — it’s LPE, not RCE — but “local code execution” increasingly means a single browser exploit away. The detection indicators are specific: look for CfRegisterSyncRoot calls from processes other than known sync clients, mount point reparse points stamped on Cloud Files sync roots, and unexpected modifications to %WINDIR%\System32\TieringEngineService.exe. Implement those detections now. A patch will come. The class won’t be fixed in that patch.

The generic advice — “implement zero trust,” “rotate credentials regularly,” “scan your dependencies” — is not wrong. It’s just not responsive to this threat class. What’s responsive: pin your CI actions by commit SHA, not tag. Scope your publish tokens to the minimum necessary lifetime and package set. Treat your security tooling supply chain with at least as much suspicion as your application dependency supply chain. Monitor for anomalous authorization patterns, not just authentication anomalies. And recognize that the revocation gap is structural — if a credential is compromised, you’re managing a damage-containment problem, not a prevention problem.

The Close

The trust inversion isn’t a metaphor. It’s the mechanism. Every one of these attacks succeeded because a system that grants trust doesn’t revoke it, doesn’t contextualize it, and doesn’t question it when the credential arrives. The attacker’s job is simple: get the credential. Everything after that is the system doing exactly what it was designed to do.

We built distribution infrastructure that scales trust unconditionally, and then we’re surprised when that unconditional trust is the attack surface.

The thing that watches the pipeline is now the thing that carries the payload. That’s not a vulnerability disclosure. That’s an architecture review.


PGP signature: the-trust-inversion.md.asc — Key fingerprint: 5FD2 1B4F E7E4 A3CA 7971 CB09 DE66 3978 8E09 1026