{"record":{"id":"f202072b4d8c0b17","repo":"mastra-ai/mastra","slug":"expected-a-pem-encoded-public-key-or-certificate-s","errorCode":null,"errorMessage":"Expected a PEM-encoded public key or certificate string for Agent Card verification","messagePattern":"Expected a PEM-encoded public key or certificate string for Agent Card verification","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client-sdks/client-js/src/utils/verify-agent-card-signature.ts","lineNumber":78,"sourceCode":"async function importVerificationKey(\n  key: AgentCardVerificationKey,\n  algorithm: string,\n): Promise<CryptoKey | Uint8Array> {\n  if (isCryptoKey(key) || key instanceof Uint8Array) {\n    return key;\n  }\n\n  if (key instanceof ArrayBuffer) {\n    return new Uint8Array(key);\n  }\n\n  if (typeof key === 'string') {\n    if (algorithm.startsWith('HS')) {\n      return new TextEncoder().encode(key);\n    }\n\n    if (!isPem(key)) {\n      throw new Error('Expected a PEM-encoded public key or certificate string for Agent Card verification');\n    }\n\n    if (isCertificate(key)) {\n      return importX509(key, algorithm);\n    }\n\n    return importSPKI(key, algorithm);\n  }\n\n  return importJWK(key as JWK, algorithm);\n}\n\nexport async function verifyAgentCardSignatureIfPresent(\n  agentCard: AgentCard,\n  options: VerifyAgentCardSignatureOptions,\n): Promise<AgentCard> {\n  const signatures = agentCard.signatures ?? [];\n  if (signatures.length === 0) {","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/client-sdks/client-js/src/utils/verify-agent-card-signature.ts#L60-L96","documentation":"importVerificationKey converts the JWK 'kty'-independent key material from an agent's signature verification config into a WebCrypto key. For non-HS algorithms the key string must be PEM-encoded; if isPem(key) fails the client throws this error because it cannot import the raw string for asymmetric verification.","triggerScenarios":"Verifying an Agent Card JWS signature with importVerificationKey where the provided key string is not PEM (missing '-----BEGIN' headers), the algorithm is not HS* (e.g. RS256/ES256) but the config supplies a raw base64 secret or a bare public key body without PEM armor.","commonSituations":"Copying a raw RSA public key body without the -----BEGIN PUBLIC KEY----- armor, pasting an HS256 shared secret while the algorithm is RS256, retrieving the key from a JWKS endpoint (bare base64 JWK values) instead of a PEM certificate, or a misconfigured env var that truncated the PEM.","solutions":["Ensure the key string includes full PEM armor: -----BEGIN PUBLIC KEY-----/-----END PUBLIC KEY----- (or CERTIFICATE for X.509).","If using an HS* algorithm, pass the shared secret as the key; otherwise supply the PEM public key/certificate, not a raw secret.","If your source is a JWKS (n/e values), convert the JWK to PEM before verification.","Check env/config for truncation or whitespace corruption of the PEM (newlines replaced/lost).","Match the algorithm in the Agent Card's JWS header with the key type you provide."],"exampleFix":"// before\nconst key = process.env.AGENT_PUBLIC_KEY_BODY; // 'MIIBIjANBgkq...'\nverifyAgentCardSignature(card, key, 'RS256');\n// after\nconst key = '-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkq...\\n-----END PUBLIC KEY-----';\nverifyAgentCardSignature(card, key, 'RS256');","handlingStrategy":"validation","validationCode":"function isPemString(key: string): boolean {\n  return /-----BEGIN (PUBLIC KEY|CERTIFICATE)-----[\\s\\S]+-----END (PUBLIC KEY|CERTIFICATE)-----/.test(key.trim());\n}\nif (!key.startsWith('HS') && !isPemString(publicKeyOrCert)) throw new Error('Provide PEM-encoded public key/certificate for asymmetric algorithms');","typeGuard":"function isPem(v: string): boolean {\n  return v.includes('-----BEGIN') && v.includes('-----END') && v.includes('KEY') || v.includes('CERTIFICATE');\n}","tryCatchPattern":"try {\n  await verifyAgentCardSignature(card, key, algorithm);\n} catch (e) {\n  if (e.message.includes('PEM-encoded public key')) {\n    console.error('Key is not PEM; re-export with armor or use HS* algorithm with a shared secret');\n  } else throw e;\n}","preventionTips":["Store PEM keys with intact newlines (use multiline env/config, avoid single-line mangling).","Match key type to algorithm: HS* with shared secret, RS/ES/PS* with PEM public key or X.509 cert.","Convert JWKS/JWK keys to PEM before verification.","Load keys at startup and validate format once, not per-request."],"tags":["crypto","validation","configuration","jws","agent-card"],"backgroundTag":"invalid-pem-key","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}