fix(security): bind verify_brand_claim response verifier to brand.json authorization - #5988
Open
garvitkaushik-123 wants to merge 1 commit into
Conversation
…n authorization
The designated-task response-signing verifier checked signature, adcp_use,
freshness, and request_hash, but no step confirmed the signing key was
authorized for the asserted brand_domain. Since brand_domain and agent_url are
attacker-choosable fields inside the signed payload, an attacker running a
conformant brand-agent for a domain it controls could emit a cryptographically
valid `owned` envelope for any brand_domain (NS-SIG-002) — the signature
attested authorship, not brand authority.
Adds a normative Brand-authorization cross-check step mirroring governance
step 13: online verifiers MUST resolve {brand_domain}'s brand.json, match a
type:brand agents[] entry whose url byte-equals agent_url
(response_signature_agent_not_in_brand_json / _brand_json_ambiguous), and
resolve kid only within that entry's jwks_uri, before trusting either an
assertion or a rejection. Cross-referenced from both brand-claim trust models;
crypto-independent conformance vectors added.
Closes adcontextprotocol#5826
Contributor
There was a problem hiding this comment.
The automated review encountered an issue (possibly reached max turns, timed out, or failed to post the final gh pr review). A human reviewer should take this PR.
This is an automated message from the Argus AI review workflow.
bokelley
requested changes
Jul 23, 2026
bokelley
left a comment
Contributor
There was a problem hiding this comment.
This changes verifier behavior too strongly for a 3.1 patch and conflicts with the recorded rollout: 3.2 should treat unbound evidence as advisory/untrusted, while mandatory hard-fail brand authorization is a 4.0 contract. Please rework this around the 3.2 trust annotation/advisory behavior and keep the eventual mandatory rejection semantics for the 4.0 design.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #5826 (security audit
NS-SIG-002, P0 — brand-spoofing).The designated-task payload-envelope response-signing profile required a
verify_brand_claim/verify_brand_claimsverifier to check the JWS signature,adcp_use, freshness, andrequest_hash— but no step bound the signing key to the assertedbrand_domain. Sincebrand_domainandagent_urlare attacker-choosable fields inside the payload the same key signs, an attacker running a conformant brand-agent for a domain it controls can emit a cryptographically validownedenvelope forbrand_domain: "victim.example". The signature attests authorship, not brand authority.Fix
Adds a normative Brand-authorization cross-check verifier step, mirroring the two anti-spoofing controls the spec already relies on — the governance token's step-13
iss→brand.json binding and the request-signing agent-URL match. Before trusting a signed envelope as evidence aboutbrand_domain, an online verifier MUST:{brand_domain}/.well-known/brand.json(SSRF-safe, one redirect).type: "brand"agents[]entry whoseurlbyte-equals the envelope'sagent_url— rejectresponse_signature_agent_not_in_brand_json(none) /response_signature_brand_json_ambiguous(>1).kidonly within that entry'sjwks_uri.Until it passes,
brand_domain/agent_urlare untrusted. The binding applies to both assertion and rejection directions (an unbound signer could forge either).Files
docs/building/by-layer/L1/security.mdx— the normative step (with reject reasons + vector citation).docs/brand-protocol/tasks/verify_brand_claim.mdx/verify_brand_claims.mdx— trust-model cross-references (single + batch envelope).static/compliance/source/test-vectors/brand-response-signing/brand-authorization-cross-check.json— 6 crypto-independent authorization-layer vectors.Notes / scope
NS-SIG-002registry from the closed fix(protocol): add anti-drift checks and Tier-1 security fixes #5833 was never merged tomain, so there is nothing to flip; this PR ships the normative fix + conformance vector only, per the narrow-PR disposition on fix(protocol): add anti-drift checks and Tier-1 security fixes #5833.request_signature_agent_not_in_brand_json).Test plan
lint-compliance-packaged-refspasses (no unresolvable refs)static/compliance/source/is protocol-scoped)