| name | apache-druid-javascript-rce-vulnerability-analysis |
| description | Understanding the CVE in Apache Druid 0.20.0 where authenticated attackers can execute arbitrary code via JavaScript payloads. The vulnerability exploits @JacksonInject with empty key "" to override JavaScriptConfig and enable JavaScript execution even when disabled. Use this skill to understand the attack vector and plan the fix. |
Vulnerability Overview
Apache Druid 0.20.0 has a Remote Code Execution (RCE) vulnerability through JavaScript filters, transforms, and other JavaScript-enabled features.
Attack Vector
The exploit sends JSON payloads with a "" (empty string) key that maps to the JavaScriptConfig parameter in filter/aggregator constructors. Because Jackson's @JacksonInject annotation defaults to allowing input values to override injected values, an attacker can supply a JavaScriptConfig with enabled: true, bypassing the server's security configuration.
Affected Components
JavaScript-enabled features in Druid that accept JavaScriptConfig via @JacksonInject:
- JavaScriptFilter —
processing/src/main/java/org/apache/druid/query/filter/JavaScriptDimFilter.java
- JavaScriptAggregatorFactory —
processing/src/main/java/org/apache/druid/query/aggregation/JavaScriptAggregatorFactory.java
- JavaScriptExtractionFn —
processing/src/main/java/org/apache/druid/query/extraction/JavaScriptExtractionFn.java
- JavaScriptParseSpec —
processing/src/main/java/org/apache/druid/data/input/impl/JavaScriptParseSpec.java
- JavaScriptPostAggregator —
processing/src/main/java/org/apache/druid/query/aggregation/post/JavaScriptPostAggregator.java
Root Cause
The @JacksonInject annotation without useInput = OptBoolean.FALSE allows deserialized JSON input to override the server-side injected JavaScriptConfig. The empty key "" in JSON is used because @JacksonInject without a value attribute uses empty string as the injection key.
Fix Strategy
Change all @JacksonInject annotations on JavaScriptConfig parameters to include useInput = OptBoolean.FALSE, which tells Jackson to never use input JSON to fill this parameter — only the injected server-side value will be used.