✓ProveIt
Examples / Report #3473182 Saved analysis

A logic error in detect_proxy caused truncation of environment variable names for long protocol schemes.

curl · 2025-12-2013.7s analysis · $0.017 in model calls

What the report claims

detect_proxy uses a fixed-size buffer of 20 bytes to construct proxy environment variable names, causing truncation of longer scheme names and leading to unintended proxy configuration.

Compare with curl's recorded outcome

Labeled AI slop

curl's maintainer lists this report as AI slop

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

ProveIt's finding

Needs a policy review

The code does what the report says, but curl's own policy may exclude it. A maintainer decides.

curl policy: Local attackers already present
Judgment withdrawn. The answer failed the evidence check.
See the withdrawn model reasoning

The following reasoning failed the citation check and does not support the final finding.

  • The truncation behavior described in the report is real: the 20-byte buffer cannot hold scheme names longer than ~13 characters plus the "_proxy" suffix, so longer schemes are silently truncated.
  • However, exploitation requires an attacker who can control environment variables on the local system. The report explicitly states: "An attacker with control over environment variables could set truncated variable names to redirect traffic."
  • The project's security policy lists "Local attackers already present" as a category that is not considered a security problem: "When an issue can only be attacked or misused by an attacker present on the local system or network, the bar is raised. If a local user wrongfully has elevated rights on your system enough to attack curl, they can probably already do much worse harm and the problem is not really in curl."
  • Standard protocol schemes (http, https, ftp, etc.) are well under the 13-character limit, so the truncation only affects unusual custom schemes. The code comment at lines 2072–2083 shows the developers already consider environment-variable manipulation in webserver contexts a known risk and mitigate it for HTTP_PROXY.
How this analysis ran 6 claims · 7 citations verified

Evidence check: the behavior is real; the project's policy section 'Local attackers already present' may exclude it

Checked against curl master on 2025-12-20 (7ded0e21cda3). Test 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 · 7 references checked out, 0 did not
2 · Claims
NVIDIA-Nemotron-3-Nano-30B-A3B
6 claims · 1669 tokens · $0.0002
3 · Evidence
2 code snippets
real curl source at 7ded0e21cda3 · 3 docs via Tavily
4 · Judgment
Nemotron-3-Ultra-550b-a55b
9558 tokens · 10.7s · $0.0163
5 · Receipts
7 of 7 citations verified
every citation must point at code the judge was shown
Inspect the withdrawn draft reply

This draft belongs to the withdrawn judgment. It may contain unsupported claims.

Thank you for the detailed analysis. The truncation you identified is real: the 20-byte buffer in detect_proxy() cannot accommodate scheme names longer than about 13 characters, so longer custom schemes are silently truncated when forming the environment variable name. However, this is not considered a security vulnerability in curl because exploitation requires an attacker who can already set environment variables on the local system. Our security policy explicitly states that issues requiring a local attacker "raise the bar" and are not treated as curl security problems, since such an attacker can likely cause far worse harm. Standard schemes (http, https, ftp, etc.) are unaffected. If you have a scenario where this truncation can be triggered without local environment-variable control, please share those details.

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

This model judgment was withdrawn. The claim assessments below are preserved for inspection and may be wrong.

Report claims

C1flaw supported

detect_proxy uses a fixed-size buffer, proxy_env[20], to construct proxy environment variable names

Read the reasoning

The code at line 2060 explicitly declares `char proxy_env[20];`, confirming a fixed 20-byte buffer.

C2location supported

in lib/url.c, the detect_proxy function

Read the reasoning

The function `detect_proxy` is defined at line 2038 in lib/url.c.

C3trigger supported

when a protocol scheme longer than 12 characters is used, the environment variable name is silently truncated

Read the reasoning

The buffer is 20 bytes; the format "%s_proxy" adds 6 characters ("_proxy") plus a null terminator, so any scheme longer than 13 characters will be silently truncated by curl_msnprintf. The report's "12 characters" is approximately correct.

C4impact supported

curl may read configuration from an unintended (truncated) environment variable, causing unexpected proxy behavior

Read the reasoning

After truncation, `curl_getenv(proxy_env)` at line 2070 reads the truncated name, so curl may look up an unintended environment variable.

C5reproduction supported

call curl_msnprintf(proxy_env, sizeof(proxy_env), "%s_proxy", conn->handler->scheme) with a long scheme such as "extremelylongprotocolname"

Read the reasoning

Line 2066 shows the exact call described.

C6reproduction supported

the scheme "extremelylongprotocolname" (25 characters) will be truncated to "extremelylongsc" instead of "extremelylongprotocolname_proxy"

Read the reasoning

The truncation behavior is real. The example "extremelylongprotocolname" (25 chars) would be truncated to the first 19 characters of the formatted string (e.g., "extremelylongprotocol") rather than "extremelylongsc" as the report states, but the core claim of silent truncation is correct.

Read the original report

Full report on HackerOne ↗

In lib/url.c, the detect_proxy function uses a fixed-size buffer, proxy_env[20], to construct proxy environment variable names (e.g., http_proxy). However, the curl URL parser (lib/urlapi.c) allows protocol schemes up to 40 characters (MAX_SCHEME_LEN). When a protocol scheme longer than 12 characters is used, the environment variable name is silently truncated to 19 characters by curl_msnprintf. This causes a business logic error where curl may read configuration from an unintended (truncated) environment variable, causing potentially unexpected proxy behavior in applications using custom schemes. Google Gemini AI was used as an analysis aid only; all findings, including the truncation behavior, were manually verified by reviewing the source code and testing a PoC. Affected Versions - curl 8.18.0-DEV (latest master branch) - Platform: Windows 10 x64 (platform-independent logic issue) Steps to Reproduce 1. Inspect lib/url.c lines 2060–2067. 2. Note that proxy_env is declared as char proxy_env[20];. 3. Observe that conn->handler->scheme can be up to 40 characters (MAX_SCHEME_LEN). 4. Call curl_msnprintf(proxy_env, sizeof(proxy_env), "%s_proxy", conn->handler->scheme); with a long scheme. 5. Example: "extremelylongprotocolname" (25 characters) will be truncated to "extremelylongsc" instead of "extremelylongprotocolname_proxy". Supporting/Reference Materials - Source code snippet from lib/url.c (lines 2060–2067) - PoC code (poc_truncation.c) demonstrating truncation - Screenshot of PoC execution showing truncation - Screenshot of the vulnerable code in lib/url.c ## Impact A business logic flaw allows proxy configuration manipulation or bypass through truncating environment variable names. This can lead to unexpected network behavior or bypass security policies that rely on protocol-specific proxy settings. An attacker with control over environment variables could set truncated variable names to redirect traffic through an unauthorized proxy.

Source code

lib/url.clines 2035–2092 · lines 2060-2067 cited by the report
2035 * name and is not limited to HTTP proxies only.
2036 * The returned pointer must be freed by the caller (unless NULL)
2037 ****************************************************************/
2038static char *detect_proxy(struct Curl_easy *data,
C2: static char *detect_proxy(struct Curl_easy *data, struct connectdata *conn)
2039 struct connectdata *conn)
2040{
2041 char *proxy = NULL;
2042
2043 /* If proxy was not specified, we check for default proxy environment
2044 * variables, to enable i.e Lynx compliance:
2045 *
2046 * http_proxy=http://some.server.dom:port/
2047 * https_proxy=http://some.server.dom:port/
2048 * ftp_proxy=http://some.server.dom:port/
2049 * no_proxy=domain1.dom,host.domain2.dom
2050 * (a comma-separated list of hosts which should
2051 * not be proxied, or an asterisk to override
2052 * all proxy variables)
2053 * all_proxy=http://some.server.dom:port/
2054 * (seems to exist for the CERN www lib. Probably
2055 * the first to check for.)
2056 *
2057 * For compatibility, the all-uppercase versions of these variables are
2058 * checked if the lowercase versions do not exist.
2059 */
2060 char proxy_env[20];
C1: char proxy_env[20]; declares a 20-byte buffer
C6: char proxy_env[20];
2061 const char *envp = proxy_env;
2062#ifdef CURL_DISABLE_VERBOSE_STRINGS
2063 (void)data;
2064#endif
2065
2066 curl_msnprintf(proxy_env, sizeof(proxy_env), "%s_proxy",
C3: curl_msnprintf(proxy_env, sizeof(proxy_env), "%s_proxy", conn->handler->scheme);
C5: curl_msnprintf(proxy_env, sizeof(proxy_env), "%s_proxy", conn->handler->scheme);
C6: curl_msnprintf(proxy_env, sizeof(proxy_env), "%s_proxy", conn->handler->scheme);
2067 conn->handler->scheme);
2068
2069 /* read the protocol proxy: */
2070 proxy = curl_getenv(proxy_env);
C4: proxy = curl_getenv(proxy_env);
2071
2072 /*
2073 * We do not try the uppercase version of HTTP_PROXY because of
2074 * security reasons:
2075 *
2076 * When curl is used in a webserver application
2077 * environment (cgi or php), this environment variable can
2078 * be controlled by the web server user by setting the
2079 * http header 'Proxy:' to some value.
2080 *
2081 * This can cause 'internal' http/ftp requests to be
2082 * arbitrarily redirected by any external attacker.
2083 */
2084 if(!proxy && !curl_strequal("http_proxy", proxy_env)) {
2085 /* There was no lowercase variable, try the uppercase version: */
2086 Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
2087 proxy = curl_getenv(proxy_env);
2088 }
2089
2090 if(!proxy) {
2091#ifndef CURL_DISABLE_WEBSOCKETS
2092 /* websocket proxy fallbacks */
lib/mprintf.clines 1131–1139 · definition of curl_msnprintf
1131int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...)
1132{
1133 int retcode;
1134 va_list ap_save; /* argument pointer */
1135 va_start(ap_save, format);
1136 retcode = curl_mvsnprintf(buffer, maxlength, format, ap_save);
1137 va_end(ap_save);
1138 return retcode;
1139}