CVE-2026-50197
Skipper Ingress vulnerability analysis and mitigation

Overview

CVE-2026-50197 is an OPA policy bypass vulnerability in Zalando Skipper, an HTTP router and reverse proxy, affecting all versions prior to 0.26.10. The flaw causes the opaAuthorizeRequestWithBody filter to silently skip request-body inspection for HTTP/1.1 Transfer-Encoding: chunked and HTTP/2 requests that omit the content-length pseudo-header, allowing attackers to bypass body-content authorization policies entirely. It was reported by researcher tonghuaroot, disclosed via GitHub Security Advisory GHSA-659f-rgp5-w4wf on June 1, 2026, and published to the GitHub Advisory Database on July 8, 2026. The vulnerability carries a CVSS v3.1 score of 8.7 (High) (Github Advisory).

Technical details

The root cause is classified as CWE-444 (Inconsistent Interpretation of HTTP Requests / HTTP Request Smuggling). In filters/openpolicyagent/openpolicyagent.go, the ExtractHttpBodyOptionally function gates body buffering on req.ContentLength <= maxBodyBytes. When Go's net/http sets req.ContentLength = -1 for chunked HTTP/1.1 or HTTP/2 requests without an explicit content-length, the gate passes (-1 <= positiveLimit), but the subsequent fillBuffer(-1) call immediately short-circuits because its loop condition len(buf) < expectedSize(-1) evaluates to 0 < -1 (false), leaving the buffer empty. OPA then evaluates an empty input.parsed_body, causing deny rules that key on body fields to fail open (default allow), while the full attacker-controlled body is forwarded to the upstream service. A complete proof-of-concept Go test (poc_test.go) was included in the advisory and committed to the repository, demonstrating the bypass with a Transfer-Encoding: chunked request carrying {"admin":true} that should be denied but reaches the upstream with HTTP 200 (Github Advisory, Fix PR).

Impact

Operators who deploy Skipper in front of private upstream services and rely on opaAuthorizeRequestWithBody for body-content authorization are silently downgraded to header/path-only enforcement for any client using chunked or HTTP/2 framing. Concrete affected patterns include field allow/deny lists for multi-tenant APIs, content-moderation filters, deprecated-API payload schema gates, and generic body-based injection validators — in every case, the forbidden payload reaches the upstream uninspected. The OPA decision log records the request as ALLOWED with raw_body length 0, providing no distinguishing signal from a legitimately empty body, which severely hampers post-hoc forensic detection and creates a confusing allow/observed asymmetry between OPA logs and upstream access logs (Github Advisory).

Exploitability

A working proof-of-concept is publicly available as part of the security advisory and was committed directly into the Skipper repository as poc_GHSA-659f-rgp5-w4wf_test.go (Fix PR). The NVD SSVC assessment classifies exploitation as "poc" and the vulnerability as "automatable" (Feedly). No authentication is required — any unauthenticated network client with access to the Skipper proxy listener can exploit this by simply omitting the Content-Length header and using chunked transfer encoding. The EPSS score is approximately 0.43–0.55%, and there is no current listing in the CISA KEV catalog. No specific threat actor attribution or confirmed in-the-wild exploitation has been reported.

Exploitation steps

  1. Identify target: Locate a Skipper proxy instance (version <= 0.26.9) configured with the opaAuthorizeRequestWithBody filter and a Rego policy that enforces body-content restrictions (e.g., denying requests where input.parsed_body.admin == true).
  2. Craft bypass request: Construct an HTTP/1.1 POST request to the protected endpoint, omitting the Content-Length header and instead using Transfer-Encoding: chunked. This causes Go's net/http to set req.ContentLength = -1 on the server side.
  3. Send chunked payload: Transmit the forbidden body content (e.g., {"admin":true}) using chunked encoding wire format over a raw TCP connection to precisely control framing:
    POST /priv HTTP/1.1\r\n
    Host: <target>\r\n
    Content-Type: application/json\r\n
    Transfer-Encoding: chunked\r\n
    \r\n
    e\r\n
    {"admin":true}\r\n
    0\r\n
    \r\n
  4. OPA evaluates empty body: Skipper's ExtractHttpBodyOptionally wraps the body but fillBuffer(-1) immediately exits with an empty buffer. OPA receives raw_body = [] and input.parsed_body = {}, causing the deny rule to evaluate as undefined and fall through to the default allow.
  5. Upstream receives full payload: Skipper returns HTTP 200 and forwards the complete {"admin":true} body to the upstream service, which the OPA policy was specifically configured to block (Github Advisory).

Indicators of compromise

  • Logs (OPA Decision Log): Requests recorded as ALLOWED with raw_body length 0 for POST/PUT requests that carry a non-empty body — particularly suspicious when the upstream access log shows a non-empty body for the same request. This asymmetry (OPA: empty body allowed; upstream: full body received) is the primary forensic signal.
  • Logs (Upstream Access Log): Requests reaching the upstream service with body content that should have been blocked by OPA policy (e.g., fields like admin=true, privileged role identifiers, or schema-forbidden fields), especially when the corresponding OPA decision log shows an allow with zero body bytes.
  • Network: HTTP/1.1 POST/PUT requests to OPA-protected endpoints using Transfer-Encoding: chunked without a Content-Length header; HTTP/2 requests to the same endpoints without a content-length pseudo-header carrying non-trivial bodies.
  • Process/Application: Unexpected behavior in upstream services consistent with receiving payloads that should have been denied (e.g., privilege escalation actions, forbidden content submissions, deprecated API calls) without corresponding OPA deny decisions (Github Advisory).

Mitigation and workarounds

Upgrade Zalando Skipper to version v0.26.10 or later, which contains the fix merged via PR #4041 on June 1, 2026 (Skipper Release). The fix modifies ExtractHttpBodyOptionally in filters/openpolicyagent/openpolicyagent.go to treat req.ContentLength == -1 as maxBodyBytes rather than a negative sentinel, ensuring fillBuffer reads chunked and HTTP/2 bodies up to the configured cap before OPA evaluation. No configuration-based workaround is available for unpatched versions — the bypass affects all deployments using opaAuthorizeRequestWithBody with body-content policies. As an interim measure, operators may consider placing an additional WAF or reverse proxy in front of Skipper that normalizes chunked requests to include a Content-Length header, though upgrading is strongly preferred (Fix Commit).

Community reactions

The vulnerability was reported by security researcher tonghuaroot and promptly addressed by the Skipper maintainers (szuecs), with the fix merged the same day it was filed (June 1, 2026) (Fix PR). The advisory includes a detailed root cause analysis and a complete, runnable proof-of-concept test, reflecting a high-quality coordinated disclosure. The fix was rapidly propagated into Zalando's internal Kubernetes-on-AWS infrastructure, with multiple downstream update PRs merged the same day. No significant broader media coverage or social media discussion beyond the GitHub advisory ecosystem has been identified.

Additional resources


SourceThis report was generated using AI

Related Skipper Ingress vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

CVE-2022-38580CRITICAL9.8
  • Skipper Ingress logoSkipper Ingress
  • github.com/zalando/skipper
NoYesOct 25, 2022
CVE-2026-65604HIGH8.8
  • Skipper Ingress logoSkipper Ingress
  • cpe:2.3:a:zalando:skipper
NoYesJul 23, 2026
CVE-2026-23742HIGH8.8
  • Skipper Ingress logoSkipper Ingress
  • github.com/zalando/skipper
NoYesJan 16, 2026
CVE-2026-24470HIGH8.1
  • Skipper Ingress logoSkipper Ingress
  • github.com/zalando/skipper
NoYesJan 26, 2026
CVE-2026-50197HIGH7.8
  • Skipper Ingress logoSkipper Ingress
  • cpe:2.3:a:zalando:skipper
NoYesJul 17, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management