Skip to content

Commit 47abd85

Browse files
agericgitster
authored andcommitted
fetch: Strip usernames from url's before storing them
When pulling from a remote, the full URL including username is by default added to the commit message. Since it adds very little value but could be used by malicious people to glean valid usernames (with matching hostnames), we're far better off just stripping the username before storing the remote URL locally. Note that this patch has no lasting visible effect when "git pull" does not create a merge commit. It simply alters what gets written to .git/FETCH_HEAD, which is used by "git merge" to automagically create its messages. Signed-off-by: Andreas Ericsson <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 66996ec commit 47abd85

File tree

3 files changed

+54
-2
lines changed

3 files changed

+54
-2
lines changed

builtin-fetch.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ static int update_local_ref(struct ref *ref,
289289
}
290290
}
291291

292-
static int store_updated_refs(const char *url, const char *remote_name,
292+
static int store_updated_refs(const char *raw_url, const char *remote_name,
293293
struct ref *ref_map)
294294
{
295295
FILE *fp;
@@ -298,11 +298,13 @@ static int store_updated_refs(const char *url, const char *remote_name,
298298
char note[1024];
299299
const char *what, *kind;
300300
struct ref *rm;
301-
char *filename = git_path("FETCH_HEAD");
301+
char *url, *filename = git_path("FETCH_HEAD");
302302

303303
fp = fopen(filename, "a");
304304
if (!fp)
305305
return error("cannot open %s: %s\n", filename, strerror(errno));
306+
307+
url = transport_anonymize_url(raw_url);
306308
for (rm = ref_map; rm; rm = rm->next) {
307309
struct ref *ref = NULL;
308310

@@ -376,6 +378,7 @@ static int store_updated_refs(const char *url, const char *remote_name,
376378
fprintf(stderr, " %s\n", note);
377379
}
378380
}
381+
free(url);
379382
fclose(fp);
380383
if (rc & 2)
381384
error("some local refs could not be updated; try running\n"

transport.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,3 +1083,51 @@ int transport_disconnect(struct transport *transport)
10831083
free(transport);
10841084
return ret;
10851085
}
1086+
1087+
/*
1088+
* Strip username (and password) from an url and return
1089+
* it in a newly allocated string.
1090+
*/
1091+
char *transport_anonymize_url(const char *url)
1092+
{
1093+
char *anon_url, *scheme_prefix, *anon_part;
1094+
size_t anon_len, prefix_len = 0;
1095+
1096+
anon_part = strchr(url, '@');
1097+
if (is_local(url) || !anon_part)
1098+
goto literal_copy;
1099+
1100+
anon_len = strlen(++anon_part);
1101+
scheme_prefix = strstr(url, "://");
1102+
if (!scheme_prefix) {
1103+
if (!strchr(anon_part, ':'))
1104+
/* cannot be "me@there:/path/name" */
1105+
goto literal_copy;
1106+
} else {
1107+
const char *cp;
1108+
/* make sure scheme is reasonable */
1109+
for (cp = url; cp < scheme_prefix; cp++) {
1110+
switch (*cp) {
1111+
/* RFC 1738 2.1 */
1112+
case '+': case '.': case '-':
1113+
break; /* ok */
1114+
default:
1115+
if (isalnum(*cp))
1116+
break;
1117+
/* it isn't */
1118+
goto literal_copy;
1119+
}
1120+
}
1121+
/* @ past the first slash does not count */
1122+
cp = strchr(scheme_prefix + 3, '/');
1123+
if (cp && cp < anon_part)
1124+
goto literal_copy;
1125+
prefix_len = scheme_prefix - url + 3;
1126+
}
1127+
anon_url = xcalloc(1, 1 + prefix_len + anon_len);
1128+
memcpy(anon_url, url, prefix_len);
1129+
memcpy(anon_url + prefix_len, anon_part, anon_len);
1130+
return anon_url;
1131+
literal_copy:
1132+
return xstrdup(url);
1133+
}

transport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,5 +74,6 @@ const struct ref *transport_get_remote_refs(struct transport *transport);
7474
int transport_fetch_refs(struct transport *transport, const struct ref *refs);
7575
void transport_unlock_pack(struct transport *transport);
7676
int transport_disconnect(struct transport *transport);
77+
char *transport_anonymize_url(const char *url);
7778

7879
#endif

0 commit comments

Comments
 (0)