Skip to content

Security considerations

This page addresses two audiences: integrators (your server, calling GenAuth with an access key) and the resource side (your API, or the adapter layer that accepts access tokens). One section per threat: how the attack happens, then graded guidance.

Normative language: MUST / MUST NOT — violating this creates an exploitable gap; SHOULD / SHOULD NOT — strongly recommended, deviate only with a clear reason and accept the risk; MAY — optional hardening.

Threat model at a glance

The attack surface in Agent Identity scenarios collapses into four threats:

ThreatIn one linePrimary defense
Credential theftAn access key or token is stolen and the attacker acts as your server or your agentKey custody constraints + short lifetimes + kill switch
Confused deputyA more privileged intermediary (your server, your agent) is tricked into exercising authority for an attackerPin the delegation subject's source + full resource-side validation
Token replayAn intercepted token is reused within its lifetimeEncrypted transport + aud binding + shortest viable lifetime
Delegation beyond authorityAn agent is delegated authority the delegator never had, or the organization does not allowMinimum-scope discipline + scope intersection + resource-side backstop

One principle runs through the whole page: delegation can only narrow authority, never widen it — and any missing layer of validation MUST be covered by the remaining layers rather than assumed correct upstream (defense in depth).

Credential theft

There are two kinds of credential here, with very different blast radii:

  • Access key (AK/SK): a long-lived, tenant-level credential. Once leaked, an attacker can start delegations in your organization's name — the worst case.
  • Delegate token / access token: short-lived, user-level credentials, attenuated and bound to a single delegation by design. The damage from a leak is bounded by both lifetime and scope.

Security investment is therefore asymmetric: guard keys like a fortress; let tokens limit themselves through short lifetimes and minimum scope. The full requirements around access keys are in the next section; requirements around tokens live in Token replay and Audience binding.

Organization-level consent (see Consent and approval) lets your server hold an access key and start delegations for a user without a real-time click from that user. This path is equivalent to authorizing in the organization's name; a leaked access key is an organization-level risk. Harden it against this checklist.

Decide deliberately before taking this path

The trust premise is that your server itself is trusted. If your caller is a browser, a mobile app, or any environment an end user can reach, you MUST NOT use this path — use the user-level (interactive) consent flow instead.

The constraints, one by one:

  1. Access key custody — You MUST store AK/SK in a key management system (KMS / secret manager), isolated per environment. You MUST NOT commit them to a repository, front-end assets, a mobile bundle, logs or error messages. You SHOULD rotate on a schedule, and rotate immediately on personnel change or suspected leak (see Revocation and incident response).
  2. Network boundary — You SHOULD confine egress for organization-level delegations to a fixed server-side network range, and configure an IP allowlist or use a private network at your network layer. You MUST NOT call from uncontrolled public environments (ephemeral containers whose logs expose the key, developer laptops holding it long-term).
  3. Minimum scope — You MUST request the smallest scope set the task needs (for example webagent.web_search:run). You MUST NOT fall back to broad capabilities or whole bundles to cover authority you "might need later".
  4. Short lifetime — You SHOULD set expiresIn to the shortest duration that completes the task. You SHOULD NOT default to the maximum.
  5. Dedicated agent identifiers — You MUST use a dedicated agent identifier per server-side integration. You MUST NOT share one agent across business lines: audit cannot attribute and the kill switch cannot target.
  6. Audit and alerting — You SHOULD alert on issuance spikes, unusual scopes appearing, and the affected user population widening, and retain end-to-end records by audit_id / grant_id (see Audit and compliance reporting).

Confused deputy

The classic shape: the attacker has no authority themselves, but can get a more privileged intermediary to act for them. In a delegation system that intermediary is your server or your agent — and the attacker does not steal credentials, they manipulate the parameters of the delegation.

The most typical entry point is substituting the delegation subject: if "which user is this delegation for" comes from client-controllable input, an attacker swaps usr_alice for usr_ceo and your server uses its own legitimate key to issue a delegate token in the victim's name.

Integrator defenses:

  • You MUST pin the delegation subject (the user ID) to a server-side session or a trusted identity context. You MUST NOT take the user identifier straight from request parameters, URL query strings or front-end forms.
  • You MUST verify that the state parameter on the interactive callback matches the one you sent, so an authorization result cannot be grafted onto someone else's session.

The two-track compatibility window

The SDK (@eazo/anima v0.2.1) has deprecated the top-level userId parameter in favour of user: { id }, but the server still accepts the old parameter during the compatibility window. That means: even if all your new code uses the new shape, one forgotten piece of old code — or a side path that hand-builds the HTTP request — can still name an arbitrary delegation subject through the old parameter. During the window you SHOULD scan for and block outbound requests carrying a top-level userId at your egress layer (gateway or middleware), and treat the old shape as a defect rather than a style preference. Field contracts: Token and claim reference.

Resource-side defenses (the last layer of defense in depth):

  • You MUST verify that the access token's aud matches you (see Audience binding).
  • You SHOULD recognize the act structure (check act.type === 'eak_delegation'), treat "an agent on behalf of a user" differently from "the user in person", and apply a stricter operation allowlist to the agent channel.
  • You MUST NOT authorize on sub alone — accepting only sub means an agent's attenuated token is indistinguishable from the user's full access, and attenuation dies on your side. Full field semantics for act and scope: Token and claim reference.

Token replay

An intercepted token can be reused within its lifetime. Defense compresses both ends — the chance of interception and the size of the usable window:

  • You MUST carry tokens over TLS end to end. You MUST NOT place a token in a URL query string, logs, error messages, or anywhere visible to the front end.
  • You MUST verify signature and expiry. You SHOULD call introspection on critical paths for online verification.
  • You SHOULD set token lifetimes to the shortest viable value — the shorter the lifetime, the smaller the replay window. Within its lifetime a delegate token expires naturally as its primary end state; emergency recall goes through the key-level and grant-level layers described in Revocation and incident response.
  • The authorization code in the interactive flow is single-use by design. You MUST NOT cache or retry-reuse it on the integration side.

Delegation beyond authority

"You cannot delegate authority you do not have" is the floor principle of this system: the upper bound of one delegation = requested scope ∩ the delegator's real permissions ∩ what organization policy allows (the three-way intersection; concept and release status in Delegate Token and attenuation).

The engineering requirements that follow:

  • Integrators MUST request only scopes the delegator genuinely holds and the current task genuinely needs — apply the intersection principle at request time instead of relying on validation to catch it.
  • Organizations SHOULD maintain explicit allowlists per credential and per agent (which key may request which scopes for which agents), and avoid default configurations where "an empty list means allow everything".
  • The resource side MUST authorize per operation against the token's scope. You MUST NOT treat "the token is valid" as "every operation is permitted".

Audience binding and the token passthrough ban

Each token kind has an explicit audience. Using the wrong one is a vulnerability:

  • A delegate token's aud targets GenAuth token exchange — it is an authorization record, not an access credential. Integrators and agents MUST NOT present a delegate token to any resource service as an access credential, and the resource side MUST NOT accept one.
  • An access token is bound to a single target resource. The resource side MUST verify aud matches itself and MUST NOT accept a token issued for another resource.

Token passthrough is banned outright: no service MUST forward a token it received to a downstream service as-is. Passthrough hands the downstream a token whose aud does not belong to it; the audit chain breaks at that hop and the attenuation boundary fails. The correct approach: when you need to reach a downstream resource, go back to GenAuth and perform a fresh token exchange for that resource. Field semantics: Token and claim reference.

Organizational defenses: accountability and the kill switch

Everything above is technical. Two organizational defenses determine how fast you respond in the moment things go wrong:

  • Accountability on record — Organizations MUST assign an Owner and a Sponsor to every agent and MUST NOT let ownerless agents persist; sponsorship transfers automatically on personnel change. Without an accountable person, it does not matter whether the alert fires — nobody picks it up. Identity model: The agent identity model.
  • Kill switch — You SHOULD rehearse the layered recall path in advance: grant revocation → agent-level kill switch → key-level revocation, with the effective timing and the responsible operator clear for each layer. An incident is not the time to read documentation. Operation matrix: Revocation and incident response.

Next steps