{"record":{"id":"7cf63b5fcfe24aa4","repo":"oven-sh/bun","slug":"keyusage-no-digital-signature","errorCode":"KEYUSAGE_NO_DIGITAL_SIGNATURE","errorMessage":"KEYUSAGE_NO_DIGITAL_SIGNATURE","messagePattern":"KEYUSAGE_NO_DIGITAL_SIGNATURE","errorType":"error_code","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/http/error.rs","lineNumber":199,"sourceCode":"    #[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\")]\n    KEYUSAGE_NO_CRL_SIGN,\n    #[error(\"UNHANDLED_CRITICAL_CRL_EXTENSION\")]\n    UNHANDLED_CRITICAL_CRL_EXTENSION,\n    #[error(\"INVALID_NON_CA\")]\n    INVALID_NON_CA,\n    #[error(\"PROXY_PATH_LENGTH_EXCEEDED\")]\n    PROXY_PATH_LENGTH_EXCEEDED,\n    #[error(\"KEYUSAGE_NO_DIGITAL_SIGNATURE\")]\n    KEYUSAGE_NO_DIGITAL_SIGNATURE,\n    #[error(\"PROXY_CERTIFICATES_NOT_ALLOWED\")]\n    PROXY_CERTIFICATES_NOT_ALLOWED,\n    #[error(\"INVALID_EXTENSION\")]\n    INVALID_EXTENSION,\n    #[error(\"INVALID_POLICY_EXTENSION\")]\n    INVALID_POLICY_EXTENSION,\n    #[error(\"NO_EXPLICIT_POLICY\")]\n    NO_EXPLICIT_POLICY,\n    #[error(\"DIFFERENT_CRL_SCOPE\")]\n    DIFFERENT_CRL_SCOPE,\n    #[error(\"UNSUPPORTED_EXTENSION_FEATURE\")]\n    UNSUPPORTED_EXTENSION_FEATURE,\n    #[error(\"UNNESTED_RESOURCE\")]\n    UNNESTED_RESOURCE,\n    #[error(\"PERMITTED_VIOLATION\")]\n    PERMITTED_VIOLATION,\n    #[error(\"EXCLUDED_VIOLATION\")]","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/src/http/error.rs#L181-L217","documentation":"CertError::KEYUSAGE_NO_DIGITAL_SIGNATURE maps BoringSSL X509 verify code 39 (X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE) via get_cert_error_from_no() in src/http/lib.rs:1558. The certificate's keyUsage lacks the digitalSignature bit, but the operation being validated (TLS purpose check) requires the key to sign (ECDHE/DHE key exchange signs the handshake with the cert key). JS error.code is KEYUSAGE_NO_DIGITAL_SIGNATURE with message 'key usage does not include digital signature' (FetchTasklet.rs:1490).","triggerScenarios":"Server certificate issued with keyUsage=keyEncipherment only (RSA static key exchange profile) while the negotiated cipher suite is ECDHE_RSA/DHE_RSA, which requires the cert key to sign; client/proxy certs lacking digitalSignature where signing is required.","commonSituations":"Legacy enterprise cert profiles that set only keyEncipherment, modern servers defaulting to forward-secret cipher suites with an old cert, hardware-appliance certs from restrictive templates.","solutions":["Inspect the leaf keyUsage: openssl x509 -in leaf.pem -noout -text | grep -A1 'Key Usage'","Reissue the certificate with keyUsage=critical,digitalSignature,keyEncipherment","Or restrict the server to static-RSA-compatible ciphers (not recommended: loses forward secrecy)","If an intermediate enforces the restriction, reissue beneath a CA without it"],"exampleFix":"# before\nkeyUsage=critical,keyEncipherment\n# after\nkeyUsage=critical,digitalSignature,keyEncipherment\nopenssl x509 -req -in server.csr -CA ca.pem -CAkey ca.key \\\n  -extfile <(printf 'keyUsage=critical,digitalSignature,keyEncipherment\nextendedKeyUsage=serverAuth') -out server.pem -days 390","handlingStrategy":"validation","validationCode":"import { execSync } from \"node:child_process\";\nconst text = execSync(\"openssl x509 -in server.pem -noout -text\").toString();\nif (!/Digital Signature/.test(text)) {\n  throw new Error(\"cert lacks digitalSignature — ECDHE/DHE handshakes will fail KEYUSAGE_NO_DIGITAL_SIGNATURE\");\n}","typeGuard":"function isNoDigitalSignature(e: unknown): e is Error & { code: \"KEYUSAGE_NO_DIGITAL_SIGNATURE\" } {\n  return e instanceof Error && (e as any).code === \"KEYUSAGE_NO_DIGITAL_SIGNATURE\";\n}","tryCatchPattern":"try { await fetch(url); } catch (e) { if (isNoDigitalSignature(e)) { openCertTicket(new URL(url).host, \"reissue with digitalSignature keyUsage\"); throw e; } throw e; }","preventionTips":["Always issue TLS server certs with digitalSignature (+keyEncipherment for RSA)","Do not reuse legacy keyEncipherment-only certs on modern forward-secret stacks","Cert-lint keyUsage in the issuance pipeline"],"tags":["tls","certificate","keyusage","cipher-suites","pki"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}