CVE-2026-73546 Overview
Envoy is an open source edge and service proxy widely deployed in cloud-native architectures. A stored Cross-Site Scripting (XSS) vulnerability [CWE-79] affects Envoy versions prior to 1.36.10, 1.37.6, 1.38.4, and 1.39.1. The /stats?format=html admin endpoint renders statistic names without HTML encoding. Data-plane components such as grpc_stats with stats_for_all_methods enabled can persist attacker-controlled path segments into cached dynamic statistic names. When an operator loads the HTML stats page, the stored payload executes in the admin interface origin and can issue same-origin privileged requests.
Critical Impact
Stored XSS in the Envoy admin interface enables attacker script execution with operator privileges, exposing sensitive proxy controls to hijack.
Affected Products
- Envoy versions prior to 1.36.10
- Envoy versions prior to 1.37.6
- Envoy versions prior to 1.38.4 and 1.39.1
Discovery Timeline
- 2026-09-21 - CVE-2026-73546 published to NVD
- 2026-09-23 - Last updated in NVD database
Technical Details for CVE-2026-73546
Vulnerability Analysis
The flaw resides in StatsHtmlRender, the component that produces HTML output for the /stats?format=html admin endpoint. The renderer sanitizes statistic string values but emits statistic names verbatim. Any data-plane feature that incorporates request-derived text into dynamically generated statistic names becomes an injection sink.
The grpc_stats filter with stats_for_all_methods enabled is a confirmed sink. It creates per-method counters where the method name is embedded in the stat name. An attacker can craft gRPC path segments containing HTML control characters such as <, >, ", ', and &. Envoy caches these stat names, so the payload remains resident until the process restarts. Exploitation completes when an operator visits the admin HTML stats page in a browser.
Root Cause
Envoy trusted statistic names as internally generated identifiers and skipped HTML escaping on output. That assumption breaks when data-plane filters propagate untrusted client input into stat names, producing a classic stored XSS chain.
Attack Vector
The attacker sends crafted requests (for example, gRPC calls with malicious method paths) through the proxy. Envoy stores the resulting stat name. When an operator with browser access to the admin interface loads /stats?format=html, the injected script runs under the admin origin and can invoke privileged admin endpoints such as /quitquitquit, /runtime_modify, or /logging.
/**
* Checks if the text contains any characters that require HTML sanitization.
* @param text the text to check.
* @return true if the text contains HTML special characters (&, <, >, ", or '), false otherwise.
*/
static inline bool requiresSanitization(absl::string_view text) {
return text.find_first_of("&<>\"'") != absl::string_view::npos;
}
Source: Envoy Commit 11d34660 — the patch adds requiresSanitization and applies HTML escaping to stat names before rendering, guarded by envoy.reloadable_features.sanitize_html_stats_names.
Detection Methods for CVE-2026-73546
Indicators of Compromise
- gRPC request paths or HTTP routes containing HTML special characters (<, >, ", ', &) targeting an Envoy-fronted service.
- Stat names in /stats?format=json output that contain angle brackets, quotes, or script substrings.
- Unexpected privileged admin actions (runtime overrides, listener drains, hot restarts) originating from operator browser sessions.
Detection Strategies
- Query /stats?format=json and scan returned keys with a regex matching HTML metacharacters to surface poisoned entries.
- Correlate anomalous gRPC method names in access logs with subsequent admin endpoint activity from operator IPs.
- Alert on any external network exposure of the Envoy admin listener, which should never be browser-reachable from untrusted networks.
Monitoring Recommendations
- Ingest Envoy access logs and admin access logs into a centralized analytics platform for retrospective hunting.
- Baseline the set of expected grpc.<service>.<method> stat names and alert on new entries containing non-alphanumeric symbols.
- Monitor Envoy version telemetry across the fleet to detect hosts running affected releases.
How to Mitigate CVE-2026-73546
Immediate Actions Required
- Upgrade Envoy to 1.36.10, 1.37.6, 1.38.4, or 1.39.1 or later.
- Restrict the admin interface to loopback or a management-only network segment; never expose it to browsers on untrusted networks.
- Disable stats_for_all_methods on the grpc_stats filter unless explicitly required, and prefer an allowlist of known methods.
Patch Information
Envoy released fixes in v1.36.10, v1.37.6, v1.38.4, and v1.39.1. The fix is described in the Envoy Security Advisory GHSA-pv9h-4fxf-7vrg and implemented across commits 11d34660, 884d30c5, 9484e17c, and ab63a0e5. The behavior is gated by the runtime flag envoy.reloadable_features.sanitize_html_stats_names.
Workarounds
- Prefer /stats?format=json or /stats?format=text and avoid loading the HTML variant in a browser until patched.
- Bind the admin listener to 127.0.0.1 and access it only through authenticated jump hosts or kubectl port-forward.
- Disable dynamic-name stat producers such as grpc_stats with stats_for_all_methods: true until the upgrade is deployed.
# Verify the runtime guard is active after upgrade
curl -s http://127.0.0.1:9901/runtime | \
grep sanitize_html_stats_names
# Restrict admin listener to loopback in envoy.yaml
# admin:
# address:
# socket_address:
# address: 127.0.0.1
# port_value: 9901
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

