{"record":{"id":"be0fbddeece1c45b","repo":"elastic/elasticsearch","slug":"cef-extensions-contain-unescaped-equals-sign","errorCode":null,"errorMessage":"CEF extensions contain unescaped equals sign","messagePattern":"CEF extensions contain unescaped equals sign","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/ingest-common/src/main/java/org/elasticsearch/ingest/common/CefParser.java","lineNumber":421,"sourceCode":"        }\n        chunks.add(buffer.toString()); // don't forget the ragged-edge last chunk ;)\n\n        if (chunks.size() == 1) {\n            String chunk = chunks.getFirst();\n            if (chunk.isEmpty()) {\n                return Map.of();\n            } else {\n                throw new IllegalArgumentException(\"Invalid extensions in the CEF event: \" + chunk);\n            }\n        }\n\n        // now turn chunks into pairs by splitting on the last space character\n        // given 'foo', 'bar\\bar = bar baz ', 'quux ', we want to end up with { 'foo': 'bar\\bar = bar ', 'baz': 'quux'}\n        Map<String, String> extensions = HashMap.newHashMap(chunks.size() - 1);\n        String key, value, chunk;\n        key = chunks.getFirst();\n        if (key.isEmpty() || containsWhitespace(key)) {\n            throw new IllegalArgumentException(UNESCAPED_EQUALS_SIGN); // TODO I'm not sure this error message is actually fair anymore\n        }\n        for (int j = 1; j < chunks.size() - 1; j++) {\n            chunk = chunks.get(j);\n            int idx = chunk.lastIndexOf(' ');\n            if (idx == -1) {\n                value = \"\";\n            } else {\n                value = chunk.substring(0, idx);\n            }\n            if (ignoreEmptyValues == false || Strings.isEmpty(value) == false) {\n                extensions.put(key, value);\n            }\n\n            key = chunk.substring(idx + 1);\n            if (key.isEmpty() || containsWhitespace(key)) {\n                throw new IllegalArgumentException(UNESCAPED_EQUALS_SIGN); // TODO I'm not sure this error message is actually fair anymore\n            }\n        }","sourceCodeStart":403,"sourceCodeEnd":439,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/modules/ingest-common/src/main/java/org/elasticsearch/ingest/common/CefParser.java#L403-L439","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Inspect the raw CEF extension block — confirm it starts with a bare key (no spaces) followed immediately by '='.","Strip any leading prose or whitespace-only prefix before invoking the cef processor.","Use an on_failure pipeline to quarantine malformed events.","If the producer is yours, emit only 'key=value' pairs in the extension section per the CEF spec."],"exampleFix":"// before — leading text before the first '=' reads as a whitespace-containing key\n//   field: 'CEF:0|v|p|1.0|1|n|3|some free text act=login next=...'\n//\n// after — extension section begins with a clean key=value pair\n//   field: 'CEF:0|v|p|1.0|1|n|3|act=login next=...'","handlingStrategy":"validation","validationCode":"// The first extension key must be non-empty and contain no whitespace.\nboolean firstKeyLooksValid(String ext) {\n    if (ext == null) return true;\n    int eq = ext.indexOf('=');\n    if (eq < 0) return false;\n    String key = ext.substring(0, eq);\n    return !key.isEmpty() && key.chars().noneMatch(Character::isWhitespace);\n}","typeGuard":null,"tryCatchPattern":"{\n  \"on_failure\": [\n    { \"set\": { \"field\": \"ingest.error\", \"value\": \"cef-bad-first-key\" } },\n    { \"redirect\": { \"pipeline\": \"quarantine\" } }\n  ]\n}","preventionTips":["Inspect the segment immediately before the first '=' — it must be a bare key with no spaces.","Trim leading prose from CEF extension sections upstream.","Use on_failure to capture the offending value for producer-side fixes."],"tags":["ingest","cef","malformed-input","parsing"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}