← Commit list

7a6bd027d0

Daniel Stenberg
Daniel Stenberg
2026-09-21
SUCCESS Duration: 384s

Subject

getinfo: make sure CURLINFO_EFFECTIVE_URL does not contain creds

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

—

Build Log

(log yok)

Commit Diff GitHub →

lib/getinfo.c+42 -5
@@ -63,6 +63,7 @@ void Curl_initinfo(struct Curl_easy *data)
curlx_safefree(info->contenttype);
curlx_safefree(info->wouldredirect);
+ curlx_safefree(info->effective_url);
memset(&info->primary, 0, sizeof(info->primary));
info->retry_after = 0;
@@ -76,15 +77,51 @@ void Curl_initinfo(struct Curl_easy *data)
#endif
}
+static CURLcode effective_url(struct Curl_easy *data,
+ const char **param_charp)
+{
+ const char *s = Curl_bufref_ptr(&data->state.url);
+ *param_charp = s ? s : "";
+ if(s) {
+ char *url = NULL;
+ /* Make a copy of the URL without credentials */
+ CURLU *u = curl_url();
+ CURLUcode uc;
+ if(!u)
+ return CURLE_OUT_OF_MEMORY;
+
+ uc = curl_url_set(u, CURLUPART_URL, s,
+ CURLU_NON_SUPPORT_SCHEME |
+ (data->set.path_as_is ? CURLU_PATH_AS_IS : 0));
+ if(!uc)
+ uc = curl_url_set(u, CURLUPART_USER, NULL, 0);
+ if(!uc)
+ uc = curl_url_set(u, CURLUPART_PASSWORD, NULL, 0);
+ if(!uc)
+ uc = curl_url_get(u, CURLUPART_URL, &url, CURLU_GET_EMPTY);
+
+ curl_url_cleanup(u);
+
+ if(uc || !url)
+ return CURLE_OUT_OF_MEMORY;
+ if(strcmp(url, s)) {
+ /* they are different */
+ curlx_free(data->info.effective_url);
+ data->info.effective_url = url;
+ *param_charp = url;
+ }
+ else
+ curl_free(url);
+ }
+ return CURLE_OK;
+}
+
static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
const char **param_charp)
{
switch(info) {
- case CURLINFO_EFFECTIVE_URL: {
- const char *s = Curl_bufref_ptr(&data->state.url);
- *param_charp = s ? s : "";
- }
- break;
+ case CURLINFO_EFFECTIVE_URL:
+ return effective_url(data, param_charp);
case CURLINFO_EFFECTIVE_METHOD: {
const char *m = CURL_EASY_STR(data, STRING_CUSTOMREQUEST);
if(!m) {
lib/transfer.c+1 -0
@@ -503,6 +503,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
data->state.authhost.want = data->set.httpauth;
data->state.authproxy.want = data->set.proxyauth;
curlx_safefree(data->info.wouldredirect);
+ curlx_safefree(data->info.effective_url);
Curl_data_priority_clear_state(data);
if(data->set.http_auto_referer)
Curl_bufref_free(&data->state.referer);
lib/url.c+1 -0
@@ -270,6 +270,7 @@ CURLcode Curl_close(struct Curl_easy **datap)
curlx_safefree(data->state.most_recent_ftp_entrypath);
curlx_safefree(data->info.contenttype);
curlx_safefree(data->info.wouldredirect);
+ curlx_safefree(data->info.effective_url);
/* No longer a dirty share, if it exists */
if(Curl_share_easy_unlink(data))
lib/urldata.h+1 -0
@@ -409,6 +409,7 @@ struct PureInfo {
curl_off_t numconnects; /* how many new connections libcurl created */
char *contenttype; /* the content type of the object */
char *wouldredirect; /* URL this would have been redirected to if asked to */
+ char *effective_url; /* when needed */
curl_off_t retry_after; /* info from Retry-After: header */
const char *conn_scheme;
int httpcode; /* Recent HTTP, FTP, RTSP or SMTP response code */
tests/data/Makefile.am+1 -0
@@ -1750,6 +1750,7 @@ TESTCASES = \
test1849 \
test1851 \
test1862 \
+ test1876 \
test1900 \
test1901 \
test1902 \
tests/data/test1876+67 -0
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="US-ASCII"?>
+<testcase>
+<info>
+<keywords>
+netrc
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data crlf="headers" nocheck="yes">
+HTTP/1.1 301 redir
+Content-Length: 0
+Content-Type: text/html
+Location: %TESTNUMBER0002
+
+</data>
+
+<data2 crlf="headers">
+HTTP/1.1 200 OK
+Content-Length: 0
+Content-Type: text/html
+
+</data2>
+
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+verify no credentials present in effective URL after redirect
+</name>
+<file name="%LOGDIR/netrc">
+machine %HOSTIP
+login netrcuser
+password netrcSECRET123
+</file>
+
+<command option="no-include">
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --netrc-optional --netrc-file %LOGDIR/netrc -L -w 'EFFECTIVE_URL=%{url_effective}\n'
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="headers">
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Basic %b64[netrcuser:netrcSECRET123]b64%
+User-Agent: curl/%VERSION
+Accept: */*
+
+GET /%TESTNUMBER0002 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Basic %b64[netrcuser:netrcSECRET123]b64%
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+<stdout>
+EFFECTIVE_URL=http://%HOSTIP:%HTTPPORT/%TESTNUMBER0002
+</stdout>
+</verify>
+</testcase>