//nefariousplan

Trust Inversion

The tools and credentials that authorize access to your systems are now the attack surface.

Security has a blind spot, and it is the shape of its own assumptions.

When you enumerate attack surface, you draw a line around ports, endpoints, parsers, auth flows. Everything inside the line is the system. Everything outside is the attacker. The things that straddle the line, the authorizers, the signing tools, the maintainer accounts, the package registries, the CI bots, the admin consoles, the AI assistants, those rarely make the surface diagram because they are not the system, they are what lets the system run.

They are also where 2025 and 2026 kept breaking.

Mechanism

The inversion is subtle. Every piece of infrastructure has things it distrusts by default and things it trusts by construction. Distrusted input gets parsed, validated, rate-limited, auth-checked. Trusted input just runs.

The pattern: an attacker moves the attack from the distrusted lane to the trusted lane. Not by breaking validation, but by compromising something further up the chain that was never modeled as hostile. Once they are riding an authorizer, the validation never fires, because the validation was built to stop outsiders and the attacker is now, in the system's view, an insider.

This is not credential theft. Credential theft is stolen credentials used for direct access. Trust inversion is bigger: the attacker captures the thing that confers legitimacy and uses it to ratify attacks across every system that downstream-trusts it. One compromise, N breaches, one for every N that trusted the mechanism.

The authorizers sit in a specific architectural position. They are upstream of the thing being protected. They typically run with broader privilege than the caller. They are deployed once and not rehardened. Nobody maps them. Security teams enumerate ports and endpoints. Nobody enumerates the things that confer legitimacy. That gap is the working surface every trust-inversion incident exploits. The fix is not better validation on the distrusted lane. The fix is recognizing that the trusted lane has an attack surface at all.

Exhibits

CVE-2026-7415: Yarbo's MQTT Broker Is Not Anonymous. The Password Is in the App.. Yarbo's robot fleet ships three trusted lanes by design, all sharing the same Hanyangtech-prefixed token. The FRP SSH tunnel back to 98.82.87.76 is a remote-maintenance authorizer. The cloud MQTT bus (EMQX, then Tencent TDMQ) is a command-and-telemetry authorizer. The credential_updater Greengrass component is a password-rotation authorizer, hardcoded with hy@0886!#. None of them are attack surface in the catalog's usual frame, because none of them are the inbound parsing lane the LAN-side attacker would target. They are weaponized because the upstream party with the master credential is also the party that authored the firmware, and that party is the vendor's Chinese parent operating the cloud infrastructure the credential authenticates against. The CVE imagines a hostile host on the LAN. The actual attacker is whoever extracted the public Android app com.hanyang.yarbo and read line 45 of device_ops_node.py. The validation on the distrusted lane was never the gate. The trusted lane is the product.

CVE-2026-42298: The Postiz Commit That Turned the PR Builder Into RCE Was Titled "Add Environment". The trusted lane here is the GITHUB_TOKEN issued to github-actions[bot] for pull_request_target events, scoped write-all against the base repository. The compromise vector is not credential theft; the credential is being correctly issued, to the correctly identified workflow, on the correctly authenticated runner. The inversion is that the trusted runner's docker build step consumed a Dockerfile authored by a fork submitter, and the build context handed to that Dockerfile contained a .git/config that actions/checkout had populated with the privileged token. One workflow file, one default-true checkout option, 203 days, every fork PR is a remote-code-execution primitive against the base repo. The validation on the distrusted lane (the PR review) was never the relevant gate, because the trusted lane (the post-merge-equivalent runner) was already executing the PR's content.

CVE-2026-22812: OpenCode Patched the CORS, Not the Auth. OpenCode's shell-execution endpoint is the agent's primary capability. The LLM proposes commands; the agent eval's them in the user's login bash with sourced .bashrc, expanded aliases, and the user's full environment. That authorization to run shell as the user is the trusted lane. The bug does not break validation; it removes the assumption that only the local TUI can reach the local server. CORS, then a CORS allowlist, then a list of approved origins (the vendor's own marketing domain plus every other localhost service on the developer's machine). Every POST to /session/:id/shell is, from the server's view, the agent doing its job. The patch chose which web origins may be the LLM today; it did not address that "is the LLM" remained an unauthenticated capability.

CVE-2026-0257: PAN-OS Encrypted GlobalProtect's Auth-Override Cookie With The TLS Certificate. The trust artifact is the X.509 certificate the GlobalProtect portal presents in its TLS handshake. Its purpose is to prove portal identity to a connecting user; the chain ships in plaintext because TLS requires it. PAN-OS's authentication-override-cookie scheme reuses that same certificate's public key as the encryption key for cookies whose decryption authorizes login. The artifact that the portal hands every client to prove "this is the portal" becomes the primitive the client uses to prove "I am any user." The advisory's step-two remediation, "use a dedicated certificate exclusively for authentication override cookies, do not reuse the portal/gateway certificate," is the configuration knob that, when turned wrong, broadcasts the cookie-mint key. Validation on the distrusted lane (the password field on /ssl-vpn/login.esp) was never the gate, because the cookie field on the same endpoint accepts anything the public key encrypted. The credential that authenticates the portal to the world authenticates the world to the portal.

CVE-2026-45321: TanStack's bundle-size.yml Poisoned the Cache. release.yml Restored It.. The trusted artifact is the GitHub Actions cache for the repository. bundle-size.yml's write into a cache key was granted because pull_request_target runs as the base. release.yml's read of the same key was unconditional because the cache service does not partition writes by which trust context produced them. The attacker did not break authentication, did not steal a credential, and did not reach the publish workflow's runner. The cache crossed the trust boundary that workflow permissions tried to maintain, and release.yml ran what the cache restored.

The Trust Inversion. The namesake post lays out the shape. Start there if the category is new, then come back for specifics.

CVE-2026-44339: PraisonAI's Permission Tier Was Never the Gate. The agent's tool-execution path is the trust artifact a PraisonAI deployment places between attacker-shapeable input and arbitrary Python execution in the process the agent was launched from. The framework names a permission tier (_perm_deny, _perm_allow, presets, env var) and ships it _perm_allow = None by default; the gate that exists is documentation, the gate that actually fires is the fact that the resolver walks globals() and __main__ when no declared tool matches. The validation on the distrusted lane (the user's chat input) was never the relevant gate, because the trusted lane (the LLM's structured tool_calls.function.name) was already executing the model's content. The four-line fallback at the bottom of execute_tool ran as the de-facto authorizer for fifteen months because every default agent's allow-check is short-circuited by _perm_allow is not None. Compromise here is not credential theft; it is whatever shapes the model's next response.

CVE-2025-58434: Flowise Sent the Reset Token to the Inbox. It Also Sent It to the Caller.. The reset emailer is the privileged sender. It holds SMTP credentials, addresses an inbox the system trusts, and carries a fresh secret. The HTTP controller is the unprivileged surface, addressing whoever knocked. Routing the same object through both turns the privileged sender's secret into payload on the unprivileged channel. The tool that was supposed to authorize the user (the email delivery) becomes the surface that bypasses the user (the JSON response). out-of-band-also-in-band names the specific mechanism; trust-inversion names the broader frame.

CVE-2026-50751: Check Point's Gateway Reads One Vendor-ID Bit to Decide Whether It Verifies the Certificate. The Attacker Sets the Bit.. Certificate authentication is a control an operator deliberately turns on to get proof-of-possession assurance a password cannot offer. CVE-2026-50751 makes the enforcement of that very control a toggle the unauthenticated peer flips: the gateway hands the decision of whether to demand the signature to the one party who cannot supply it. The mechanism deployed to raise the bar becomes the mechanism the attacker configures, and the configurations that selected certificate auth for extra assurance are precisely the ones the bypass hits.

CVE-2026-34220: MikroORM's Raw-SQL Brand Was a Property Name. The trusted artifact is MikroORM's own internal raw-SQL marker. The attacker captures it not by compromising the maintainer, the package, or the database, but by writing nine bytes of JSON into a request body. Every site in the ORM that calls isRaw(x) was downstream-trusting the result and inlining x.sql into a query unquoted. One compromise covers every Custom Type column on every install of every affected version. The cost of capture is a property name and the willingness to send a request, which is the lowest cost-of-capture this catalog has recorded.

CVE-2026-8732: WP Maps Pro's Temp-Access Endpoint Creates Administrators. The Vendor's Email Is Hardcoded.. The wpgmp_temp_access endpoint and its fc_user_* account convention are the Flippercode support team's intended path to administrative access on customer sites: a customer files a ticket, the technician spawns a temporary admin, fixes the issue, calls the check_temp=true cleanup branch when done. The trust the customer extends to the vendor is implemented as a publicly-reachable endpoint that creates the credential out of nothing. The tool that authorizes vendor access to customer systems is the tool an unauthenticated visitor uses to acquire the same access. The cleanup branch the vendor designed for their own workflow is the cleanup branch the PoC calls to remove evidence of a prior attacker before the next exploitation attempt.

CVE-2025-29927: The Recursion Guard Was the Auth Bypass. The recursion guard in Next.js's edge sandbox had authority to skip middleware execution. Its input was a colon-separated string read straight off the inbound HTTP request. The framework's internal control header was the trust artifact; the attacker captured it by knowing its name and writing it on the wire. This is trust inversion one floor below the catalog's usual frame: the authorizer is not a maintainer account or a signing UI, it is a framework's own IPC channel that never modeled the network as hostile.

CVE-2024-22120: Zabbix's Audit Log Is the Read Primitive. The trusted lane is the database credentials Zabbix's audit subsystem uses to write auditlog rows. Those credentials authorize INSERTs on behalf of the system. CVE-2024-22120 turns that authorization into ratification of arbitrary SELECTs against sessions and config, on behalf of a low-privilege user who never held the credentials and never could acquire them. The validation that should have stopped the inversion was abandoned at the dispatcher, by design, with a comment in the same commit that fixed the SQLi sink. The fix closes the lane at the database layer; the comment documents that the input remains untrusted and uncentralized everywhere else.

CVE-2026-41651: Polkit Authorized the Slot, Not the Value. Polkit is the trust artifact every Linux desktop relies on for privileged-action authorization. PackageKit's bug turns polkit's grant into the attacker's primitive. Polkit did its job correctly; the design that called it failed to keep the parameters polkit was authorizing intact long enough for the authorization to mean anything.

CVE-2026-34621 Revisited: The 136-Day Detection Lie. The Adobe case extends Trust Inversion to the meta-layer of detection. The sandbox was inverted, yes; but the vendor's advisory apparatus — the "no known exploits" flag, the PSIRT text, the CVSS exploitation-status field — is also a defender-paid input that the vendor controls, and it ran 136 days behind public VirusTotal evidence. Defenders reading the text as threat detection were reading a legal-and-PR artifact.

Axios, Sapphire Sleet, and 70 Million Weekly Installs. The axios maintainer account was compromised, which meant the next npm publish carried an attacker's code with the maintainer's signature. 70 million weekly downloads downstream, and none of them had authenticated the attacker, because they were authenticating the maintainer. The distrusted lane (a random package) was closed. The trusted lane (the same package you have always used) was wide open.

CVE-2024-12356: Treasury Was the Proof of Concept. The privileged-remote-access broker is the trust artifact every enterprise that buys it places between the public internet and their internal admin surface. The bug never breaks validation; it removes the assumption that the customer-thin-client subprotocol is reachable only from a customer who legitimately needs support. Once an attacker holds the X-Ns-Company tenant identifier (returned by an unauthenticated lookup endpoint) and a four-line binary payload, validation never fires because the code path never modeled this caller as hostile. The disclosure trail makes the inversion explicit: BeyondTrust patched their own cloud first, then published the advisory the rest of the world needed to defend themselves with.

Bybit: $1.5B via a JavaScript Injection Nobody Was Looking For. The signing surface on the Safe multisig UI displayed one transaction, signed a different one. The cryptographic signature was correct. The signers had reviewed the transaction in the display. The display was the attacker's rendering. The signed bytes were the attacker's payload. One and a half billion dollars, no credential theft, no key exfiltration. The trust boundary lives at the rendering layer, and that is the layer that was poisoned.

tj-actions: Mutable Tags Were Always a Lie. GitHub Actions users reference third-party actions by tag. Tags are mutable. For years the ecosystem treated @v1 as a pinned release. An attacker moved the tag, and every pipeline that imported the action at that tag imported the attacker's code. The thing the ecosystem depended on for immutability was, at the protocol level, mutable by design.

Prompt Injection Is a Supply Chain Attack. Every input to an LLM is interpreted as potential instruction. When the context window contains content from email, a webpage, a PDF, anything the attacker places inside the prompt is, from the model's perspective, coming from the same trusted channel as the user's question. The AI's capability to take your intent and act on it is also the attacker's capability to take the attacker's intent and act on it.

TeamPCP Came for the Scanners. The team's vulnerability scanner was the payload delivery mechanism. A defender's tool, running with defender privileges, reading every repository in the org, became the attacker's read primitive. The scanner is supposed to find attacks. Now it is an attack.

Boundaries

Not every supply-chain attack is trust inversion. If a developer installs a malicious package they chose from a search, that is a naive trust decision, not an inverted mechanism. Trust inversion requires that the mechanism OF trust was itself compromised.

Not every credential theft is trust inversion. An attacker who steals a user's password and reads their email is impersonating. It becomes inversion only when the stolen credentials are used to ratify attacks against the credential-holder's downstream dependents. A compromised npm maintainer unlocks that maintainer's ability to ship to millions. That is inversion. A stolen personal Gmail password does not, unless Gmail happens to be a signing authority for something.

Not every phishing attack is trust inversion. Phishing requires the user to be fooled. Trust inversion often does not touch the user at all. The mechanism that was supposed to shield the user from having to decide is the thing that got compromised. Your signing tool, your scanner, your tag. The user kept doing what they always did. What changed is what the trusted thing said.

Defender playbook

Enumerate your authorizers. Not your systems, the things that authorize actions on your systems. Which accounts can publish. Which tags can move. Which tools run with elevated scope. Which LLM contexts can call tools. Which scanners have read across the org. That is your trust-inversion attack surface.

For each authorizer, ask what happens when it is compromised, not when it fails. Failure models assume the component is honest but broken. Compromise models assume the component is under attacker control and still performing its function. The second is where you find your actual exposure.

Check which of your authorizers use mutable references. Tags, latest, version ranges, dynamic resolution. If the reference is mutable and the thing downstream treats it as pinned, you have the tj-actions shape sitting in your codebase.

Ask what part of your trust chain lives in a user interface that you do not control. Hardware wallet displays, admin dashboards, signing prompts. Whoever controls the rendering controls the signature, regardless of what the cryptography says.

Rate every maintainer account you depend on by blast radius, not by reputation. The question is not whether the person is trustworthy. The question is what happens to you if their account is not the person.

Kinship

Revocation Gap. Trust inversion opens the door; revocation gap determines how long it stays open. The moment a trusted mechanism is compromised, every downstream that still trusts it is being attacked. Detection time and revocation time are the window where damage compounds.

Security Tool As Primitive. A specific shape of trust inversion where the authorizer is a security tool. The defender's hands become the attacker's hands. The mechanism is the same, just applied to tooling built to protect rather than to authorize broadly.

The Detector Is The Target. Sibling of security-tool-as-primitive, applied to detection surface (sandboxes, SOC tooling, scanners). If your detection mechanism has attacker-controlled input, your detector is now part of the attacker's surface.

You did not get breached by an attacker. You got breached by the thing you trust.