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

  1. Inspect the input for the exact '-----END <LABEL>-----' string matching the BEGIN label (same uppercase, same internal spacing).
  2. Ensure the full PEM block including the footer is pasted - check for truncation.
  3. 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

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


AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13). Data as JSON: /api/errors/d57a6e7d9738e41b. Report an issue: GitHub.