Originally reported by @ekilmer
A2A extension is in alpha state and can be fixed in the open
A2A: REJECT mode accepts arbitrary bodyless GET paths
Brief description
The alpha envoy.filters.http.a2a filter treats every bodyless downstream GET request as valid A2A discovery traffic. When configured with traffic_mode: REJECT, non-discovery paths such as /internal/admin can be forwarded instead of receiving the local 400 response intended for non-A2A traffic.
The A2A filter is alpha-tagged.
CVSS
CVSS v3.1: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
Score: 3.7
Rating: LOW
Scoped severity from the report: Low.
Impact
A downstream client can send a bodyless GET request to an arbitrary path and have it accepted as A2A traffic by the filter in REJECT mode. Practical impact depends on an A2A-only gateway sharing the same listener, route, or virtual host with sensitive non-A2A GET endpoints.
No crash is involved.
You are impacted if
You may be impacted if all of the following are true:
- You configure alpha
envoy.filters.http.a2a.
- The A2A filter uses
traffic_mode: REJECT.
- The same listener, route, or virtual host can reach non-A2A
GET endpoints that should be rejected by the A2A filter.
- Downstream clients can send requests to those endpoints.
Affected component(s)
- Alpha component:
envoy.filters.http.a2a
source/extensions/filters/http/a2a/a2a_filter.cc
api/envoy/extensions/filters/http/a2a/v3/a2a.proto
Attack vector(s)
A remote downstream client sends a bodyless GET request to a non-discovery path on an Envoy deployment with the A2A filter in REJECT mode.
GET /internal/admin HTTP/1.1
Host: gateway.example
Discover(s)/Credits
Eric Kilmer and Benjamin Samuels of Trail of Bits in collaboration with OpenAI.
Example exploit or proof-of-concept
Configuration condition:
name: envoy.filters.http.a2a
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.a2a.v3.A2a
traffic_mode: REJECT
Details
source/extensions/filters/http/a2a/a2a_filter.cc:34-35 returns true for every GET. decodeHeaders() then marks a bodyless GET as A2A and returns Continue at source/extensions/filters/http/a2a/a2a_filter.cc:68-71, before the REJECT mode non-A2A check at source/extensions/filters/http/a2a/a2a_filter.cc:91-96.
This conflicts with the API documentation in api/envoy/extensions/filters/http/a2a/v3/a2a.proto, which describes REJECT mode as rejecting requests that are not following A2A.
Mitigations / Workarounds
Potential mitigations include isolating A2A routes from sensitive non-A2A GET endpoints, avoiding REJECT mode as the only guard on shared routes, or applying the patch when available in the relevant branch or release.
Detection
Review configurations for envoy.filters.http.a2a with traffic_mode: REJECT, especially where A2A traffic shares a listener, route, or virtual host with sensitive GET endpoints.
Originally reported by @ekilmer
A2A extension is in alpha state and can be fixed in the open
A2A: REJECT mode accepts arbitrary bodyless GET paths
Brief description
The alpha
envoy.filters.http.a2afilter treats every bodyless downstreamGETrequest as valid A2A discovery traffic. When configured withtraffic_mode: REJECT, non-discovery paths such as/internal/admincan be forwarded instead of receiving the local400response intended for non-A2A traffic.The A2A filter is alpha-tagged.
CVSS
CVSS v3.1:
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:NScore:
3.7Rating: LOW
Scoped severity from the report: Low.
Impact
A downstream client can send a bodyless
GETrequest to an arbitrary path and have it accepted as A2A traffic by the filter inREJECTmode. Practical impact depends on an A2A-only gateway sharing the same listener, route, or virtual host with sensitive non-A2AGETendpoints.No crash is involved.
You are impacted if
You may be impacted if all of the following are true:
envoy.filters.http.a2a.traffic_mode: REJECT.GETendpoints that should be rejected by the A2A filter.Affected component(s)
envoy.filters.http.a2asource/extensions/filters/http/a2a/a2a_filter.ccapi/envoy/extensions/filters/http/a2a/v3/a2a.protoAttack vector(s)
A remote downstream client sends a bodyless
GETrequest to a non-discovery path on an Envoy deployment with the A2A filter inREJECTmode.Discover(s)/Credits
Eric Kilmer and Benjamin Samuels of Trail of Bits in collaboration with OpenAI.
Example exploit or proof-of-concept
Configuration condition:
Details
source/extensions/filters/http/a2a/a2a_filter.cc:34-35returns true for everyGET.decodeHeaders()then marks a bodylessGETas A2A and returnsContinueatsource/extensions/filters/http/a2a/a2a_filter.cc:68-71, before theREJECTmode non-A2A check atsource/extensions/filters/http/a2a/a2a_filter.cc:91-96.This conflicts with the API documentation in
api/envoy/extensions/filters/http/a2a/v3/a2a.proto, which describesREJECTmode as rejecting requests that are not following A2A.Mitigations / Workarounds
Potential mitigations include isolating A2A routes from sensitive non-A2A
GETendpoints, avoidingREJECTmode as the only guard on shared routes, or applying the patch when available in the relevant branch or release.Detection
Review configurations for
envoy.filters.http.a2awithtraffic_mode: REJECT, especially where A2A traffic shares a listener, route, or virtual host with sensitiveGETendpoints.