{"record":{"id":"27c7e1bf3e5a0e42","repo":"gchq/CyberChef","slug":"pem-footer-footer-not-found-27c7e1","errorCode":null,"errorMessage":"PEM footer '${footer}' not found","messagePattern":"PEM footer '(.+?)' not found","errorType":"validation","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/PubKeyFromCert.mjs","lineNumber":47,"sourceCode":"        this.checks = [];\n    }\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 CERTIFICATE-----/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 CERTIFICATE-----\";\n            const indexFooter = input.indexOf(footer, indexBase64);\n            if (indexFooter === -1) {\n                throw new OperationError(`PEM footer '${footer}' not found`);\n            }\n\n            const certPem = input.substring(match.index, indexFooter + footer.length);\n            const cert = new r.X509();\n            cert.readCertPEM(certPem);\n            let pubKey;\n            try {\n                pubKey = cert.getPublicKey();\n            } catch {\n                throw new OperationError(\"Unsupported public key type\");\n            }\n            const pubKeyPem = r.KEYUTIL.getPEM(pubKey);\n\n            // PEM ends with '\\n', so a new key always starts on a new line\n            output += pubKeyPem;\n        }\n        return output;\n    }","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/PubKeyFromCert.mjs#L29-L65","documentation":"Public Key from Certificate scans the input for '-----BEGIN CERTIFICATE-----' markers and, for each, looks for the matching '-----END CERTIFICATE-----' footer. If a BEGIN marker is found but the END marker is absent after it, the PEM is truncated/malformed and the op throws rather than feeding invalid PEM to jsrsasign.","triggerScenarios":"Pasting a PEM whose END line was cut off; a BEGIN marker inside a larger blob with no matching END; copy-paste that dropped the footer; concatenation of certs where the last one is incomplete.","commonSituations":"Terminal/copypaste truncation of long PEM output; a certificate chain where one cert is clipped; PEM embedded in prose with the footer stripped.","solutions":["Ensure every '-----BEGIN CERTIFICATE-----' has a matching '-----END CERTIFICATE-----'.","Re-copy the full PEM including both delimiters from the source.","If the input is not PEM, convert it to PEM first (e.g. openssl x509 -in cert.der -inform DER -outform PEM).","Remove any stray BEGIN markers from surrounding text."],"exampleFix":"// before: truncated PEM\nrun(\"-----BEGIN CERTIFICATE-----\\nMIIB...\\n\");\n\n// after: complete PEM\nrun(\"-----BEGIN CERTIFICATE-----\\nMIIB...\\n-----END CERTIFICATE-----\\n\");","handlingStrategy":"validation","validationCode":"function pemHasMatchingFooter(pem) {\n  let idx = pem.indexOf(\"-----BEGIN CERTIFICATE-----\");\n  while (idx !== -1) {\n    const after = idx + \"-----BEGIN CERTIFICATE-----\".length;\n    if (pem.indexOf(\"-----END CERTIFICATE-----\", after) === -1) return false;\n    idx = pem.indexOf(\"-----BEGIN CERTIFICATE-----\", after);\n  }\n  return true;\n}\nif (!pemHasMatchingFooter(input)) throw new Error(\"PEM is missing an END CERTIFICATE footer\");","typeGuard":"function isCompletePemChain(pem) {\n  let idx = pem.indexOf(\"-----BEGIN CERTIFICATE-----\");\n  while (idx !== -1) {\n    const after = idx + \"-----BEGIN CERTIFICATE-----\".length;\n    if (pem.indexOf(\"-----END CERTIFICATE-----\", after) === -1) return false;\n    idx = pem.indexOf(\"-----BEGIN CERTIFICATE-----\", after);\n  }\n  return true;\n}","tryCatchPattern":"try {\n  return pubKeyFromCert.run(input, []);\n} catch (e) {\n  if (e.message.startsWith(\"PEM footer\")) {\n    // re-copy the full PEM including the END line\n  }\n  throw e;\n}","preventionTips":["Always copy both BEGIN and END PEM delimiters.","Convert DER to PEM with openssl if the input is binary.","Remove stray BEGIN markers from surrounding prose."],"tags":["crypto","x509","certificate","pem","input-validation"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}