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

  1. Ensure every '-----BEGIN CERTIFICATE-----' has a matching '-----END CERTIFICATE-----'.
  2. Re-copy the full PEM including both delimiters from the source.
  3. If the input is not PEM, convert it to PEM first (e.g. openssl x509 -in cert.der -inform DER -outform PEM).
  4. 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

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.