RC RANDOM CHAOS

OAuth ate your secrets

The Vercel OAuth breach shows environment variables are not protected by location, only by the identity assertion placed in front of them.

· 8 min read

Opening position

A platform breach involving OAuth and environment variable exposure is not a configuration issue. It is a trust boundary issue. The distinction matters because the response is different. Configuration issues get patched. Trust boundary issues require redesign.

Environment variables on managed platforms occupy a position the industry has decided not to examine closely. They sit behind the platform’s identity layer, accessible to running workloads, and are treated by most engineering teams as a private memory space. That treatment is a habit, not a control. The habit only holds while the identity layer in front of those variables behaves as expected. When OAuth becomes the path to that identity layer, the security of every secret behind it inherits the weakest assumption in the OAuth flow.

This is the position to start from. Environment variables are not protected by their location. They are protected, if at all, by whatever validates the identity calling for them. When that identity check is delegated to OAuth, and OAuth itself is the abused surface, there is no remaining boundary. The secrets are not behind a wall. They are behind a token check that the attacker is now satisfying.

What actually failed

The externally observable failure is access to platform environment variables through an OAuth-based attack path. The path was usable. The variables were retrievable. Anything beyond those two facts about the mechanism, including dwell time, lateral movement, account counts, or persistence, is not confirmed. State it that way and stop.

What the failure demonstrates at the system layer is that the OAuth grant, once obtained or abused, was sufficient to reach a resource that engineering teams treat as out of band. There was no second control between the granted token and the secrets store. The identity layer was the boundary. The boundary held exactly as well as the OAuth flow that fed it, which is to say it did not hold.

The consumer-side behaviour is also part of what failed. Workloads that read environment variables do so without re-validating the caller, the context, or the legitimacy of the request to expose those values back through any reachable interface. Whether any specific consumer code in this incident did so is not confirmed. What is confirmed is that the platform exposure path existed and was reachable through the OAuth surface. That is the failure to define and respond to.

Why it failed

The OAuth surface was treated as an identity layer rather than as an attack surface. Those are not the same thing. An identity layer asserts who is calling. An attack surface is anything an adversary can interact with to influence that assertion. Treating OAuth as the former without continuously validating it as the latter produces exactly the failure mode observed: the moment the assertion is wrong, every downstream control that trusted it is also wrong, in parallel, without any of them firing an alert.

The second reason is the placement of environment variables in the trust model. They were positioned as inert configuration rather than as a live secrets boundary. Inert configuration receives no enforcement. A secrets boundary receives access checks, audit, rotation, and scoped issuance. Whether any of those controls existed on the affected variables is not confirmed. What is observable is that the OAuth path reached them, which means whatever controls were present did not enforce a separation between the OAuth-granted identity and the secrets-store identity. Those should not be the same identity. Where they collapse into one, there is no boundary to breach. There is only a token to obtain.

The third reason is the operator assumption that platform-managed means platform-protected. Managed platforms move the operational burden of secrets storage off the team. They do not move the threat model. The threat model still includes any path that can produce a valid identity assertion against the platform. OAuth is one of those paths. SSO is another. Service-to-service tokens are another. Each of these is a pipe into the same secrets surface, and each is governed by different validation logic, different revocation behaviour, and different telemetry. Treating the secrets surface as protected requires treating every one of those pipes as continuously hostile. That treatment was absent. The breach is the consequence of its absence.

Mechanism of Failure or Drift

The mechanism is the collapse of two distinct identity domains into one. OAuth issues an identity to a calling workload. The secrets store, which should hold its own identity model and its own access decisions, accepted that OAuth-issued identity as authoritative. No second evaluation occurred at the secrets boundary. No per-request validation compared the OAuth assertion against a policy scoped specifically to the secrets surface. The secrets store and the OAuth surface were effectively the same identity plane. Whether any additional identity validation was present is not confirmed. What is observable is that once the OAuth flow was satisfied, the secrets plane answered.

The drift is how this collapse became normal. Managed platforms consolidate identity to reduce operational friction. A single token is frequently used across compute, storage, configuration, deployment, and secrets access. That consolidation is a feature from a usability standpoint and a liability from a security standpoint. The drift occurs when the operational benefit is retained and the compensating boundary is never added. The absence of a second-layer check is not a decision made once. It is a decision reaffirmed continuously by not making it. Every deploy that ships without that separation extends the drift.

Environment variables sit at the terminal end of this collapse. They are the last readable value. The OAuth token in front of them is the only element standing between an external caller and the literal bytes of a credential. When the OAuth assertion is abused, the request that reaches the variable surface looks identical to a legitimate request. The variable store has no basis to refuse. It was not designed to refuse. It was designed to serve configuration to workloads already judged trustworthy by something else. That something else failed. The variable store did what it was built to do, which in this case meant returning secrets to a caller holding a valid token.

Expansion into Parallel Pattern

The same mechanism is present anywhere a single identity assertion flows into a resource that performs no independent validation. Service account tokens issued to compute workloads frequently reach object storage, databases, queue systems, and internal APIs without any of those downstream systems applying scope checks beyond the presence of a valid token. The token is the boundary. If the token is obtained, the resource responds. This is the same mechanism as the OAuth path into platform environment variables. The label on the token changes. The collapse of identity into a single assertion does not.

SSO into administrative consoles presents the identical pattern at a different layer. A successful SSO assertion commonly grants session access to a console that fronts many resource types, each of which trusts the SSO-derived session without re-evaluating whether the specific action on the specific resource should be permitted for that session in that context. The session is the boundary. Once obtained, the reachable surface includes resources that would require separate authorisation if the identity plane and the resource plane were not collapsed. The mechanism is identical. One identity assertion, many downstream resources, no per-resource enforcement.

CI/CD tokens illustrate the same pattern with a shorter horizon. A pipeline credential, once exposed, often reaches deployment targets, artifact stores, and secrets systems. The pipeline identity is the boundary. If that identity is compromised through a workflow, a third-party action, or a misrouted trigger, the downstream systems do not ask whether this specific pipeline run, invoked by this specific actor, for this specific branch, should be performing this specific action. They accept the token. The pattern repeats. Identity consolidates into a single assertion. The assertion becomes the boundary. The boundary becomes the target.

Hard Closing Truth

Environment variables on managed platforms are secrets. They are not configuration. Treating them as configuration produces the outcome observed in this breach. A secret requires a boundary that is enforced per access, scoped per caller, and recorded per read. If that enforcement is absent, the value is not protected. It is stored. Storage is not protection. The Vercel OAuth exposure defines the consequence of that distinction being ignored.

Identity is the boundary. Any control that depends on an identity assertion must treat that assertion as continuously hostile and must validate the assertion against the specific action requested, not against a general claim of legitimacy. OAuth, SSO, service account tokens, and pipeline credentials are all identity assertions. None of them are boundaries on their own. A boundary exists only where a second evaluation occurs, performed by the resource being accessed, against a policy narrower than the identity itself. Where that second evaluation is absent, the resource is reachable by any caller who can produce the upstream assertion. Whether such second evaluations existed on the affected surface is not confirmed. What is confirmed is that the path was usable end to end.

What must now be true is that the identity plane and the secrets plane are separated. The token that proves who a workload is cannot be the same token that retrieves what that workload needs. The secrets surface must issue its own short-lived, narrowly scoped credential, bound to the specific action, the specific resource, and the specific context. The OAuth layer must be treated as an attack surface subject to continuous validation, revocation, and telemetry at a fidelity that surfaces abuse before secrets are read. Anything less leaves the variable store sitting behind a single token. A single token has been demonstrated to be insufficient. The mechanism has been shown to work. It will be used again against any platform that has not closed the collapse.

See also: NordVPN for tunneled traffic when operating outside controlled networks.


#ad Contains an affiliate link.

Share

Keep Reading

Stay in the loop

New writing delivered when it's ready. No schedule, no spam.