gchq/CyberChef · error · OperationError
PEM footer '${footer}' not found
Error message
PEM footer '${footer}' not found What it means
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.
Source
Thrown at src/core/operations/PEMToHex.mjs:54
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const output = [];
let match;
const regex = /-----BEGIN ([A-Z][A-Z ]+[A-Z])-----/g;
while ((match = regex.exec(input)) !== null) {
// find corresponding end tag
const indexBase64 = match.index + match[0].length;
const footer = `-----END ${match[1]}-----`;
const indexFooter = input.indexOf(footer, indexBase64);
if (indexFooter === -1) {
throw new OperationError(`PEM footer '${footer}' not found`);
}
// decode base64 content
const base64 = input.substring(indexBase64, indexFooter);
const bytes = fromBase64(base64, "A-Za-z0-9+/=", "byteArray", true);
const hex = toHexFast(bytes);
output.push(hex);
}
return output.join("\n");
}
}
export default PEMToHex;
View on GitHub (pinned to 4290ea7539)
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.
Example fix
// before: BEGIN present, END missing -----BEGIN CERTIFICATE----- MIIB... // after: matching footer supplied -----BEGIN CERTIFICATE----- MIIB... -----END CERTIFICATE-----
Defensive patterns
Strategy: validation
Validate before calling
function hasMatchingPemFooter(pem) {
const re = /-----BEGIN ([A-Z][A-Z ]+[A-Z])-----/g;
let m;
while ((m = re.exec(pem)) !== null) {
const footer = `-----END ${m[1]}-----`;
if (pem.indexOf(footer, m.index + m[0].length) === -1) {
return { ok: false, missing: footer };
}
}
return { ok: true };
} Try / catch
try {
hex = chef.PEMToHex(input);
} catch (e) {
if (e instanceof OperationError && /PEM footer .* not found/.test(e.message)) {
// e.message names the exact missing footer
} else throw e;
} Prevention
- Always copy the complete BEGIN..END block.
- Validate PEM pair integrity before passing to the operation.
- Avoid hand-editing PEM whitespace or labels.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- PEM footer '${footer}' not found
- Unsupported PEM type '${match[1]}'
- Unsupported RSA public key format. Only PKCS#8 is supported.
- DSA keys are not supported for JWK
- Invalid recipe
AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13).
Data as JSON: /api/errors/d57a6e7d9738e41b.
Report an issue: GitHub.