CVE-2026-77066 Overview
CVE-2026-77066 is a Server-Side Request Forgery (SSRF) vulnerability [CWE-918] in Omnivore, an open-source read-later application. The flaw exists in the scanFeedsResolver function within packages/api/src/resolvers/subscriptions/index.ts. The resolver forwards a caller-supplied URL directly to axios.get(url, rssParserConfig()) without any address validation. An authenticated attacker can direct the server to issue HTTP requests to arbitrary internal endpoints and receive parsed feed metadata in response.
Critical Impact
Authenticated users can probe internal network services and extract feed-shaped metadata from reachable endpoints, enabling internal reconnaissance and limited information disclosure.
Affected Products
- Omnivore API service (packages/api)
- Omnivore self-hosted deployments prior to commit c4d7d85
- Omnivore GraphQL scanFeeds query interface
Discovery Timeline
- 2026-08-20 - CVE-2026-77066 published to NVD
- 2026-08-20 - Last updated in NVD database
Technical Details for CVE-2026-77066
Vulnerability Analysis
The scanFeedsResolver accepts a URL from an authenticated GraphQL client and passes it directly into axios.get() without host validation. The same source file already implements validateUrl() on the subscribe path, and createPageSaveRequest applies an equivalent check using the private-ip library. That library rejects private and reserved IP ranges. The omission is specific to this resolver, making the flaw a localized defense-in-depth failure rather than a systemic input handling issue.
Root Cause
The root cause is missing URL validation before an outbound HTTP request. The resolver trusts the url argument supplied by the GraphQL caller. Because the server issues the request, requests originate from the API host and can reach loopback addresses, link-local ranges, cloud metadata services, and internal RFC1918 networks that are otherwise unreachable from the internet.
Attack Vector
An authenticated user submits a scanFeeds GraphQL query with a URL targeting internal infrastructure. The resolver parses the response as an RSS or Atom feed, or as HTML, and returns url, title, description, and type fields to the caller. Disclosure is limited to feed-shaped metadata and to <link> elements advertising feeds. Responses that fail to parse still leak reachability information through error differentiation, allowing internal port scanning.
}
}
+ // Ensure that we are not running a http request against local/private IPs.
+ try {
+ validateUrl(url)
+ } catch (e) {
+ return {
+ errorCodes: [ScanFeedsErrorCode.BadRequest],
+ }
+ }
+
try {
- // fetch page content and parse feeds
const response = await axios.get(url, rssParserConfig())
const content = response.data as string
// check if the content is html or xml
Source: Omnivore security patch commit c4d7d85
Detection Methods for CVE-2026-77066
Indicators of Compromise
- Outbound HTTP requests from the Omnivore API pod or host targeting RFC1918 ranges, 127.0.0.0/8, or 169.254.169.254
- GraphQL query logs containing scanFeeds operations with URLs referencing internal hostnames or IP literals
- Repeated scanFeeds requests from a single authenticated user against varying internal ports
- Application logs showing axios connection errors correlated with non-public destination addresses
Detection Strategies
- Inspect API access logs for GraphQL mutations and queries named scanFeeds and correlate the url parameter against an allowlist of external hosts
- Monitor egress traffic from the Omnivore API service using flow logs or eBPF-based network telemetry
- Alert on outbound HTTP requests from application service accounts to cloud metadata endpoints such as 169.254.169.254
Monitoring Recommendations
- Ingest Omnivore API access logs and egress network flows into a centralized data lake for correlation across identity and network telemetry
- Baseline the destinations that the Omnivore API normally contacts and alert on deviations toward internal subnets
- Track error-response patterns in scanFeeds responses to identify systematic internal port enumeration
How to Mitigate CVE-2026-77066
Immediate Actions Required
- Apply upstream commit c4d7d8562e6b9aabb1d8e4dabca268e314baa43a which adds validateUrl() to the scanFeedsResolver and to the webhooksResolver
- Restrict egress from the Omnivore API service to only the destinations required for feed retrieval
- Block API-tier access to cloud instance metadata services using IMDSv2 hop-limit enforcement or network policy
- Review authentication logs for suspicious scanFeeds GraphQL activity from newly registered accounts
Patch Information
The fix is delivered in commit c4d7d8562e6b9aabb1d8e4dabca268e314baa43a in the Omnivore repository. The patch adds a call to validateUrl(url) in packages/api/src/resolvers/subscriptions/index.ts before invoking axios.get(), and imports the same validateUrl function into packages/api/src/resolvers/webhooks/index.ts. The validation relies on the private-ip library to reject private and reserved address ranges. Details are available in the Vulncheck advisory and the Omnivore issue tracker.
Workarounds
- Place the Omnivore API behind an egress proxy that enforces an allowlist of external feed hosts
- Deploy Kubernetes NetworkPolicy or host firewall rules that deny outbound connections from the API service to RFC1918 and link-local ranges
- Disable the scanFeeds GraphQL operation at the gateway if the feature is not required
# Kubernetes NetworkPolicy example blocking API egress to internal ranges
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: omnivore-api-egress
spec:
podSelector:
matchLabels:
app: omnivore-api
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
- 169.254.0.0/16
- 127.0.0.0/8
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

