{"record":{"id":"d57a6e7d9738e41b","repo":"gchq/CyberChef","slug":"pem-footer-footer-not-found","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/PEMToHex.mjs","lineNumber":54,"sourceCode":"        ];\n    }\n\n    /**\n     * @param {string} input\n     * @param {Object[]} args\n     * @returns {string}\n     */\n    run(input, args) {\n        const 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 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            // decode base64 content\n            const base64 = input.substring(indexBase64, indexFooter);\n            const bytes = fromBase64(base64, \"A-Za-z0-9+/=\", \"byteArray\", true);\n            const hex = toHexFast(bytes);\n            output.push(hex);\n        }\n        return output.join(\"\\n\");\n    }\n\n}\n\nexport default PEMToHex;\n","sourceCodeStart":36,"sourceCodeEnd":69,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/PEMToHex.mjs#L36-L69","documentation":"Thrown by PEMToHex.run when the BEGIN-tag regex /-----BEGIN ([A-Z][A-Z ]+[A-Z])-----/g matches a header but input.indexOf cannot find the matching '-----END <label>-----' footer at or after the header end. PEM requires a paired BEGIN/END block; a header with no footer is treated as malformed input. The footer label is rebuilt verbatim from match[1], so any spacing/case difference defeats the search.","triggerScenarios":"Input has a '-----BEGIN CERTIFICATE-----' (or any matched label) but the matching '-----END CERTIFICATE-----' is absent; the END tag was truncated during copy-paste; the footer label differs in spacing or case from the captured header label so indexOf returns -1.","commonSituations":"Copy-pasting only the first half of a PEM block; a truncated file; PEM whose footer label has extra/missing spaces so it no longer equals 'END ' + match[1]; concatenation that drops the footer line.","solutions":["Inspect the input for the exact '-----END <LABEL>-----' string matching the BEGIN label (same uppercase, same internal spacing).","Ensure the full PEM block including the footer is pasted - check for truncation.","If generating PEM programmatically, verify an END line is emitted for every BEGIN line."],"exampleFix":"// before: BEGIN present, END missing\n-----BEGIN CERTIFICATE-----\nMIIB...\n// after: matching footer supplied\n-----BEGIN CERTIFICATE-----\nMIIB...\n-----END CERTIFICATE-----","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    hex = chef.PEMToHex(input);\n} catch (e) {\n    if (e instanceof OperationError && /PEM footer .* not found/.test(e.message)) {\n        // e.message names the exact missing footer\n    } else throw e;\n}","preventionTips":["Always copy the complete BEGIN..END block.","Validate PEM pair integrity before passing to the operation.","Avoid hand-editing PEM whitespace or labels."],"tags":["pem","parsing","base64","cryptography"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}