gchq/CyberChef · error · OperationError

failed to format datetime string ${datetime}

Error message

failed to format datetime string ${datetime}

What it means

ParseX509CRL formats date fields (thisUpdate, nextUpdate, revocation dates, invalidity dates) via generalizedDateTimeToUTC, which expects a UTCTime/GeneralizedTime string matching ^\d{12,14}Z$. If jsrsasign hands back a date string not matching that shape, formatting aborts. The input comes from the parsed CRL, so this reflects a malformed or unexpected CRL/date encoding rather than user-typed text.

Source

Thrown at src/core/operations/ParseX509CRL.mjs:110

            out += `\tCRL extensions:\n${formatCRLExtensions(crl.getParam().ext, 8)}\n`;
        }

        out += `Revoked Certificates:\n${formatRevokedCertificates(crl.getRevCertArray(), 4)}
Signature Value:\n${formatCRLSignature(crl.getSignatureValueHex(), 8)}`;

        return out;
    }
}

/**
 * Generalized date time string to UTC.
 * @param {string} datetime
 * @returns UTC datetime string.
 */
function generalizedDateTimeToUTC(datetime) {
    // Ensure the string is in the correct format
    if (!/^\d{12,14}Z$/.test(datetime)) {
        throw new OperationError(`failed to format datetime string ${datetime}`);
    }

    // Extract components
    let centuary = "20";
    if (datetime.length === 15) {
        centuary = datetime.substring(0, 2);
        datetime = datetime.slice(2);
    }
    const year = centuary + datetime.substring(0, 2);
    const month = datetime.substring(2, 4);
    const day = datetime.substring(4, 6);
    const hour = datetime.substring(6, 8);
    const minute = datetime.substring(8, 10);
    const second = datetime.substring(10, 12);

    // Construct ISO 8601 format string
    const isoString = `${year}-${month}-${day}T${hour}:${minute}:${second}Z`;

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Re-export the CRL in canonical PEM/DER from a trusted source (e.g. openssl crl).
  2. Verify the CRL with openssl first: 'openssl crl -in crl.pem -noout -text'.
  3. Check that the jsrsasign version bundled with your CyberChef build matches the one this op was written against.
  4. If the CRL is valid but the date shape differs, report it — the regex may need widening for that GeneralizedTime variant.
Defensive patterns

Strategy: try-catch

Validate before calling

function isValidGeneralizedTime(s) {
  return /^\d{12,14}Z$/.test(s);
}
// Validate each date field before formatting if you control the CRL parsing pipeline.

Type guard

function isGeneralizedTimeString(s) {
  return typeof s === "string" && /^\d{12,14}Z$/.test(s);
}

Try / catch

try {
  return parseX509CRL.run(crlInput, [inputFormat]);
} catch (e) {
  if (e.message.startsWith("failed to format datetime string")) {
    // CRL date encoding is non-standard; validate with openssl externally
  }
  throw e;
}

Prevention

When it happens

Trigger: A CRL whose thisUpdate/nextUpdate fields are not standard UTCTime (YYMMDDHHMMSSZ) or GeneralizedTime; a jsrsasign version that returns dates in a different format; a corrupt or hand-edited CRL; a revocation entry whose date field is malformed.

Common situations: Parsing a CRL produced by a non-RFC-conformant CA; jsrsasign upgrade changing date output; DER that was incorrectly re-encoded; partial/truncated CRL bytes fed in.

Related errors


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