ext_authz headers_to_add Omitted from Route Cache Clearing
Affected commit: c33d01624d
Sink: source/extensions/filters/http/ext_authz/ext_authz.cc:713
Summary
When HTTP ext_authz returns headers_to_add that affect routing, the clear_route_cache condition at line 713-716 checks headers_to_set, headers_to_append, headers_to_remove, query_parameters_to_set, and query_parameters_to_remove — but not headers_to_add (used at line 751). The request retains its original permissive route despite the ext_authz service intending a route change via the added header.
Detail
// source/extensions/filters/http/ext_authz/ext_authz.cc:713-716
if (config_->clearRouteCache() &&
(!response->headers_to_set.empty() || !response->headers_to_append.empty() ||
!response->headers_to_remove.empty() || !response->query_parameters_to_set.empty() ||
!response->query_parameters_to_remove.empty())) {
// clears route cache
}
// Line 751: headers_to_add is processed separately, but not checked above
for (const auto& [key, value] : response->headers_to_add) { ... }
The ext_authz service may add a routing-relevant header (e.g., x-route-to: restricted) via headers_to_add, expecting Envoy to re-evaluate the route. Since the route cache is not cleared, the request continues on its original (permissive) route.
Reproduce
#!/bin/bash
set -e
git clone --depth 1 https://github.com/envoyproxy/envoy.git /tmp/envoy-extauthz
cd /tmp/envoy-extauthz
echo "HEAD: $(git rev-parse HEAD)"
# Show the route-cache clearing condition that omits headers_to_add
sed -n '710,720p' source/extensions/filters/http/ext_authz/ext_authz.cc
# Show that headers_to_add is processed later, after the clearing check
grep -n 'headers_to_add' source/extensions/filters/http/ext_authz/ext_authz.cc | head -5
echo ""
echo "=== Vulnerable code confirmed at HEAD ==="
echo "Line 713-716: clearRouteCache condition checks:"
echo " headers_to_set, headers_to_append, headers_to_remove,"
echo " query_parameters_to_set, query_parameters_to_remove"
echo "Line 751: headers_to_add is processed AFTER the condition check."
echo ""
echo "When ext_authz returns headers via headers_to_add (not headers_to_set),"
echo "the route cache is not cleared even with clear_route_cache: true."
echo "If the added header affects routing, the request retains its original"
echo "(potentially more permissive) route."
rm -rf /tmp/envoy-extauthz
Observed output (verified at c33d01624d):
HEAD: c33d01624d5b173b5d6e5c0c0474d480cab69b7b
// Any changes to request headers or query parameters can affect how the request is going to be
// routed. If we are changing the headers we also need to clear the route
// cache.
if (config_->clearRouteCache() &&
(!response->headers_to_set.empty() || !response->headers_to_append.empty() ||
!response->headers_to_remove.empty() || !response->query_parameters_to_set.empty() ||
!response->query_parameters_to_remove.empty())) {
ENVOY_STREAM_LOG(debug, "ext_authz is clearing route cache", *decoder_callbacks_);
decoder_callbacks_->downstreamCallbacks()->clearRouteCache();
}
source/extensions/filters/http/ext_authz/ext_authz.cc:751: for (const auto& [key, value] : response->headers_to_add) {
source/extensions/filters/http/ext_authz/ext_authz.cc:872: if (!response->response_headers_to_add.empty()) {
=== Vulnerable code confirmed at HEAD ===
Line 713-716: clearRouteCache condition checks:
headers_to_set, headers_to_append, headers_to_remove,
query_parameters_to_set, query_parameters_to_remove
Line 751: headers_to_add is processed AFTER the condition check.
When ext_authz returns headers via headers_to_add (not headers_to_set),
the route cache is not cleared even with clear_route_cache: true.
If the added header affects routing, the request retains its original
(potentially more permissive) route.
Credit
Zheng Yu @ Depthfirst