RC RANDOM CHAOS

Bearer tokens vouch for nobody

Alibaba's restriction of Claude Code exposes how OAuth 2.0 bearer tokens resolve a past verification instead of validating the entity acting now.

· 8 min read
Bearer tokens vouch for nobody

OAuth 2.0 does not authenticate a person. It authenticates a token. It confirms that a bearer credential was issued under a prior act of consent, and it authorizes whatever holds that credential to act within a granted scope. Claude Code, the agentic coding tool reportedly restricted inside Alibaba over alleged backdoor risk, is a third-party code execution environment. It reads source, writes source, and runs inside developer workflows under delegated credentials. The reported decision does not describe a breach. It describes a boundary being drawn around a system that executes code on behalf of an authenticated session, and it raises the question of what that authentication actually attests to.

A tool operating under OAuth 2.0 holds a token scoped to the permissions granted at the moment of consent. That token is a reference. It points backward to an authorization that already happened. The service that accepts it does not re-derive the user’s intent, does not re-examine the environment presenting the credential, and does not revalidate the conditions under which the grant was made. It resolves the reference and proceeds. This is the designed behaviour of bearer-token authorization as specified in RFC 6749. The token is presented, the scope is honored, and the transaction completes. Nothing in the protocol asks whether the holder is still the entity the token was minted for.

The restriction reported at Alibaba is, read structurally, a statement about where a system’s trust surface ends. Claude Code runs against a codebase through credentials the organization issued into its own environment. Alibaba retains no visibility into the internal resolution of trust that occurs once a third-party execution environment holds those credentials. The decision to restrict is the recognition that a token honored across service boundaries carries trust the issuing organization can no longer inspect. The tool behaves exactly as designed. The concern is not misbehavior by Claude Code. It is the structure of delegated execution itself, in which a credential issued once continues to speak for an identity long after the moment of verification has passed.

The assumption underneath this arrangement was that identity, once verified, is durable. OAuth 2.0 was built on the premise that authentication happens at a boundary, produces a token, and that the token then stands in for the verified identity everywhere it is subsequently presented. Trust is established one time and referenced thereafter. The efficiency of the protocol is precisely this substitution. It removes the need to re-authenticate at every service, every call, every hop across a distributed system. Re-verification is expensive. A reference to a completed verification is cheap. The protocol optimized for the cheap operation, and the entire ecosystem of federated access was built on top of that optimization.

This produced a trust model in which authorization is treated as persistent and transferable. It is persistent because the token remains valid across its lifetime without any re-examination of the conditions that justified issuing it. It is transferable because any service that accepts the token grants the access the token names, regardless of what the holder is actually doing in the present moment. The identity of the credential’s source came to stand in for the integrity of each individual action taken under it. A token minted for a developer becomes authorization for anything operating within that developer’s session, including an autonomous code execution environment acting on the developer’s behalf. The scope was defined at consent. The uses were not.

The model further assumed that the environment holding the token was equivalent to the identity that earned it. When a human authenticates and a process inherits the session, the working assumption is that the process is an extension of the person. Claude Code executing under a developer’s credentials is treated by every downstream service as the developer. The public registry it pulls from, the internal repository it writes to, the pipeline it triggers: each of these resolves the token, not the actor. None of them asks who is presently in control of the credential. The assumption held cleanly as long as the holder of the token and the verified identity were the same thing. For most of the protocol’s operational history, they were.

That assumption no longer holds. What changed was not attacker capability, and it was not a flaw introduced into OAuth 2.0. What changed is that the holder of the token and the verified identity stopped being the same thing. An agentic tool operating inside a developer session is a distinct execution context that inherits the developer’s trust without inheriting the developer’s presence, and without extending the organization’s visibility into what it does with that trust. The token still resolves correctly. The identity it references no longer fully describes what is acting under it. The verification remains true as a historical fact and false as a present condition.

The system did not re-evaluate trust when the nature of the holder changed, because re-evaluation is not part of bearer-token resolution. A token issued to a verified developer and a token presented by a third-party execution environment operating in that developer’s session are, to every service that accepts them, the same token. The introduction of an autonomous execution environment did not break authentication. It widened the gap between what the token attests, which is that an identity was verified once under a defined scope, and what the token now authorizes, which is action taken independently inside that identity’s boundary. Trust was inherited from a past state and applied to a present one that the past state never described. The registry proxied that trust outward, and the internal services proxied it inward, and at no point in the chain did any component reassess it.

This is where the reported restriction becomes legible as a systems statement rather than a security incident. Alibaba’s exposure is not the claim that Claude Code did something specific. It is that trust proxied through OAuth 2.0, and through the public registry the tool operates against, is validated at issuance and never again. The organization can observe that a token was accepted and a scope was honored. It cannot observe whether the entity presenting the credential is the entity that earned it, or what that entity is doing between the accepted calls. When trust is a reference to a past verification, the present is authorized by history. That arrangement was stable while identity and execution were the same event. The introduction of a third-party execution environment separated them, and the assumption that once bound them together became a liability the system continues, correctly and by design, to honor.

The failure is not an event. It is a substitution. At the moment a token is presented, the accepting service performs one operation. It resolves the reference. It confirms the credential is well-formed, unexpired, and scoped, and it returns the access the scope names. What it does not do, because RFC 6749 does not ask it to, is examine the content of the action being taken under the credential. The identity of the source stands in for the integrity of the request. A write to an internal repository authorized by a valid token is, to the service performing the write, indistinguishable from any other write carrying the same scope.

This is the point where reference replaces validation. Claude Code presenting a developer’s token is not bypassing OAuth 2.0. It is exercising it. Every service in the chain behaves exactly as specified. The public registry it pulls from resolves the reference. The internal repository it writes to resolves the reference. The pipeline it triggers resolves the reference. Nothing is subverted. The observable behaviour of the system is correct behaviour, and that is what makes the condition durable. There is no error state, no failed check, no anomaly for a monitor to catch. The system does not log a validation, because no validation was performed. It logs a successful resolution, because resolution is the operation it was built to perform.

Alibaba’s restriction is legible against exactly this. What the organization can observe is the accepted token and the honored scope. What it cannot observe is the distance between the identity the token references and the entity presently acting under it, because that distance does not appear anywhere in the system’s output. The mechanism does not produce a signal. It produces a transaction. The integrity of the content, meaning what the code does, what the agent writes, what the pipeline executes, was never the thing the token attested to, and the services honoring the token never claimed otherwise. They attested to the reference. The failure mode is that the reference was treated as the thing it points at.

The pattern is execution based on reference rather than verification. A system performs an expensive verification once, records the result as a reference, and thereafter honors the reference in place of repeating the verification. The reference is cheap to resolve and the verification is costly to repeat, so the system optimizes for resolution. This is not a defect of OAuth 2.0. It is the general shape of any system that has decided continuous verification is too expensive to perform. The bearer token is one instance of it. The pattern is the class the token belongs to.

Consider DNS resolution. An authoritative server verifies a name-to-address mapping once. A resolver caches the answer and honors it for the duration of the TTL carried in the record, as specified in RFC 1035. For that interval, every query for that name resolves the cached reference. The resolver does not return to the authority, because returning to the authority is the expensive operation the cache exists to avoid. The cached record is a reference to a past verification, in the same way a bearer token is. And the same separation applies. The mapping was true when it was verified and remains honored regardless of whether it is still true now. The record resolves correctly. Whether it still describes reality is a question the resolver does not ask, because asking it is the cost the cache was built to remove.

In both systems, the object in circulation is not the verified fact. It is a pointer to a verification that happened. The pointer carries none of the conditions that justified the original check, and the system honoring the pointer has no way to know whether those conditions still hold. Reference and reality are bound at the moment of verification and drift apart afterward, quietly, because nothing in the system is watching the binding. The token and the cached record are the same object under different names, which is trust frozen at issuance and spent continuously thereafter. Wherever a system substitutes a reference for a verification to save the cost of re-checking, this gap opens. It is not a property of authentication. It is a property of the substitution.

OAuth 2.0 resolves the identity once and does not resolve it again. The verification remains true as a record and unproven as a present fact. The control exists. The outcome does not.


Contains a referral link.

Share

Keep Reading

Stay in the loop

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