@@ -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 */
8988void 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