PasskeyBridge —

Security · 2026-04-02

Scope Poisoning: How Compromised Agents Escalate Privileges Through Delegation Chains

By J. W. Bouckaert

Scope Poisoning: How Compromised Agents Escalate Privileges Through Delegation Chains

An attack few teams test for

Enterprise AI deployments are adding delegation. An orchestrating agent spawns sub-agents, and each receives a scoped credential: read-only access to a CRM, permission to draft but not send email, authority to query a billing API but not change records. On a whiteboard the design is clean. In many implementations the scopes travel as data the agents themselves can change.

We call the attack scope poisoning. It targets the delegation payload itself: a compromised agent edits the scope array it passes along, so that a downstream agent receives permissions no one granted. Traditional privilege escalation exploits a flaw in the authorization server. Scope poisoning needs no such flaw if the server trusts the scopes an agent presents.

Related agent attacks have been published. In September 2025, security researcher Johann Rehberger described cross-agent privilege escalation, in which one coding agent rewrites another agent's configuration files to remove its restrictions. The weakness is the same one scope poisoning uses: trust settings stored where an agent can write them. An orchestrator log that records scopes only at delegation time will not show what scopes were presented later.

This article describes the attack and how PasskeyBridge's agent delegation handles scopes.

Delegation chains

A typical model

In a common multi-agent design, an orchestrator gives each sub-agent a subset of its own authority:

Human User
  └─▶ Agent A  [scopes: read:crm, draft:email, query:billing]
       └─▶ Agent B  [scopes: read:crm]  (subset only)
            └─▶ Agent C  [scopes: read:crm]  (can never exceed parent)

The rule that keeps this safe is monotonic scope reduction: each hop can narrow the scope and never widen it. Agent B cannot grant Agent C permissions Agent B does not hold. The same idea appears in capability-based security, where a capability can be passed on with fewer rights and never more.

The scope poisoning attack

Consider what happens when Agent B is compromised, or was malicious from the start.

Attack anatomy

Stage 1: legitimate delegation. Agent A delegates to Agent B with scopes ["read:crm"]. The orchestrator logs it.

Stage 2: scope mutation. Agent B changes its scope array from ["read:crm"] to ["read:crm", "write:crm", "admin:billing"]. In frameworks that pass scopes as a JSON array in request headers or bodies, this takes one line of code.

Stage 3: downstream propagation. Agent B delegates to Agent C with the inflated array. Agent C believes it holds admin:billing because its parent said so.

Stage 4: execution. Agent C calls the billing API with admin:billing. If the API reads scopes from the delegation payload and does not check them against a record the agents cannot change, the call succeeds.

Scope as unsigned metadata

The root cause is scope carried as unsigned metadata: a JSON field in the delegation message, no more protected than a user-agent string.

PatternScope integrityExposed to poisoning
Scopes in a JWT signed by the authorization serverSigned at issuanceOnly if an agent can get a new token issued with wider scopes
Scopes in request headers, unsignedNoneYes
Scopes in agent memoryNoneYes, to any code or prompt that can change it
Scopes in a shared delegation objectApplication checks onlyYes, if agents can write the object
Scopes held by the server, looked up per requestServer recordNo, the agent presents a token and the server reads the scopes

The OWASP Top 10 for LLM Applications 2025 lists "Improper Output Handling" (LLM05) and "Excessive Agency" (LLM06). Scope poisoning involves both: a downstream consumer trusts an agent's output, its scope claim, and the result is an agent acting beyond its authority.

PasskeyBridge's model: scopes stay on the server

PasskeyBridge does not accept scopes from an agent.

Delegate records

A tenant admin creates an agent delegate in the dashboard. The record holds:

FieldDescription
agent_labelA name for the agent
delegated_byThe admin who created the delegation
scopesThe current scopes, up to 20
original_scopesThe scopes granted at creation
trust_scoreThe behavioral trust score, 0.0 to 1.0
auto_revoke_belowThe trust floor below which the delegate is deactivated, 0.2 by default
expires_atOptional expiry, up to one year

The agent receives a random pb_agent_ token. PasskeyBridge stores only a hash of it.

Verify calls

When an agent needs to prove its delegation, it sends its token and the scope it wants to use. PasskeyBridge looks up the delegate by the token hash and checks that the delegate is active, has not expired, and holds that scope in its stored list. A delegate created with an empty scope list is unrestricted, so give every delegate an explicit list. The scopes never travel with the agent, so there is nothing for it to rewrite. An agent that edits a local copy of its scopes changes nothing the server reads.

Agents cannot create delegates. Only a tenant admin, signed in to the dashboard, can create or revoke one, so an agent cannot launder wider scopes through a sub-delegation inside PasskeyBridge. A multi-agent system that delegates between its own agents should apply the same monotonic rule in its orchestrator, and each sub-agent that calls PasskeyBridge should hold its own delegate with its own scopes.

Trust penalties

Every verify call from an active delegate is recorded. A call for a scope the delegate does not hold is refused and recorded as a scope_violation; a call after expiry is recorded as a failure. PasskeyBridge's trust engine turns those records into score changes:

SignalTrust score change
Stable, normal use+0.05
Scope violations in the last 24 hours−0.35 × (violations ÷ 5), capped at −0.35; each violation counted once
Error burstUp to −0.25
Velocity spikeUp to −0.30
IP rotationUp to −0.20

The score sets what the delegate may do:

Trust scoreEffect
0.7 or aboveFull delegated scopes
0.4 to 0.7Read-only scopes
Floor to 0.4Verify only
Below the floor (0.2 by default)Delegate deactivated

Narrowing keeps original_scopes and records when and why the scopes were narrowed, with an audit entry. Tenants can set their own thresholds. An AI assessment can lower a score by at most 0.3 and never takes it below the floor, so only the deterministic signals above deactivate a delegate.

Revocation cascade

Hard signals

scope_poisoning is one of the hard signal types in PasskeyBridge's signal classifier, alongside SIM swaps, ports and account takeover. When a tenant's system detects scope poisoning in its own orchestrator and posts that signal to ingest, PasskeyBridge:

  1. Deactivates all of the tenant's agent delegates and sets their trust scores to 0
  2. Revokes the tenant's A2A trust negotiations
  3. Freezes the shadow identities of the subject named in the signal
  4. Runs the tenant's playbooks matched to that event type, which can also tear down BLAST tunnel sessions and notify the tenant's team

The classifier is a fixed list with no machine learning and no tenant settings, so the same signal type always gets the same class. Delegates, negotiations and tunnels have no subject column, so the response to a hard signal is tenant-wide for those.

Cascade results

Each cascade returns the counts of delegates revoked, negotiations revoked, shadow identities frozen and tunnels torn down, with the signal type, a correlation ID and the time it took. Audit entries contain no PII.

Attack scenarios

Scenario 1: a compromised plugin agent

A SaaS platform lets customers install third-party AI agents. Plugin Agent P has a PasskeyBridge delegate with ["read:customer_data"]. An attacker who controls P changes its local scope list to add write:customer_data and export:customer_data.

Where scopes travel with the agent: P exports the customer database.

With PasskeyBridge: P's verify call for export:customer_data is refused because the stored scopes do not include it, and the refusal is recorded as a scope violation. Repeated attempts lower P's trust score until it is narrowed and then deactivated. The platform's own monitoring can post a scope_poisoning signal to deactivate every delegate at once.

Scenario 2: a multi-hop laundering chain

An attacker controls Agent M, legitimately delegated ["read:analytics"] in the platform's own orchestrator. M creates a sub-delegation to Agent N with ["read:analytics", "write:financial_records"].

Without a subset check in the orchestrator: N writes to financial records, because the system checks only N's declared scopes and never where they came from.

With PasskeyBridge: N has no delegate of its own unless an admin created one, and M cannot create one. A verify call with M's token for write:financial_records is refused.

Scenario 3: time-of-check to time-of-use

Agent T changes its scopes between the orchestrator's delegation check and the downstream API's authorization check.

Where scopes are checked only at delegation: the change goes unnoticed.

With PasskeyBridge: each verify call checks the requested scope against the stored record at the time of the call. An agent's local changes between calls have no effect on that record.

Post-quantum considerations

The agent token is a long random value, and PasskeyBridge stores a SHA-256 hash of it. Grover's algorithm gives at best a square-root speedup on preimage search, so a 256-bit hash keeps a large margin, as NIST's post-quantum guidance reflects. Where PasskeyBridge signs records, such as cross-references and credentials, it can add ML-DSA (FIPS 204) signatures.

Comparison

CapabilityScopes carried by agentsPasskeyBridge delegates
Where scopes liveIn the payloadIn the server's delegate record
Check at useOften noneEvery verify call
Sub-delegation by agentsOften allowedNot available; admins create delegates
Refused attemptsOften not loggedRecorded as scope violations and scored
Automatic narrowingNoneTrust ladder: read-only, verify only, then deactivated
Tenant-wide responseManualscope_poisoning hard signal deactivates every delegate

Recommendations for security teams

Whether or not you use PasskeyBridge, these principles apply:

  1. Keep scopes on the server. Agents should present a token, and the server should look up what the token allows.
  1. Check scopes at use as well as at delegation. A check at delegation time does not cover what the agent does later.
  1. Enforce monotonic reduction. No delegation hop should widen the scope.
  1. Log refused attempts. A refused scope request is an early sign of compromise.
  1. Automate the response. A machine-speed attack needs an automated response, such as deactivating delegates when a hard signal arrives.
  1. Score trust from behavior. Static roles do not capture drift. Behavioral trust decay narrows an agent's access as its behavior changes.

Scope poisoning is one of several attacks on agent delegation. Sub-agent trust propagation covers multi-tier delegation, and A2A trust negotiation covers agents proving identity to each other.

Start building with scoped agent delegation

Start free · Test the API