{"record":{"id":"5d01a02c9ff0307a","repo":"gchq/CyberChef","slug":"crl-entry-extension-object-missing-extname-key","errorCode":null,"errorMessage":"CRL entry extension object missing 'extname' key: ${ext}","messagePattern":"CRL entry extension object missing 'extname' key: (.+?)","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/ParseX509CRL.mjs","lineNumber":163,"sourceCode":"\n    let out = ``;\n\n    extensions.sort((a, b) => {\n        if (!Object.hasOwn(a, \"extname\") || !Object.hasOwn(b, \"extname\")) {\n            return 0;\n        }\n        if (a.extname < b.extname) {\n            return -1;\n        } else if (a.extname === b.extname) {\n            return 0;\n        } else {\n            return 1;\n        }\n    });\n\n    extensions.forEach((ext) => {\n        if (!Object.hasOwn(ext, \"extname\")) {\n            throw new OperationError(`CRL entry extension object missing 'extname' key: ${ext}`);\n        }\n        switch (ext.extname) {\n            case \"authorityKeyIdentifier\":\n                out += `X509v3 Authority Key Identifier:\\n`;\n                if (Object.hasOwn(ext, \"kid\")) {\n                    out += `\\tkeyid:${colonDelimitedHexFormatString(ext.kid.hex.toUpperCase())}\\n`;\n                }\n                if (Object.hasOwn(ext, \"issuer\")) {\n                    out += `\\tDirName:${ext.issuer.str}\\n`;\n                }\n                if (Object.hasOwn(ext, \"sn\")) {\n                    out += `\\tserial:${colonDelimitedHexFormatString(ext.sn.hex.toUpperCase())}\\n`;\n                }\n                break;\n            case \"cRLDistributionPoints\":\n                out += `X509v3 CRL Distribution Points:\\n`;\n                ext.array.forEach((distPoint) => {\n                    const fullName = `Full Name:\\n${formatGeneralNames(distPoint.dpname.full, 4)}`;","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/ParseX509CRL.mjs#L145-L181","documentation":"While rendering CRL-level extensions, formatCRLExtensions iterates crl.getParam().ext and requires each extension object to carry an 'extname' key to switch on. If jsrsasign returns an extension object without 'extname', the op throws. This is an internal contract assertion about jsrsasign's parsed structure, triggered by unusual or unsupported CRL extensions.","triggerScenarios":"A CRL containing an extension that jsrsasign parses into an object lacking 'extname'; a malformed extensions sequence; a jsrsasign version that emits a different key for some extensions.","commonSituations":"Encountering a non-standard or proprietary CRL extension; parsing CRLs from older/newer CAs; version skew between CyberChef's expectations and the bundled jsrsasign.","solutions":["Validate the CRL with 'openssl crl -in crl.pem -noout -text' to see which extension is unusual.","Re-obtain the CRL from the issuer; a corrupt download can produce malformed extension objects.","Check the bundled jsrsasign version against the one this op expects; upgrade/downgrade if the structure changed.","If the CRL is legitimately using an unsupported extension, file an issue so the op tolerates the shape."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const crl = new r.X509CRL(input);\nconst exts = crl.getParam().ext || [];\nif (exts.some(e => !Object.hasOwn(e, \"extname\"))) {\n  throw new Error(\"CRL contains an extension without 'extname'; parsing will fail\");\n}","typeGuard":"function extensionsHaveExtname(exts) {\n  return Array.isArray(exts) && exts.every(e => Object.hasOwn(e, \"extname\"));\n}","tryCatchPattern":"try {\n  return parseX509CRL.run(crlInput, [inputFormat]);\n} catch (e) {\n  if (e.message.includes(\"missing 'extname' key\")) {\n    // an extension shape jsrsasign produced is unexpected; inspect with openssl\n  }\n  throw e;\n}","preventionTips":["Validate the CRL with openssl crl -text first.","Use a current CyberChef build so jsrsasign matches the op.","Report conformant CRLs that the op rejects."],"tags":["crypto","x509","crl","parsing","extensions"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}