August 4, 2026
Breaking API Gateway Isolation with Path Traversal and URL Parsing Discrepancies
How a simple “../” and CRLF injection bypassed proxy restrictions and exposed internal services

By Hazem Brini
4 min read
How a simple "../" and CRLF injection bypassed proxy restrictions and exposed internal services
By Hazem Brini
Introduction
During a private bug bounty engagement, I discovered a path traversal vulnerability affecting an API Gateway protecting a large microservice architecture.
At first glance, the issue looked like a classic information disclosure involving Prometheus metrics.
However, after investigating further, it became clear that the real vulnerability was much deeper.
The gateway itself could be tricked into routing requests outside of their intended namespace, effectively breaking the isolation between public and internal APIs.
The vulnerability was ultimately classified as Critical by the security team because it allowed access to internal endpoints that were never intended to be reachable from the Internet.
For responsible disclosure reasons, the target hostnames and service names have been anonymized throughout this article.
Understanding the architecture
Most modern applications expose only a subset of their APIs through an API Gateway.
The gateway acts as a security boundary, forwarding only approved routes while hiding internal services from the Internet.
A simplified architecture looked similar to this:
Internet
│
▼
Load Balancer
│
▼
API Gateway
│
┌───────────────┼─────────────────┐
│ │ │
Public API Users API Internal APIs
│
/_/metrics , /_/heapdump ..Internet
│
▼
Load Balancer
│
▼
API Gateway
│
┌───────────────┼─────────────────┐
│ │ │
Public API Users API Internal APIs
│
/_/metrics , /_/heapdump ..The assumption behind this architecture is simple:
If a route isn't exposed by the gateway, it shouldn't be reachable from the outside.
As this research demonstrates, that assumption can quickly break down if request normalization isn't handled consistently across the infrastructure.
The First Clue
While mapping the application, something caught my attention.
One of the public endpoints looked like this:
/match/ad/apps/rec/discover/match/ad/apps/rec/discoverAt first glance, the URL structure didn't resemble a typical REST endpoint. The URL structure looked more like an API Gateway dispatching requests to different backend services.
Of course, I had no visibility into the actual architecture. However, several observations pointed in that direction:
- Consistent routing patterns across different endpoints.
- Similar response formats despite different URL paths.
- Multiple path segments suggesting backend service routing rather than a single application.
That led me to ask a simple question:
What happens if the gateway doesn't properly handle ../ sequences?
After appending several traversal sequences to the request, something unexpected happened.
Instead of returning a 404 Not Found, the application started responding with resources belonging to completely different backend routes.
At that point, it became clear that the request path was being resolved before being forwarded internally, allowing traversal outside the originally intended route.
Discovering Internal Endpoints
Following the traversed routes eventually led to an internal API index exposing several backend endpoints:
- recommend
- preview
- fetch
- configuration
- health
- metrics
Seeing /_/metrics immediately caught my attention.
Prometheus endpoints often expose valuable operational information, making them highly interesting during reconnaissance.
Unfortunately…
Direct access was blocked.
Stage 1: 403 Forbidden
Requesting the endpoint normally produced:
403 Forbidden
Request forbidden by administrative rules.403 Forbidden
Request forbidden by administrative rules.This told me something important.
The endpoint wasn't missing.
It existed.
Some security layer was actively blocking access.
Stage 2: Looking for a Parsing Discrepancy
A 403 Forbidden response rarely marks the end of an investigation.
It usually indicates that the resource exists, but a security control is preventing access.
That naturally led me to look for inconsistencies in how different infrastructure components parsed the request.
In many infrastructures, a request passes through several components before reaching the backend:
- Load Balancer
- WAF
- Reverse Proxy
- API Gateway
- Backend Framework
The interesting part is that these components don't always interpret URLs in exactly the same way.
If one component validates the raw URL while another later normalizes it, unexpected bypasses become possible.
This class of vulnerabilities is commonly known as a URL parsing discrepancy or path normalization issue.
Turning 403 into 200
After experimenting with different URL encodings and control characters, I discovered that inserting a CRLF sequence before traversing back to the protected endpoint caused the filtering logic to be bypassed.
The payload looked roughly like:
../%0d%0a/../../_/metrics../%0d%0a/../../_/metricsThe exact same request that previously returned 403 Forbidden suddenly returned:
HTTP/1.1 200 OKHTTP/1.1 200 OKalong with the full Prometheus metrics page.
How the Bypass Worked ?
Client
│
GET /discover../%0d%0a/../../_/metrics
│
▼
Load Balancer / WAF
│
Checks the raw request
✔ Request allowed
│
▼
API Gateway
│
Normalizes the request path
│
▼
Internal route (/_/metrics)
│
▼
HTTP 200 OKClient
│
GET /discover../%0d%0a/../../_/metrics
│
▼
Load Balancer / WAF
│
Checks the raw request
✔ Request allowed
│
▼
API Gateway
│
Normalizes the request path
│
▼
Internal route (/_/metrics)
│
▼
HTTP 200 OKAlthough I obviously don't know the vendor's internal implementation, the behavior strongly suggests that different infrastructure components interpreted the request differently.
One component evaluated the raw request and allowed it to pass, while another later normalized the path before routing it internally.
The result was a classic parser discrepancy: the component enforcing the security policy and the component routing the request disagreed on what the final URL actually was.
Vendor Assessment
The report was submitted through an Intigriti on a private bug bounty program.
While I initially reported the issue as an exposed metrics endpoint, the vendor's investigation revealed the real impact: bypassing API Gateway path restrictions to access internal APIs.
As the triager explained:
"The main impact is not reading the
/metricsendpoint, but going from/external/to/users/using the simple ../ trick. Since some of these APIs are unauthenticated and can leak personal information, we have decided to treat this report as Critical instead of High."
The report was subsequently upgraded from High to Critical.
Lessons Learned
This research reinforced three important lessons:
- Normalize URLs before validating them.
- Every component in the request chain must interpret URLs consistently.
- Internal APIs should never rely solely on gateway isolation for security.
Sometimes, an exposed endpoint isn't the vulnerability… it's simply the first clue that a much larger architectural issue exists.
Final Thoughts
I'd like to thank the security team for their professionalism throughout the disclosure process. Their fast triage, clear communication, and thorough impact assessment made the experience a great example of effective collaboration between researchers and vendors.
Hopefully this write-up encourages other researchers to look beyond the obvious. Some of the most impactful vulnerabilities don't begin with sophisticated payloads, but with a simple question and a bit of curiosity.
"What happens if I add ../?"