{"record":{"id":"e9bafd1731e938a9","repo":"mastra-ai/mastra","slug":"agent-card-signature-algorithm-protectedheader","errorCode":null,"errorMessage":"Agent Card signature algorithm \"${protectedHeader.alg}\" is not allowed","messagePattern":"Agent Card signature algorithm \"(.+?)\" is not allowed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client-sdks/client-js/src/utils/verify-agent-card-signature.ts","lineNumber":119,"sourceCode":"  if (!canonicalPayload) {\n    throw new MastraClientError(200, 'OK', 'Failed to canonicalize A2A Agent Card for signature verification');\n  }\n\n  const allowedAlgorithms = options.algorithms ?? [...DEFAULT_AGENT_CARD_SIGNATURE_ALGORITHMS];\n  const encodedPayload = base64url.encode(canonicalPayload);\n  const verificationErrors: string[] = [];\n\n  for (const [index, signature] of signatures.entries()) {\n    try {\n      const compactJws = `${signature.protected}.${encodedPayload}.${signature.signature}`;\n      const protectedHeader = decodeProtectedHeader(compactJws);\n\n      if (typeof protectedHeader.alg !== 'string') {\n        throw new Error('Agent Card signature is missing a protected \"alg\" header');\n      }\n\n      if (!allowedAlgorithms.includes(protectedHeader.alg)) {\n        throw new Error(`Agent Card signature algorithm \"${protectedHeader.alg}\" is not allowed`);\n      }\n\n      const verificationKey = await options.keyProvider({\n        agentCard,\n        signature,\n        protectedHeader,\n        alg: protectedHeader.alg,\n        kid: typeof protectedHeader.kid === 'string' ? protectedHeader.kid : undefined,\n        jku: typeof protectedHeader.jku === 'string' ? protectedHeader.jku : undefined,\n        index,\n      });\n\n      if (!verificationKey) {\n        throw new Error('No verification key was provided for Agent Card signature verification');\n      }\n\n      const importedKey = await importVerificationKey(verificationKey, protectedHeader.alg);\n      await compactVerify(compactJws, importedKey, {","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/client-sdks/client-js/src/utils/verify-agent-card-signature.ts#L101-L137","documentation":"After confirming a string `alg` exists, the library checks it against the allowed algorithm list — either options.algorithms or the defaults (ES256/384/512, RS256/384/512, PS256/384/512). If the signature's alg is outside this list (e.g. HS256, EdDSA, none), it throws and records the error per signature; if all signatures fail, the aggregate error is raised.","triggerScenarios":"getAgentCard() with verification enabled where a signature's protected header declares an algorithm not in options.algorithms ?? DEFAULT_AGENT_CARD_SIGNATURE_ALGORITHMS — commonly 'HS256' (symmetric signer), 'EdDSA', or '\"alg\":\"none\"'.","commonSituations":"Server signs with EdDSA (Ed25519) which is not in the default allowlist; developer restricts options.algorithms to RS256 but server uses ES256; symmetric HS signing misused for public card verification.","solutions":["Make the server sign the Agent Card with an allowlisted asymmetric algorithm (ES256 or RS256 recommended).","If the server's algorithm is acceptable, extend options.algorithms — e.g. algorithms: ['ES256','EdDSA'] — and ensure importVerificationKey supports it.","If you intentionally narrowed algorithms, align your keyProvider to return keys matching the algorithms the server actually uses.","Check the signature's protected header (decode base64url) to see the exact alg being rejected."],"exampleFix":"// before\nawait getAgentCard(); // client default algorithms only\n\n// after: allow the server's EdDSA keys\nconst client = new MastraClient({ baseUrl, verifyAgentCardSignature: { keyProvider, algorithms: ['ES256', 'EdDSA'] } });","handlingStrategy":"validation","validationCode":"// before enabling verification, check the server's alg against your allowlist\nconst DEFAULTS = ['ES256','ES384','ES512','RS256','RS384','RS512','PS256','PS384','PS512'];\nconst header = JSON.parse(atob(card.signatures[0].protected.replace(/-/g,'+').replace(/_/g,'/')));\nif (!(options.algorithms ?? DEFAULTS).includes(header.alg)) {\n  console.warn(`server signs with ${header.alg}; add it to options.algorithms or change the signer`);\n}","typeGuard":"function isAllowedAlg(alg: string, allowed: readonly string[]): alg is typeof allowed[number] {\n  return (allowed as readonly string[]).includes(alg);\n}","tryCatchPattern":"try {\n  await client.getAgentCard();\n} catch (e) {\n  if (e instanceof MastraClientError && /algorithm .* is not allowed/.test(e.message)) {\n    // adjust options.algorithms or re-sign server-side, then retry once\n  }\n}","preventionTips":["Document which algorithms your server uses and mirror them in options.algorithms.","Prefer ES256 or RS256 so the default allowlist works out of the box.","Never use symmetric HS algorithms for publicly verifiable Agent Cards.","Test verification end-to-end whenever the signer's algorithm changes."],"tags":["jws","algorithm-allowlist","agent-card","signature-verification"],"backgroundTag":"disallowed-jws-algorithm","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}