FrankChen021 commented on code in PR #19572:
URL: https://github.com/apache/druid/pull/19572#discussion_r3388206173


##########
server/src/main/java/org/apache/druid/server/QueryLifecycle.java:
##########
@@ -227,6 +238,28 @@ public void initialize(final Query<?> baseQuery)
     Map<String, Object> finalContext = 
QueryContexts.override(contextWithDefaults, baseQuery.getContext());
     finalContext.put(BaseQuery.QUERY_ID, queryId);
 
+    // Anti-spoof + propagation. Strip user-supplied values for all reserved 
keys, then
+    // inject filter-captured values for headers actually present on this 
request. Reserved
+    // keys can ONLY originate from a filter-captured header — which means 
either a real
+    // client request (entry point) or an inter-Druid RPC where the upstream 
Druid node
+    // attached the header onto the wire (see 
DirectDruidClient.applyToOutboundRequest).
+    // Without the strip, a malicious client could supply 
{"context":{"traceId":"forged"}}
+    // in the query JSON body and have it survive into OpenLineage / Atlas / 
audit.
+    //
+    // Trade-off: if an intermediate L7 proxy strips the custom X- header 
between two
+    // Druid nodes, the propagated value is lost on the receiving node (no 
fallback to
+    // the body-context value, which was just stripped). Druid's internal RPCs 
are
+    // expected to be direct (broker→historical etc.) rather than mediated by a
+    // header-rewriting proxy. Operators running a mesh that strips custom X-* 
headers
+    // should add the configured headers to their mesh's allow-list.
+    for (String reservedKey : 
requestHeaderContextConfig.getHeaderToContextKey().values()) {
+      finalContext.remove(reservedKey);
+    }
+    final Map<String, String> captured = RequestHeaderContext.current();
+    if (!captured.isEmpty()) {
+      finalContext.putAll(captured);

Review Comment:
   P2 Header-mapped context bypasses context authorization
   
   Captured request headers are merged into the final query context here, but 
these keys were not included in the user context keys that 
AuthConfig.contextKeysToAuthorize checks. Since RequestHeaderContextConfig only 
rejects queryId/subQueryId/sqlQueryId, an operator can map a client-controlled 
header to existing operational context keys such as priority, lane, or cache 
flags; clients can then set those values via headers without the QUERY_CONTEXT 
WRITE authorization required for the same keys in the query body. Please either 
reject mappings to existing Druid query-context keys or include captured header 
target keys in context authorization unless they come from a trusted internal 
source.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to