Skip to content

Register x-agent-trust extension#67

Merged
handrews merged 3 commits intoOAI:mainfrom
razashariff:register-x-agent-auth
Apr 11, 2026
Merged

Register x-agent-trust extension#67
handrews merged 3 commits intoOAI:mainfrom
razashariff:register-x-agent-auth

Conversation

@razashariff
Copy link
Copy Markdown
Contributor

Registers the x-agent-auth extension for agent trust verification, as suggested by @handrews in Discussion #5267.

The extension declares agent authentication requirements for API endpoints. AI agents present signed trust tokens (JWT-structured, ECDSA P-256) verified locally using cached issuer public keys (JWKS pattern). Trust levels gate access per endpoint.

Follows the existing format from x-twitter.md.

@razashariff razashariff requested a review from a team as a code owner March 29, 2026 19:22
@razashariff
Copy link
Copy Markdown
Contributor Author

Hi @miqui @handrews -- thanks for the approval. Is there anything else needed to get this merged? Happy to address any feedback.

@miqui
Copy link
Copy Markdown
Contributor

miqui commented Apr 1, 2026

@razashariff - I have added this to the week TDC agenda. We should be able to merge it then.

Comment thread registries/_extension/x-agent-auth.md Outdated
@razashariff
Copy link
Copy Markdown
Contributor Author

No, x-agent-trust-required is not registered separately yet. Happy to register it as a follow-up PR if the group prefers it as a standalone entry.

@handrews
Copy link
Copy Markdown
Member

handrews commented Apr 2, 2026

@razashariff we talked about some more general auth planning ideas in the TDC (technical developer community) call today, which might impact this so we did not get to deciding on merging it. I might have some additional feedback here between now and next week based on that more general planning, and we should be able to get things merged then.

@handrews
Copy link
Copy Markdown
Member

handrews commented Apr 2, 2026

@razashariff I guess my first question here is why this is a new OpenAPI Object / Operation Object field instead of leveraging the Security Scheme Object and Security Requirement Object. How are you thinking about the relationship between these things?

@razashariff
Copy link
Copy Markdown
Contributor Author

Thanks Henry, appreciate the update. Happy to align with the broader auth direction -- let me know if any changes are needed and I'll update the PR. Looking forward to next week.

@razashariff
Copy link
Copy Markdown
Contributor Author

The core issue is that agent authentication introduces a concept that doesn't exist in the current Security Scheme model: graduated trust.

Today's securitySchemes answer a binary question -- is this caller authenticated? Agent auth answers a different question -- how much should I trust this caller, and what should I allow based on that trust level?

An agent with a valid OAuth2 token is authenticated. But that tells the API nothing about whether the agent has been verified, what its behaviour history looks like, whether it's been sanctioned, or what trust tier it belongs to. Trust levels (L0-L4) gate access per operation based on verified agent identity and reputation -- that's a layer above authentication.

The verification model is also distinct. Agent trust tokens use JWKS-based local verification with pre-signed credentials from a trust authority. No redirect flows, no token introspection, no authorization server round-trips. The API caches the issuer's public keys and verifies independently. This maps closer to certificate-based identity than to OAuth2 or OpenID flows.

There have been 30+ CVEs filed against MCP implementations in 2026 (CVE-2026-23744, CVE-2026-0756, CVE-2025-6514). The root cause in most cases is that APIs have no way to verify agent identity or enforce trust-based access. The OWASP MCP Security Cheat Sheet documents this gap.

I built this as an extension because it addresses a pattern that the current Security Scheme types weren't designed for. If the auth rework creates a path to express this within the core security model, I'd welcome that and will adapt accordingly.

@miqui
Copy link
Copy Markdown
Contributor

miqui commented Apr 6, 2026

hi @razashariff Can you point out the exact text of the OWASP MCP security guide that you are referring to?

I don't see a concern in merging this PR as is unless something significant shows up before the next TDC. If changes need to be made later, that should be fine too.

@lornajane
Copy link
Copy Markdown
Contributor

Could you comment on how you see the comparison between the graduated trust compares with the scopes required aspect of the existing OAuth2 support? I know you're getting a lot of questions here but that's because we're supportive of the change but WITH one eye on the changes we know are coming in OpenAPI 3.3. If there's a way to get this extension registered in a more forwards-compatible way, I would like us to do that even if it takes a little longer to get it right.

@razashariff
Copy link
Copy Markdown
Contributor Author

Hi @miqui, thanks for the quick response and for the positive signal on merging.

The relevant text is from the OWASP MCP Security Cheat Sheet under "Best Practices" sections 6 and 7:

Section 6 - Authentication, Authorization & Transport Security:

"Enforce authentication on all remote MCP server endpoints. Use OAuth 2.0 with PKCE for remote server authorization flows. Bind session IDs to user-specific context to prevent session hijacking. Validate on each request that the session or token belongs to the current requester; reject the call if it does not (prevents confused deputy)."

Section 7 - Message-Level Integrity and Replay Protection:

"Transport-layer security (TLS) protects data in transit but does not guarantee message integrity at the application layer. A compromised proxy, middleware, or host-level agent can modify JSON-RPC payloads after TLS termination. Message-level signing ensures that tool calls and responses have not been tampered with between client and server. Sign each MCP message (JSON-RPC request body) with an asymmetric key (e.g., ECDSA P-256) bound to the sender's identity... Bind signatures to agent or user identity. Each signed message should include the signer's identity reference (e.g., a certificate fingerprint or public key hash) so the receiver can attribute and audit the request cryptographically."

Full cheat sheet: https://cheatsheetseries.owasp.org/cheatsheets/MCP_Security_Cheat_Sheet.html

The `x-agent-auth` extension provides the OpenAPI-level mechanism for advertising these authentication and signing requirements at the specification level, so that client tooling can discover and enforce them without relying on out-of-band documentation.

Happy to refine the extension wording in a follow-up PR if anything surfaces at the next TDC. Appreciate your review.

Raza

@razashariff
Copy link
Copy Markdown
Contributor Author

razashariff commented Apr 6, 2026

Thanks for the follow-up @lornajane -- and thanks for the TSC's patience on this. This is exactly the distinction I should have made clearer in the original PR.

Graduated trust vs OAuth2 scopes -- orthogonal, not overlapping

Concern OAuth2 scopes Agent trust level
Question answered What is the client allowed to do? How trustworthy is this specific agent instance?
Granted at Authorisation consent time (user) Issuance time (agent passport issued)
Evaluated at Request time (server checks scopes) Request time (server checks trust level)
Scope of decision Per-operation permissions Per-operation minimum assurance
Revocation Token revocation affects all requests Agent-specific, one agent revoked without affecting others

They compose rather than replace each other. A request to `POST /payments` might require both:

  • OAuth2 scope `write:payments` (the user authorised the client to move money on their behalf), and
  • Agent trust level L3 or higher (the specific agent instance has passed automated scanning and is allowed to execute financial actions)

Neither check substitutes for the other. An agent can have the right scope but insufficient trust level (rejected). An agent can be highly trusted but lack the scope (rejected). Only agents satisfying both pass the trust gate.

The practical difference matters because OAuth2 binds authorisation to the client, not to individual agent instances running inside that client. Two agent instances running under the same client and the same token can have different trust levels (one has fresh code attestation, the other has not yet passed scanning). Trust levels fill that gap.

Forward compatibility with 3.3

You raise the critical point. I'd like to structure this so it can graduate cleanly from an extension to a first-class mechanism in 3.3 without breaking existing specs. Two directions I've considered:

Direction A -- Extension mirroring the security field syntax:

paths:
  /payments:
    post:
      security:
        - oauth2: [write:payments]
      x-agent-auth:
        - agentTrust: [L3]

The x-agent-auth field uses the same array-of-objects shape as `security`. When 3.3 promotes it, specs migrate via a simple rename with no structural changes.

Direction B -- Treat it as a proposed new security scheme type:

components:
  securitySchemes:
    agentTrust:
      type: agentTrust
      minLevel: L2
      verificationEndpoint: https://trust.example.com/verify
paths:
  /payments:
    post:
      security:
        - oauth2: [write:payments]
        - agentTrust: [L3]

This uses the first-class `security:` field today and adds `agentTrust` as a new type in `securitySchemes`. Strictly, the new type value requires a spec amendment -- which is exactly what 3.3 could land. Until then, the extension acts as a forward-looking reservation of the syntax.

I'd lean toward Direction B for forward compatibility. It means the extension today already uses the structure that 3.3 would formalise, and the migration is "promote the type from extension-registered to spec-recognised" rather than rewriting the spec files.

Would either direction align with what the TSC is considering for 3.3? Happy to restructure the PR accordingly. I want this to land in a way that survives 3.3 without requiring a second migration from implementers.

Raza

@handrews
Copy link
Copy Markdown
Member

handrews commented Apr 6, 2026

@razashariff

The relevant text is...

I think the question here is how this text relates to your specific effort. This seems to be setting forth some general guidelines rather than endorsing a specific approach such as your IETF drafts. Which is fine if you're putting forth a possible solution, but it kind-of sounds like you're saying that these MCP documents endorse your own approach, specifically?

You don't need to prove that your proposal will be adopted to get an extension registered (extensions are for experimentation, after all), we're just trying to understand how your proposals relate to these documents since you have referenced them repeatedly.

@handrews
Copy link
Copy Markdown
Member

handrews commented Apr 6, 2026

Direction A -- Extension mirroring the security field syntax:

The issue with mirroring the security field syntax is that it is one of several features that require unusual handling in terms of resolving component names. That's going to be a heavier lift for tools — some of them might have their code organized well enough to re-use the infrastructure, but this sort of resolution is generally a thorny area to work with.

Part of the extension review process is making sure that the extensions are reasonably easy to implement in major tools.

You're correct that we can't add a new type value until 3.3, but what I need to spend a bit of time looking into is whether we might be able to creatively re-use the fairly generic type: apiKey (which is really just an input parameter with limited options) to get this information represented in a way that will be easier to support. If this boils down to putting something in a header or query parameter (or several something in different headers and query parameters), plus a bit of metadata, this might be a path that would see easier adoption. I should have more time to look at your I-Ds today or tomorrow.

This is similar to @lornajane 's questions about scopes- looking at what we currently have that might be close to what you need as a way to make the extension easier to support.

@razashariff
Copy link
Copy Markdown
Contributor Author

razashariff commented Apr 6, 2026

@handrews -- happy to clarify the relationship.

The OWASP MCP Security Cheat Sheet was developed in discussion with OWASP maintainers who agreed that signed agentic flows materially reduce the attack surface in MCP-based systems. Section 7 (Message-Level Integrity and Replay Protection) is based on the IETF draft I submitted (draft-sharif-mcps-secure-mcp), which specifies per-message ECDSA P-256 signing, nonce-and-timestamp replay protection, and signer-identity binding for JSON-RPC payloads in the MCP context. That IETF draft is one proposed solution to the threat model the cheat sheet documents. Other implementations of the same guidance are possible and equally valid.

Bringing this back to the OpenAPI spec:

The OWASP guidance describes what needs to happen (authenticated, signed, replay-protected agentic requests). The IETF draft describes how one vendor-neutral mechanism can achieve it. The gap both leave open is at the advertisement layer -- how does an API declare to consuming agents that it expects these properties, in a format that standard tooling can parse and enforce?

That's what `x-agent-auth` is proposing. It doesn't mandate ECDSA P-256, doesn't mandate the IETF draft, doesn't mandate any specific wire format. It gives an OpenAPI-level declaration point where an API vendor can say "requests to this operation require agent authentication at minimum level L3" and let the consumer resolve the actual mechanism via configuration or discovery.

Concrete example. A payments API using mutual TLS plus the IETF draft's message signing could advertise:

paths:
  /payments:
    post:
      security:
        - oauth2: [write:payments]
        - agentTrust: [L3]

A different API using a completely different agent-auth stack could use the same `agentTrust` declaration with the mechanism resolved by their security scheme configuration. The extension is a contract surface, not a protocol implementation.

On the point about not needing adoption-proof for an experimental extension: agreed, and that's the lane I'm asking for. Experimental extension registration, not endorsement of the underlying IETF work. If the TSC is comfortable with that, I'm happy to restructure in whichever direction (A or B from my previous comment) lines up best with 3.3 planning.

Hope this helps.

Raza

@razashariff
Copy link
Copy Markdown
Contributor Author

Thanks Henry -- sounds good. Tool compatibility was a key driver for this proposal so aligned with that fully.

Reusing type: apiKey makes sense. Agent authentication on the wire is really just a header carrying a signature plus a bit of metadata, so a generic apiKey-shaped representation fits naturally without needing anything exotic in the spec or in tool code paths.

Whatever shape lands well with you and the TSC I'm happy to work with -- the extension itself is deliberately thin and the heavy lifting happens at the verification layer, not in OpenAPI.

Thanks again,

Raza

@handrews
Copy link
Copy Markdown
Member

handrews commented Apr 6, 2026

@razashariff I seem to be having a bit of trouble finding the HTTP header in question- apologies if I am missing something obvious. Of your three proposed RFC the one that is not MCP or OIDC-specific doesn't seem to define any headers? What is the name and format? Given that I can try to pull together bits from both @lornajane 's questions and mine to offer a suggestion of how this might work within the current security schemes.

@razashariff
Copy link
Copy Markdown
Contributor Author

Hi @handrews — you're right. The umbrella framework draft (draft-sharif-agent-identity-framework) covers the threat model and trust stack but deliberately stayed transport-agnostic; the wire-format headers currently sit in the MCP-specific draft. For the OpenAPI context we want a generic naming, so let me pin it down here:

Header: Agent-Signature

Format (one line, structured fields style per RFC 8941):

Agent-Signature: keyid="<jwk-thumbprint>", alg="ES256", ts=1712425200, nonce="b64url", sig="b64url"

Where:

  • keyid — JWK thumbprint (RFC 7638) of the signing key, resolvable via the JWKS at issuerKeysUrl
  • alg — JWS algorithm identifier (ES256 default, matches x-agent-auth.algorithm)
  • ts — unix seconds, validated against a bounded window (replay protection)
  • nonce — per-message random, receiver rejects duplicates within the window
  • sig — ECDSA signature over the canonical request (method + path + ts + nonce + SHA-256 of body)

Optional companion header for passport / delegation context:

Agent-Passport-Id: <jwk-thumbprint>

That's what the live demo at https://x-agent-auth.fly.dev verifies against /.well-known/agent-trust-keys. Happy to push an update to the demo openapi.yaml so the header + format is explicit in the doc rather than only in the framework text — probably helps both your mapping exercise and Lorna's question on how this sits relative to existing schemes.

If it's useful, I can also extract this into a short standalone section in the framework draft so there's a single citable reference rather than asking reviewers to pull it from the MCP draft.

Thanks both — this is the shaping that cleans it up for a clean landing.

Raza

@razashariff
Copy link
Copy Markdown
Contributor Author

Hi Henry — as per your suggestion, I've updated the demo spec so the Agent-Signature header is now defined in-line at https://x-agent-auth.fly.dev/openapi.yaml (under x-agent-auth.header — name, format, fields, example, and RFC references all in one place). Should give you a single spot to pull from for the securitySchemes mapping.

Raza

@handrews
Copy link
Copy Markdown
Member

handrews commented Apr 6, 2026

@razashariff thanks! For your I-Ds, you'll need an "IANA Considerations" section with a "Field Name Registration" section. RFC9110 has an example of this, although you can probably find other RFCs that have this section for headers using the structured field syntax. But including that will help folks used to reading IETF drafts understand what you're doing. Particularly as your live demo just shows inputs and outputs and not the HTTP messages going back and forth.

With this in mind, I think you could do something like:

components:
  securitySchems:
    AgentTrust:
      type: apiKey
      description: Uses agent trust information in lieu of a traditional API Key.
      in: header
      name: Agent-Signature
      x-agent-trust:
        algorithm: ES256
        trustLevels: [L0, L1, L2, L3, L4]
        issuerKeysUrl: /.well-known/agent-trust-keys
security:
- AgentTrust: [L3]

I'm reading this as setting a minimum trust level of L3 for the API.

So with this approach, you'd have to get tooling providers to notice type: apiKey Security Schemes with the x-agent-trust extension field, and for such schemes, they would check the value in the scopes array in the Security Requirment Object to see what trust level is expected.

This is just off the top of my head, I'll be interested to see what @lornajane , @miqui , @mikekistler and others think. It may not be the best approach! But it is getting it into the current framework, which means at minimum current documentation tools are likely to display it to human readers, even if runtime tools don't do anything with it.

@razashariff
Copy link
Copy Markdown
Contributor Author

Thanks Henry — that's really clear and makes perfect sense. Wrapping it under type: apiKey with the x-agent-trust extension block is a nice pragmatic shape: documentation tools display it today without waiting on a new type, and 3.3 can formalise it properly later without breaking anyone who's already adopted the pattern. It also supports the future roadmap nicely and gives a seamless integration path from the current framework into a first-class type later. Reading the scopes array as a minimum trust requirement works well — that aligns cleanly with how existing tooling already treats the field.

On your two points:

1. IANA Considerations / Field Name Registration — agreed, that's missing from the framework draft. Adding a proper "IANA Considerations" section with a "Field Name Registration" subsection following the RFC 9110 pattern (name, status, structured type, reference) so there's a single citable definition for the header.

2. HTTP message visibility in the live demo — fair point, the current playground only shows token in/out. Updating it so each signed request displays the actual Agent-Signature header on the wire, and the response panel shows the verification path end-to-end.

CC'ing @mikekistler and @lornajane — happy to adjust the shape based on anything you'd prefer differently, especially on the trustLevels vs minLevel question Henry flagged. I don't have strong feelings on that naming as long as the semantics are clear.

Raza

@razashariff
Copy link
Copy Markdown
Contributor Author

Hi Henry — quick update on your two points:

Demo: the live page now has a "Real HTTP with the Agent-Signature header" section that renders the full HTTP request on the wire (signed Agent-Signature and Agent-Passport-Id headers, the canonical request that was signed, and a side-by-side honest vs tampered-body verification so you can see the integrity check actually catch a payload change). Same URL: https://x-agent-auth.fly.dev/

IANA Considerations / Field Name Registration: drafted the section against the framework I-D (RFC 9110 pattern, structured-field Dictionary per RFC 8941, both Agent-Signature and Agent-Passport-Id registered as provisional, full canonical-request format included). Holding the -01 submission until you and Lorna have had a chance to look at the shape — happy to push it whenever it's useful as a citable reference, or fold in any naming/structure tweaks first if there's anything you'd prefer.

No rush on either side — just wanted to flag both are ready.

Hope this helps.

Raza

@miqui
Copy link
Copy Markdown
Contributor

miqui commented Apr 6, 2026

@handrews

I think what you are suggesting here:

components:
  securitySchemes:
    AgentTrust:
      type: apiKey
      description: Uses agent trust information in lieu of a traditional API Key.
      in: header
      name: Agent-Signature
      x-agent-trust:
        algorithm: ES256
        trustLevels: [L0, L1, L2, L3, L4]
        issuerKeysUrl: /.well-known/agent-trust-keys
security:
- AgentTrust: [L3]

It is a good approach. Would we still need to register the x-agent-trust extension? It would seem so. I want to make sure we are describing "this new security scheme REQUIRES the custom extension".

@handrews
Copy link
Copy Markdown
Member

handrews commented Apr 6, 2026

@miqui yes, it would still be registered, @razashariff would just change the objects field in the registration template and otherwise update the wording (once other folks have had a chance to chime in). Technically it would only extend the Security Scheme Object, but the wording should also discuss the usage in the Security Requirement Object.

make sure we are describing "this new security scheme REQUIRES the custom extension".

Well, the security scheme type is still apiKey so we can't mandate a requirement. But the extension can document that it applies to type: apiKey (unless it applies to something else, e.g. sending that header alongside things from another security scheme, perhaps even a traditional apiKey scheme), and that if you are using type: apiKey to describe the Agent-Signature header then the extension field is necessary for proper functioning.

You probably also want to say something to discourage using Agent-Signature as a regular operation parameter as that could produce contradictions and unclear behavior.

@razashariff
Copy link
Copy Markdown
Contributor Author

Thanks both. Update is straightforward — objects field set to "Security Scheme Object", and the wording extended to cover usage in the Security Requirement Object as well. Ready to push whenever @lornajane and @mikekistler have had a chance to chime in.

Raza

@razashariff razashariff changed the title Register x-agent-auth extension Register x-agent-trust extension Apr 7, 2026
@razashariff
Copy link
Copy Markdown
Contributor Author

Pushed the rename and updated wording per your guidance:

  • File renamed: registries/_extension/x-agent-auth.md -> registries/_extension/x-agent-trust.md
  • objects field set to securitySchemeObject
  • Body wording covers: applies to type: apiKey schemes using Agent-Signature; the x-agent-trust field is required for correct behaviour (documented in prose since the base apiKey type can't grammatically mandate it, per @handrews); may also be used alongside other security schemes; scopes array entries treated as minimum trust level when referenced from a Security Requirement Object; explicit note discouraging Agent-Signature as a regular operation parameter to avoid contradictions with the security layer
  • PR title updated to match
  • Example block now shows the converged YAML with the nested x-agent-trust block

@lornajane @mikekistler -- happy to adjust further if anything reads off, easy to tweak in another commit on the same branch.

Raza

@razashariff
Copy link
Copy Markdown
Contributor Author

@miqui @handrews — pushed the rename + wording in the previous commit, captured all your asks. Easy to tweak further on the same branch if anything else you want me to add or that will help.

Thanks,
Raza

@razashariff
Copy link
Copy Markdown
Contributor Author

@miqui — saw tomorrow's TDC has "AI initiatives" on the agenda. Anything else useful I can prep ahead of the call to support PR #67? Happy to help.

Thanks again,
Raza

@razashariff
Copy link
Copy Markdown
Contributor Author

Hi @lornajane, hope all is well.

Is there any further clarification that would help your framing for PR #67? I noticed there's a TDC today and wanted to check in — Henry made a few suggestions which I've pushed in the latest commit, so just wanted to see if you or the team need anything else from my side.

Thanks again,
Raza

Copy link
Copy Markdown
Contributor

@mikekistler mikekistler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. 👍

@razashariff
Copy link
Copy Markdown
Contributor Author

Thanks @mikekistler — appreciate the approval and thanks @handrews and @miqui for the guidance that got us here.
Team effort :)

Cheers for now,
Raza

@handrews handrews merged commit 1e21ad2 into OAI:main Apr 11, 2026
1 check passed
@handrews
Copy link
Copy Markdown
Member

@razashariff OK, it's merged! Just to be clear, having it in the registry doesn't necessarily mean tools will support it. You'll need to do your own evangelism for that- good luck!

@razashariff
Copy link
Copy Markdown
Contributor Author

Thanks Henry -- really appreciate the guidance throughout. Understood on evangelism, that's the next phase. Will keep you and the rest of the OpenAPI team updated as traction builds.

Cheers,
Raza

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants