{"record":{"id":"666ef1f29d506b51","repo":"oven-sh/bun","slug":"invalid-purpose","errorCode":"INVALID_PURPOSE","errorMessage":"INVALID_PURPOSE","messagePattern":"INVALID_PURPOSE","errorType":"error_code","errorClass":"CertError","httpStatus":null,"severity":"error","filePath":"src/http/error.rs","lineNumber":173,"sourceCode":"    #[error(\"OUT_OF_MEM\")]\n    OUT_OF_MEM,\n    #[error(\"DEPTH_ZERO_SELF_SIGNED_CERT\")]\n    DEPTH_ZERO_SELF_SIGNED_CERT,\n    #[error(\"SELF_SIGNED_CERT_IN_CHAIN\")]\n    SELF_SIGNED_CERT_IN_CHAIN,\n    #[error(\"UNABLE_TO_GET_ISSUER_CERT_LOCALLY\")]\n    UNABLE_TO_GET_ISSUER_CERT_LOCALLY,\n    #[error(\"UNABLE_TO_VERIFY_LEAF_SIGNATURE\")]\n    UNABLE_TO_VERIFY_LEAF_SIGNATURE,\n    #[error(\"CERT_CHAIN_TOO_LONG\")]\n    CERT_CHAIN_TOO_LONG,\n    #[error(\"CERT_REVOKED\")]\n    CERT_REVOKED,\n    #[error(\"INVALID_CA\")]\n    INVALID_CA,\n    #[error(\"PATH_LENGTH_EXCEEDED\")]\n    PATH_LENGTH_EXCEEDED,\n    #[error(\"INVALID_PURPOSE\")]\n    INVALID_PURPOSE,\n    #[error(\"CERT_UNTRUSTED\")]\n    CERT_UNTRUSTED,\n    #[error(\"CERT_REJECTED\")]\n    CERT_REJECTED,\n    #[error(\"SUBJECT_ISSUER_MISMATCH\")]\n    SUBJECT_ISSUER_MISMATCH,\n    #[error(\"AKID_SKID_MISMATCH\")]\n    AKID_SKID_MISMATCH,\n    #[error(\"AKID_ISSUER_SERIAL_MISMATCH\")]\n    AKID_ISSUER_SERIAL_MISMATCH,\n    #[error(\"KEYUSAGE_NO_CERTSIGN\")]\n    KEYUSAGE_NO_CERTSIGN,\n    #[error(\"UNABLE_TO_GET_CRL_ISSUER\")]\n    UNABLE_TO_GET_CRL_ISSUER,\n    #[error(\"UNHANDLED_CRITICAL_EXTENSION\")]\n    UNHANDLED_CRITICAL_EXTENSION,\n    #[error(\"KEYUSAGE_NO_CRL_SIGN\")]","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/src/http/error.rs#L155-L191","documentation":"CertError::INVALID_PURPOSE maps BoringSSL X509 verify code 26 (X509_V_ERR_INVALID_PURPOSE) via get_cert_error_from_no() in src/http/lib.rs:1545. The certificate's Key Usage or Extended Key Usage does not permit the purpose it is being validated for (TLS server authentication of the fetch target). JS error.code is INVALID_PURPOSE with message 'unsupported certificate purpose' (FetchTasklet.rs:1457).","triggerScenarios":"Server presents a client-auth-only, code-signing, S/MIME, or OCSP-signing certificate where a TLS server cert is required; a CA in the chain carries EKU restrictions that exclude serverAuth so leafs under it fail purpose checks.","commonSituations":"Reusing a client VPN/mTLS cert on the server side, internal tooling issuing certs from a template without extendedKeyUsage=serverAuth, CAs whose EKU constraints propagate down the chain.","solutions":["Inspect the leaf: openssl x509 -in leaf.pem -text -noout | grep -A1 'Extended Key Usage' — it must include TLS Web Server Authentication","Reissue the cert with extendedKeyUsage=serverAuth (plus clientAuth if used for mTLS)","If the CA enforces EKU constraints, reissue from a CA whose EKUs include serverAuth","Stop reusing certs across purposes; one cert, one role"],"exampleFix":"# before: CSR signed without EKU\nopenssl x509 -req -in server.csr -CA ca.pem -CAkey ca.key -out server.pem\n# after: include server EKU\nopenssl x509 -req -in server.csr -CA ca.pem -CAkey ca.key -out server.pem \\\n  -extfile <(printf 'extendedKeyUsage=serverAuth\nkeyUsage=digitalSignature,keyEncipherment')","handlingStrategy":"validation","validationCode":"import { X509Certificate } from \"node:crypto\";\nconst cert = new X509Certificate(await Bun.file(\"server.pem\").text());\nconst eku = (cert as any).keyUsage ?? \"\"; // node exposes keyUsage string\nconst x509text = await Bun.$`openssl x509 -in server.pem -noout -text`.text();\nif (!/TLS Web Server Authentication/.test(x509text)) {\n  throw new Error(\"server.pem lacks serverAuth EKU — fetch will fail INVALID_PURPOSE\");\n}","typeGuard":"function isInvalidPurpose(e: unknown): e is Error & { code: \"INVALID_PURPOSE\" } {\n  return e instanceof Error && (e as any).code === \"INVALID_PURPOSE\";\n}","tryCatchPattern":"try { await fetch(url); } catch (e) { if (isInvalidPurpose(e)) { openCertTicket(new URL(url).host, \"missing serverAuth EKU\"); throw e; } throw e; }","preventionTips":["Certificate templates must pin extendedKeyUsage=serverAuth for TLS endpoints","Never reuse client/VPN/signing certs on servers","Add a cert-lint step (openssl x509 -text grep) to your issuance pipeline"],"tags":["tls","certificate","eku","pki","fetch"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}