{"record":{"id":"b36ac9de1d8da133","repo":"gchq/CyberChef","slug":"pem-footer-footer-not-found-b36ac9","errorCode":null,"errorMessage":"PEM footer '${footer}' not found","messagePattern":"PEM footer '(.+?)' not found","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/PEMToJWK.mjs","lineNumber":53,"sourceCode":"    }\n\n    /**\n     * @param {string} input\n     * @param {Object[]} args\n     * @returns {string}\n     */\n    run(input, args) {\n        let output = \"\";\n        let match;\n        const regex = /-----BEGIN ([A-Z][A-Z ]+[A-Z])-----/g;\n        while ((match = regex.exec(input)) !== null) {\n            // find corresponding end tag\n            const indexBase64 = match.index + match[0].length;\n            const header = input.substring(match.index, indexBase64);\n            const footer = `-----END ${match[1]}-----`;\n            const indexFooter = input.indexOf(footer, indexBase64);\n            if (indexFooter === -1) {\n                throw new OperationError(`PEM footer '${footer}' not found`);\n            }\n\n            const pem = input.substring(match.index, indexFooter + footer.length);\n            if (match[1].indexOf(\"KEY\") !== -1) {\n                if (header === \"-----BEGIN RSA PUBLIC KEY-----\") {\n                    throw new OperationError(\"Unsupported RSA public key format. Only PKCS#8 is supported.\");\n                }\n\n                const key = r.KEYUTIL.getKey(pem);\n                if (key.type === \"DSA\") {\n                    throw new OperationError(\"DSA keys are not supported for JWK\");\n                }\n                const jwk = r.KEYUTIL.getJWKFromKey(key);\n                if (output.length > 0) {\n                    output += \"\\n\";\n                }\n                output += JSON.stringify(jwk);\n            } else if (match[1] === \"CERTIFICATE\") {","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/PEMToJWK.mjs#L35-L71","documentation":"Same BEGIN/END integrity check as PEMToHex, but inside PEMToJWK.run. After matching a '-----BEGIN <label>-----' header it searches for '-----END <label>-----'; if absent it throws before attempting any jsrsasign key parsing. The footer is rebuilt from match[1], so label spacing/case must match exactly.","triggerScenarios":"A matched BEGIN header has no corresponding END footer; footer truncated; footer label mismatched in case/spacing relative to the captured header label.","commonSituations":"Partial copy-paste of a key/certificate PEM; truncated input; hand-edited PEM where the END label was altered.","solutions":["Verify each BEGIN block has a matching END block with the identical label.","Paste the complete PEM including the footer line.","Avoid editing PEM whitespace or label text."],"exampleFix":"// before: header without footer\n-----BEGIN PUBLIC KEY-----\nMIIBIjAN...\n// after: complete block\n-----BEGIN PUBLIC KEY-----\nMIIBIjAN...\n-----END PUBLIC KEY-----","handlingStrategy":"validation","validationCode":"function hasMatchingPemFooter(pem) {\n    const re = /-----BEGIN ([A-Z][A-Z ]+[A-Z])-----/g;\n    let m;\n    while ((m = re.exec(pem)) !== null) {\n        const footer = `-----END ${m[1]}-----`;\n        if (pem.indexOf(footer, m.index + m[0].length) === -1) {\n            return { ok: false, missing: footer };\n        }\n    }\n    return { ok: true };\n}","typeGuard":null,"tryCatchPattern":"try {\n    jwk = chef.PEMToJWK(input);\n} catch (e) {\n    if (e instanceof OperationError && /PEM footer .* not found/.test(e.message)) {\n        // supply the missing END block\n    } else throw e;\n}","preventionTips":["Paste complete key/certificate PEM blocks with matching BEGIN/END labels.","Validate footer presence before conversion.","Do not alter label spacing or case."],"tags":["pem","parsing","jwk","cryptography"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}