✓ProveIt
Examples / Report #1553841 Saved analysis

CVE-2022-27780: percent-encoded path separator in URL host

curl · 2022-04-288.1s analysis · $0.007 in model calls

What the report claims

URL decoding the entire proxy string could lead to SSRF filter bypasses.

Compare with curl's recorded outcome

Known vulnerability

A real vulnerability: CVE-2022-27780 percent-encoded path separator in URL host

Shown for comparison after analysis. The pipeline did not see this label.

ProveIt's finding

More detail needed

There is not enough information to verify the reported bug.

Why this finding?
  • No curl source code was provided for the target revision (fa40e15ae742), making it impossible to verify any claims about curl's proxy string parsing and URL decoding behavior.
  • The deterministic checks indicate the revision was grounded but the curl_source section explicitly states no code could be retrieved.
  • Without the relevant proxy parsing code (likely in lib/url.c or similar), the central claim about URL decoding of the host component cannot be assessed.
What still needs checking
  • curl source code for revision fa40e15ae742, particularly the proxy URL parsing and handling logic (likely in lib/url.c, lib/http_proxy.c, or similar files)
How this analysis ran 6 claims · 0 citations verified

Checked against curl master on 2022-04-28 (fa40e15ae742). Dev evaluation split. Citation verification checks that a referenced line was in the evidence; it does not prove the model interpreted it correctly.

1 · Grounding
grounded
no model · 1 references checked out, 0 did not
2 · Claims
NVIDIA-Nemotron-3-Nano-30B-A3B
6 claims · 1953 tokens · $0.0002
3 · Evidence
0 code snippets
real curl source at fa40e15ae742 · 2 docs via Tavily
4 · Judgment
Nemotron-3-Ultra-550b-a55b
4369 tokens · 6.2s · $0.0073
5 · Receipts
0 of 0 citations verified
every citation must point at code the judge was shown
Review a draft reply to the reporter

Edit and verify before sending.

Thank you for the report. We cannot evaluate this without the curl source code for the target revision. Please provide the relevant proxy URL parsing code (likely in lib/url.c or lib/http_proxy.c) from commit fa40e15ae742, or confirm the revision you tested against so we can retrieve the correct files.

Inspect all claims and source code 6 claims · 0 code excerpts

Report claims

C1flaw not verifiable

URL decoding the entire proxy string could lead to SSRF filter bypasses.

Read the reasoning

No curl source code was provided to verify whether URL decoding of the entire proxy string occurs and could lead to SSRF filter bypasses.

C2location not verifiable

When the following curl specifies the proxy string `http://example.com%2F127.0.0.1`

Read the reasoning

This describes a proxy string example but cannot be verified against curl's parsing logic without the source code.

C3trigger not verifiable

If curl URL parser or another RFC3986 compliant parser parses the initial string http://127.0.0.1%2F.example.com, it will derive 127.0.0.1%2Fexample.com or 127.0.0.1/example.com as the host

Read the reasoning

Claims about how curl's URL parser or RFC3986-compliant parsers handle percent-encoded separators cannot be verified without curl's parsing code.

C4impact not verifiable

curl will then URL decode the entire proxy string to http://127.0.0.1/example.com and send it to the server

Read the reasoning

The claim that curl URL-decodes the entire proxy string and sends it to the server cannot be verified without the relevant curl source code.

C5reproduction not verifiable

Perform the following: curl -x http://127.0.0.1:8899 http://example.com%2F127.0.0.1

Read the reasoning

Reproduction step provided but cannot be validated against curl's actual behavior without the source code.

C6reproduction not verifiable

curl -x http://127.0.0.1:8899 -H "Host: example.com" http://example.com%2F127.0.0.1/%2e%2e/

Read the reasoning

Second reproduction step with Host header override cannot be verified without curl's source code.

What the report says about other projects

confirmed nghttpx normalizes host by converting to lower case and decodes percent-encoded unreserved characters in path per RFC 3986

“For host part, they are converted to lower case. For path part, percent-encoded unreserved characters defined in RFC 3986 are decoded, and any dot-segments (".." and ".") are resolved and removed.” source

confirmed RFC 7239 defines node identifier syntax for proxy forwarding

“The node identifier is one of the following: o The client's IP address, with an optional port number o A token indicating that the IP address of the client is not known to the proxy server o A generated token, allowing for tracing and debugging, while allowing the internal structure or sensitive information to be hidden” source

Read the original report (excerpt)

Full report on HackerOne ↗

## Summary: URL decoding the entire proxy string could lead to SSRF filter bypasses. For example, When the following curl specifies the proxy string `http://example.com%2F127.0.0.1` - If curl URL parser or another RFC3986 compliant parser parses the initial string http://127.0.0.1%2F.example.com, it will derive 127.0.0.1%2Fexample.com or 127.0.0.1/example.com as the host, if for instance, an SSRF check is used to determine if a host ends with .example.com (.example.com being a allow-listed domain), the check will succeed. - curl will then URL decode the entire proxy string to http://127.0.0.1/example.com and send it to the server ```` GET http://127.0.0.1/example.com HTTP/1.1 Host: 127.0.0.1/example.com User-Agent: curl/7.83.0 Accept: */* Proxy-Connection: Keep-Alive ```` - This proxy string is valid, and proxy servers, even RFC3986-compliant ones will send the request to the host 127.0.0.1 ## Steps To Reproduce: I switched things up and used 127.0.0.1 as the allow-listed server and example.com as the target server to make it easier (no need to setup a HTTP server) to reproduce. 1. I used https://github.com/abhinavsingh/proxy.py as my proxy server. 2. Perform the following: ```` curl -x http://127.0.0.1:8899 http://example.com%2F127.0.0.1 ```` 3. You will receive a malformed response ```` <?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>400 - Bad Request</title> </head> <body> <h1>400 - Bad Request</h1> </body> </html> ```` However, this response is actually being returned by example.com, the reason is that proxy.py will forward the Host header, currently 127.0.0.1/example.com curl sends it, making it a Blind SSRF 4. If - an attacker can control the host header either via curl itself - the proxy does not forward the host header curl sends, - or if servers which ignore the Host header entirely such as Express is used, it is possible to read the full response ```` curl -x http://127.0.0.1:8899 -H "Host: example.com" http://example.com%2F127.0.0.1/%2e%2e/ ```` ## Recommended Fix: The recommended fix for this is to not URL decode the host component of the proxy string when passing to p …

Source code

No source code was retrieved for this analysis. The evidence may be incomplete.