A logic error in detect_proxy caused truncation of environment variable names for long protocol schemes.
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
The code does what the report says, but curl's own policy may exclude it. A maintainer decides.
curl policy: Local attackers already presentSee 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.
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
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.
in lib/url.c, the detect_proxy function
Read the reasoning
The function `detect_proxy` is defined at line 2038 in lib/url.c.
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.
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.
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.
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
Source code
| 2035 | * name and is not limited to HTTP proxies only. |
| 2036 | * The returned pointer must be freed by the caller (unless NULL) |
| 2037 | ****************************************************************/ |
| 2038 | static 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 */ |
| 1131 | int 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 | } |