Skip to content

Commit ba46f8b

Browse files
authored
fix: avoid curl_getenv for unix:// too (#3540)
1 parent 5b09e4d commit ba46f8b

File tree

1 file changed

+29
-17
lines changed

1 file changed

+29
-17
lines changed

ext/coms.c

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,8 @@ static void ddtrace_store_env(char **target, const char *value) {
8282
*
8383
* There is a special case in libcurl for HTTP: to avoid header-based
8484
* injection in CGI/server contexts, it does *not* automatically fall back
85-
* from "http_proxy" to "HTTP_PROXY". We still snapshot both here, but when
86-
* we later configure our agent handle we only ever use the cached value
87-
* explicitly, not libcurl's own HTTP_PROXY fallback.
85+
* from "http_proxy" to "HTTP_PROXY". To match libcurl behavior, we only
86+
* snapshot "http_proxy" (lowercase) for HTTP.
8887
*/
8988
void ddtrace_coms_minit_proxy_env(void) {
9089
const char *v;
@@ -96,11 +95,8 @@ void ddtrace_coms_minit_proxy_env(void) {
9695
}
9796
ddtrace_store_env(&ddtrace_env_no_proxy, v);
9897

99-
/* http_proxy / HTTP_PROXY */
98+
/* http_proxy (note: intentionally no HTTP_PROXY fallback; matches curl) */
10099
v = getenv("http_proxy");
101-
if (!v || !v[0]) {
102-
v = getenv("HTTP_PROXY");
103-
}
104100
ddtrace_store_env(&ddtrace_env_http_proxy, v);
105101

106102
/* https_proxy / HTTPS_PROXY */
@@ -838,6 +834,14 @@ static void ddtrace_curl_set_hostname_generic(CURL *curl, const char *path) {
838834

839835
if (url && url[0]) {
840836
const char *proxy = NULL;
837+
const char *http_url = url;
838+
bool is_unix_socket = false;
839+
840+
if (strlen(url) > 7 && strncmp(url, "unix://", 7) == 0) {
841+
is_unix_socket = true;
842+
curl_easy_setopt(curl, CURLOPT_UNIX_SOCKET_PATH, url + 7);
843+
http_url = "http://localhost";
844+
}
841845

842846
/* Choose a proxy based on the agent URL scheme, using the cached
843847
* env values. This mirrors curl's detect_proxy() precedence:
@@ -846,29 +850,37 @@ static void ddtrace_curl_set_hostname_generic(CURL *curl, const char *path) {
846850
*
847851
* This happens without calling getenv() in the worker thread.
848852
*/
849-
if (strncmp(url, "http://", 7) == 0) {
853+
if (strncmp(http_url, "http://", 7) == 0) {
850854
if (ddtrace_env_http_proxy) {
851855
proxy = ddtrace_env_http_proxy;
852856
} else if (ddtrace_env_all_proxy) {
853857
proxy = ddtrace_env_all_proxy;
854858
}
855-
} else if (strncmp(url, "https://", 8) == 0) {
859+
} else if (strncmp(http_url, "https://", 8) == 0) {
856860
if (ddtrace_env_https_proxy) {
857861
proxy = ddtrace_env_https_proxy;
858862
} else if (ddtrace_env_all_proxy) {
859863
proxy = ddtrace_env_all_proxy;
860864
}
861865
}
862866

863-
if (proxy) {
864-
curl_easy_setopt(curl, CURLOPT_PROXY, proxy);
865-
}
867+
/* Prevent libcurl from consulting proxy-related environment variables
868+
* (via curl_getenv()) in the background writer thread.
869+
*
870+
* This preserves the *startup-snapshotted* proxy behavior:
871+
* - if we cached a proxy value during MINIT, use it
872+
* - otherwise, use no proxy
873+
*
874+
* If CURLOPT_PROXY is left unset, libcurl may call detect_proxy()
875+
* during curl_easy_perform(), which can hit curl_getenv() even when
876+
* no proxy env vars are set. Setting it explicitly avoids that code
877+
* path entirely.
878+
*
879+
* For unix:// agent URLs, proxying is not meaningful; we explicitly
880+
* disable it as well.
881+
*/
882+
curl_easy_setopt(curl, CURLOPT_PROXY, (!is_unix_socket && proxy) ? proxy : "");
866883

867-
char *http_url = url;
868-
if (strlen(url) > 7 && strncmp(url, "unix://", 7) == 0) {
869-
curl_easy_setopt(curl, CURLOPT_UNIX_SOCKET_PATH, url + 7);
870-
http_url = "http://localhost";
871-
}
872884
size_t agent_url_len = strlen(http_url) + strlen(path) + 1;
873885
char *agent_url = malloc(agent_url_len);
874886
sprintf(agent_url, "%s%s", http_url, path);

0 commit comments

Comments
 (0)