Skip to content

Commit d5c61f7

Browse files
committed
Try not to log credentials in repo URL
This extracts the username and password from the URL and replaces it with the bare URL, using the usual credential mechanism for user/pass.
1 parent 65e0953 commit d5c61f7

File tree

2 files changed

+63
-3
lines changed

2 files changed

+63
-3
lines changed

main.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,11 @@ func main() {
481481
if *flPassword != "" && *flPasswordFile != "" {
482482
handleConfigError(log, true, "ERROR: only one of --password and --password-file may be specified")
483483
}
484+
if u, err := url.Parse(*flRepo); err == nil { // it may not even parse as a URL, that's OK
485+
if u.User != nil {
486+
handleConfigError(log, true, "ERROR: credentials may not be specified in --repo when --username is specified")
487+
}
488+
}
484489
} else {
485490
if *flPassword != "" {
486491
handleConfigError(log, true, "ERROR: --password may only be specified when --username is specified")
@@ -564,6 +569,21 @@ func main() {
564569
absTouchFile := makeAbsPath(*flTouchFile, absRoot)
565570

566571
// Merge credential sources.
572+
if *flUsername == "" {
573+
// username and user@host URLs are validated as mutually exclusive
574+
if u, err := url.Parse(*flRepo); err == nil { // it may not even parse as a URL, that's OK
575+
if u.User != nil {
576+
if user := u.User.Username(); user != "" {
577+
*flUsername = user
578+
}
579+
if pass, found := u.User.Password(); found {
580+
*flPassword = pass
581+
}
582+
u.User = nil
583+
*flRepo = u.String()
584+
}
585+
}
586+
}
567587
if *flUsername != "" {
568588
cred := credential{
569589
URL: *flRepo,
@@ -1535,7 +1555,7 @@ func (git *repoSync) currentWorktree() (worktree, error) {
15351555
// and tries to clean up any detritus. This function returns whether the
15361556
// current hash has changed and what the new hash is.
15371557
func (git *repoSync) SyncRepo(ctx context.Context, refreshCreds func(context.Context) error) (bool, string, error) {
1538-
git.log.V(3).Info("syncing", "repo", git.repo)
1558+
git.log.V(3).Info("syncing", "repo", redactURL(git.repo))
15391559

15401560
if err := refreshCreds(ctx); err != nil {
15411561
return false, "", fmt.Errorf("credential refresh failed: %w", err)
@@ -1660,7 +1680,7 @@ func (git *repoSync) SyncRepo(ctx context.Context, refreshCreds func(context.Con
16601680

16611681
// fetch retrieves the specified ref from the upstream repo.
16621682
func (git *repoSync) fetch(ctx context.Context, ref string) error {
1663-
git.log.V(2).Info("fetching", "ref", ref, "repo", git.repo)
1683+
git.log.V(2).Info("fetching", "ref", ref, "repo", redactURL(git.repo))
16641684

16651685
// Fetch the ref and do some cleanup, setting or un-setting the repo's
16661686
// shallow flag as appropriate.
@@ -1711,7 +1731,7 @@ func md5sum(s string) string {
17111731

17121732
// StoreCredentials stores a username and password for later use.
17131733
func (git *repoSync) StoreCredentials(ctx context.Context, url, username, password string) error {
1714-
git.log.V(1).Info("storing git credential", "url", url)
1734+
git.log.V(1).Info("storing git credential", "url", redactURL(url))
17151735
git.log.V(9).Info("md5 of credential", "url", url, "username", md5sum(username), "password", md5sum(password))
17161736

17171737
creds := fmt.Sprintf("url=%v\nusername=%v\npassword=%v\n", url, username, password)

test_e2e.sh

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1812,6 +1812,46 @@ function e2e::auth_http_password() {
18121812
assert_file_eq "$ROOT/link/file" "$FUNCNAME"
18131813
}
18141814

1815+
##############################################
1816+
# Test HTTP basicauth with a password in the URL
1817+
##############################################
1818+
function e2e::auth_http_password_in_url() {
1819+
# Run a git-over-HTTP server.
1820+
CTR=$(docker_run \
1821+
-v "$REPO":/git/repo:ro \
1822+
e2e/test/httpd)
1823+
IP=$(docker_ip "$CTR")
1824+
1825+
# Try with wrong username
1826+
assert_fail \
1827+
GIT_SYNC \
1828+
--one-time \
1829+
--repo="http://wrong:testpass@$IP/repo" \
1830+
--root="$ROOT" \
1831+
--link="link"
1832+
assert_file_absent "$ROOT/link/file"
1833+
1834+
# Try with wrong password
1835+
assert_fail \
1836+
GIT_SYNC \
1837+
--one-time \
1838+
--repo="http://testuser:wrong@$IP/repo" \
1839+
--root="$ROOT" \
1840+
--link="link"
1841+
assert_file_absent "$ROOT/link/file"
1842+
1843+
# Try with the right password
1844+
GIT_SYNC \
1845+
--one-time \
1846+
--repo="http://testuser:testpass@$IP/repo" \
1847+
--root="$ROOT" \
1848+
--link="link"
1849+
1850+
assert_link_exists "$ROOT/link"
1851+
assert_file_exists "$ROOT/link/file"
1852+
assert_file_eq "$ROOT/link/file" "$FUNCNAME"
1853+
}
1854+
18151855
##############################################
18161856
# Test HTTP basicauth with a password-file
18171857
##############################################

0 commit comments

Comments
 (0)