gchq/CyberChef · error · OperationError
PEM footer '${footer}' not found
Error message
PEM footer '${footer}' not found What it means
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.
Source
Thrown at src/core/operations/PubKeyFromCert.mjs:47
this.checks = [];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
let output = "";
let match;
const regex = /-----BEGIN CERTIFICATE-----/g;
while ((match = regex.exec(input)) !== null) {
// find corresponding end tag
const indexBase64 = match.index + match[0].length;
const footer = "-----END CERTIFICATE-----";
const indexFooter = input.indexOf(footer, indexBase64);
if (indexFooter === -1) {
throw new OperationError(`PEM footer '${footer}' not found`);
}
const certPem = input.substring(match.index, indexFooter + footer.length);
const cert = new r.X509();
cert.readCertPEM(certPem);
let pubKey;
try {
pubKey = cert.getPublicKey();
} catch {
throw new OperationError("Unsupported public key type");
}
const pubKeyPem = r.KEYUTIL.getPEM(pubKey);
// PEM ends with '\n', so a new key always starts on a new line
output += pubKeyPem;
}
return output;
}View on GitHub (pinned to 4290ea7539)
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.
Example fix
// before: truncated PEM
run("-----BEGIN CERTIFICATE-----\nMIIB...\n");
// after: complete PEM
run("-----BEGIN CERTIFICATE-----\nMIIB...\n-----END CERTIFICATE-----\n"); Defensive patterns
Strategy: validation
Validate before calling
function pemHasMatchingFooter(pem) {
let idx = pem.indexOf("-----BEGIN CERTIFICATE-----");
while (idx !== -1) {
const after = idx + "-----BEGIN CERTIFICATE-----".length;
if (pem.indexOf("-----END CERTIFICATE-----", after) === -1) return false;
idx = pem.indexOf("-----BEGIN CERTIFICATE-----", after);
}
return true;
}
if (!pemHasMatchingFooter(input)) throw new Error("PEM is missing an END CERTIFICATE footer"); Type guard
function isCompletePemChain(pem) {
let idx = pem.indexOf("-----BEGIN CERTIFICATE-----");
while (idx !== -1) {
const after = idx + "-----BEGIN CERTIFICATE-----".length;
if (pem.indexOf("-----END CERTIFICATE-----", after) === -1) return false;
idx = pem.indexOf("-----BEGIN CERTIFICATE-----", after);
}
return true;
} Try / catch
try {
return pubKeyFromCert.run(input, []);
} catch (e) {
if (e.message.startsWith("PEM footer")) {
// re-copy the full PEM including the END line
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Terminal/copypaste truncation of long PEM output; a certificate chain where one cert is clipped; PEM embedded in prose with the footer stripped.
Related errors
AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13).
Data as JSON: /api/errors/27c7e1bf3e5a0e42.
Report an issue: GitHub.