elastic/elasticsearch · error · IllegalArgumentException

CEF extensions contain unescaped equals sign

Error message

CEF extensions contain unescaped equals sign

What it means

Thrown by CefParser.parseExtensions when the first chunk's key — i.e. the text before the first '=' — is empty or contains whitespace. A whitespace-containing key indicates an unescaped '=' was missing earlier, so the parser ended up treating prose as a key. The constant UNESCAPED_EQUALS_SIGN is reused here even though the actual root cause can also be an empty leading key.

Source

Thrown at modules/ingest-common/src/main/java/org/elasticsearch/ingest/common/CefParser.java:421

        }
        chunks.add(buffer.toString()); // don't forget the ragged-edge last chunk ;)

        if (chunks.size() == 1) {
            String chunk = chunks.getFirst();
            if (chunk.isEmpty()) {
                return Map.of();
            } else {
                throw new IllegalArgumentException("Invalid extensions in the CEF event: " + chunk);
            }
        }

        // now turn chunks into pairs by splitting on the last space character
        // given 'foo', 'bar\bar = bar baz ', 'quux ', we want to end up with { 'foo': 'bar\bar = bar ', 'baz': 'quux'}
        Map<String, String> extensions = HashMap.newHashMap(chunks.size() - 1);
        String key, value, chunk;
        key = chunks.getFirst();
        if (key.isEmpty() || containsWhitespace(key)) {
            throw new IllegalArgumentException(UNESCAPED_EQUALS_SIGN); // TODO I'm not sure this error message is actually fair anymore
        }
        for (int j = 1; j < chunks.size() - 1; j++) {
            chunk = chunks.get(j);
            int idx = chunk.lastIndexOf(' ');
            if (idx == -1) {
                value = "";
            } else {
                value = chunk.substring(0, idx);
            }
            if (ignoreEmptyValues == false || Strings.isEmpty(value) == false) {
                extensions.put(key, value);
            }

            key = chunk.substring(idx + 1);
            if (key.isEmpty() || containsWhitespace(key)) {
                throw new IllegalArgumentException(UNESCAPED_EQUALS_SIGN); // TODO I'm not sure this error message is actually fair anymore
            }
        }

View on GitHub (pinned to db6a809a66)

Solutions

  1. Inspect the raw CEF extension block — confirm it starts with a bare key (no spaces) followed immediately by '='.
  2. Strip any leading prose or whitespace-only prefix before invoking the cef processor.
  3. Use an on_failure pipeline to quarantine malformed events.
  4. If the producer is yours, emit only 'key=value' pairs in the extension section per the CEF spec.

Example fix

// before — leading text before the first '=' reads as a whitespace-containing key
//   field: 'CEF:0|v|p|1.0|1|n|3|some free text act=login next=...'
//
// after — extension section begins with a clean key=value pair
//   field: 'CEF:0|v|p|1.0|1|n|3|act=login next=...'
Defensive patterns

Strategy: validation

Validate before calling

// The first extension key must be non-empty and contain no whitespace.
boolean firstKeyLooksValid(String ext) {
    if (ext == null) return true;
    int eq = ext.indexOf('=');
    if (eq < 0) return false;
    String key = ext.substring(0, eq);
    return !key.isEmpty() && key.chars().noneMatch(Character::isWhitespace);
}

Try / catch

{
  "on_failure": [
    { "set": { "field": "ingest.error", "value": "cef-bad-first-key" } },
    { "redirect": { "pipeline": "quarantine" } }
  ]
}

Prevention

When it happens

Trigger: Extension string that begins with '=' (empty first key), or that contains words and spaces before the first '='. Examples: '=value second=...', 'foo bar baz=key second=...' (the leading 'foo bar baz' segment, after splitting on '=', leaves a key with internal whitespace).

Common situations: Producer emits a stray '=' at the start of the extension block; a leading free-text fragment precedes the real extensions; field extraction upstream concatenated non-extension text with the extension section.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/be0fbddeece1c45b. Report an issue: GitHub.