CVE-2026-39361 Overview
OpenObserve, a cloud-native observability platform, contains a Server-Side Request Forgery (SSRF) vulnerability in versions 0.70.3 and earlier. The validate_enrichment_url function in src/handler/http/request/enrichment_table/mod.rs fails to properly block IPv6 addresses because Rust's url crate returns them with surrounding brackets (e.g., [::1] instead of ::1). This parsing inconsistency allows authenticated attackers to bypass URL validation and access internal services that should be blocked from external access.
Critical Impact
An authenticated attacker can exploit this SSRF vulnerability to reach internal services, retrieve cloud provider IAM credentials via metadata services (AWS IMDSv1, GCP metadata, or Azure IMDS), and probe internal network infrastructure.
Affected Products
- OpenObserve version 0.70.3 and earlier
- OpenObserve cloud deployments with access to cloud provider metadata services
- OpenObserve self-hosted deployments with internal network services
Discovery Timeline
- 2026-04-07 - CVE CVE-2026-39361 published to NVD
- 2026-04-09 - Last updated in NVD database
Technical Details for CVE-2026-39361
Vulnerability Analysis
This vulnerability falls under CWE-918 (Server-Side Request Forgery). The core issue stems from a parsing inconsistency in how Rust's url crate handles IPv6 addresses. When an IPv6 address is extracted from a URL, the crate returns it with surrounding square brackets (e.g., [::1]), but the validation logic performs string comparisons against unbracketed values like ::1 or localhost. This mismatch creates a bypass condition where IPv6 loopback and private addresses pass through the security filter undetected.
On cloud deployments, this SSRF vulnerability enables attackers to query cloud provider metadata endpoints such as AWS IMDSv1 at 169.254.169.254, GCP metadata services, or Azure IMDS, potentially exposing IAM credentials and sensitive instance metadata. On self-hosted deployments, attackers can leverage this vulnerability to probe internal network services that are not meant to be externally accessible.
Root Cause
The root cause lies in the validate_enrichment_url function's failure to normalize IPv6 address formats before comparison. When checking if a host matches blocked addresses like ::1 (IPv6 loopback), the code compares against the raw host string without stripping the bracket notation that Rust's url parsing library adds to IPv6 addresses. This creates a classic input normalization bypass where [::1] does not match the string ::1, allowing the malicious request to proceed.
Attack Vector
An authenticated attacker can craft enrichment table URLs containing IPv6 addresses in bracket notation to bypass the localhost and private IP range validation. By targeting cloud metadata endpoints using IPv6-mapped addresses or directly accessing internal services via IPv6, attackers can exfiltrate credentials and sensitive data from otherwise protected resources.
// Security patch in src/handler/http/request/enrichment_table/mod.rs
// Source: https://github.com/openobserve/openobserve/commit/d1a5d8f65b432e2e82f83231390dec7f107e8d75
.ok_or_else(|| "URL must have a valid host".to_string())?;
// Block localhost
+ let host = host.trim_start_matches('[').trim_end_matches(']');
if host == "localhost" || host == "127.0.0.1" || host == "::1" {
return Err("Cannot access localhost URLs".to_string());
}
// Block private IP ranges
if let Ok(ip) = host.parse::<std::net::IpAddr>() {
- match ip {
- std::net::IpAddr::V4(v4) => {
- let octets = v4.octets();
- // RFC1918 private ranges: 10.x.x.x, 172.16-31.x.x, 192.168.x.x
- // AWS metadata: 169.254.169.254
- if octets[0] == 10
- || (octets[0] == 172 && (16..=31).contains(&octets[1]))
- || (octets[0] == 192 && octets[1] == 168)
- || (octets[0] == 169 && octets[1] == 254)
- {
- return Err("Cannot access private IP addresses".to_string());
- }
- }
- std::net::IpAddr::V6(v6) => {
- // Block IPv6 localhost and private ranges
- if v6.is_loopback() || v6.segments()[0] & 0xfe00 == 0xfc00 {
- return Err("Cannot access private IP addresses".to_string());
+ let v4 = match ip {
+ std::net::IpAddr::V4(v4) => Some(v4),
+ std::net::IpAddr::V6(v6) => match v6.to_ipv4_mapped() {
Source: GitHub Commit Update
Detection Methods for CVE-2026-39361
Indicators of Compromise
- HTTP requests to enrichment table endpoints containing IPv6 addresses in bracket notation (e.g., [::1], [::ffff:169.254.169.254])
- Outbound connections from OpenObserve instances to cloud metadata endpoints (169.254.169.254, metadata.google.internal, 169.254.169.254/metadata/instance)
- Unexpected access to internal network services from the OpenObserve application
- Authentication logs showing users accessing enrichment table functionality with suspicious URL parameters
Detection Strategies
- Implement network monitoring to detect connections from OpenObserve to cloud metadata service IPs and internal network ranges
- Configure web application firewall (WAF) rules to inspect and block requests containing IPv6 loopback or private addresses in URL parameters
- Enable detailed logging on enrichment table API endpoints and monitor for unusual URL patterns
- Deploy egress filtering to prevent OpenObserve from initiating connections to internal services or metadata endpoints
Monitoring Recommendations
- Set up alerts for any outbound traffic from OpenObserve instances to link-local addresses (169.254.x.x) or IPv6 private ranges
- Monitor cloud provider audit logs (AWS CloudTrail, GCP Cloud Audit Logs, Azure Activity Log) for metadata service access from application instances
- Review OpenObserve application logs for enrichment table URL validation errors that may indicate exploitation attempts
- Implement real-time monitoring of network flows from OpenObserve containers or hosts to detect lateral movement attempts
How to Mitigate CVE-2026-39361
Immediate Actions Required
- Upgrade OpenObserve to a version newer than 0.70.3 that includes the security patch
- Review and audit recent enrichment table URL submissions for signs of exploitation
- For cloud deployments, migrate from IMDSv1 to IMDSv2 (AWS) to require session tokens for metadata access
- Implement network-level restrictions to prevent OpenObserve from accessing cloud metadata endpoints
Patch Information
The vulnerability has been addressed in commit d1a5d8f65b432e2e82f83231390dec7f107e8d75. The fix normalizes IPv6 address handling by stripping bracket notation before performing validation comparisons. Additionally, the patch improves IPv6 private address detection by converting IPv6-mapped IPv4 addresses to their IPv4 equivalents for proper range checking.
For detailed patch information, see the GitHub Security Advisory GHSA-gcwf-3p7h-wm79 and the associated commit.
Workarounds
- If immediate patching is not possible, implement a reverse proxy or WAF rule to filter enrichment table requests containing IPv6 addresses
- Configure cloud provider instance metadata service to require IMDSv2 hop limits or disable IMDSv1 entirely
- Deploy network segmentation to isolate OpenObserve instances from internal services and cloud metadata endpoints
- Restrict enrichment table functionality to trusted administrators only until the patch can be applied
# Configuration example - AWS IMDSv2 enforcement via instance metadata options
aws ec2 modify-instance-metadata-options \
--instance-id <your-instance-id> \
--http-tokens required \
--http-put-response-hop-limit 1 \
--http-endpoint enabled
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


