All advisories
Draft

ext_authz headers_to_add Omitted from Route Cache Clearing

envoyproxy/envoy

Affected packages

envoy other
Affected versions= c33d01624d5b173b5d6e5c0c0474d480cab69b7b
Patched versionsNot specified

Description

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