Skip to content

Commit b204af8

Browse files
author
Mark Ruvald Pedersen
committed
Add url_redact() and tests: Ensure we avoid leaking passwords or tokens
Artifact's commit message contains the src-repo's URL. This URL may contain sensitive information which should be filtered out.
1 parent dd17dc1 commit b204af8

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

src/git_recycle_bin.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
import argparse
77
import subprocess
88
import mimetypes
9+
import urllib.parse
910
from itertools import takewhile
1011

11-
import datetime
1212
import datetime
1313
import dateutil.relativedelta
1414
from dateutil.tz import tzlocal
@@ -115,6 +115,29 @@ def sanitize_branch_name(name: str) -> str:
115115
return sanitized_name
116116

117117

118+
def url_redact(url: str, replacement: str = 'REDACTED'):
119+
""" Replace sensitive password/api-token from URL with a string """
120+
parsed = urllib.parse.urlparse(url)
121+
122+
# If there is no password, return the original URL
123+
if not parsed.password:
124+
return url
125+
126+
# Redact the password/token
127+
new_netloc = parsed.netloc.replace(parsed.password, replacement)
128+
129+
# Reconstruct the URL
130+
redacted_url = urllib.parse.urlunparse((
131+
parsed.scheme,
132+
new_netloc,
133+
parsed.path,
134+
parsed.params,
135+
parsed.query,
136+
parsed.fragment
137+
))
138+
139+
return redacted_url
140+
118141

119142
def exec(command):
120143
printer.debug("Run:", command, file=sys.stderr)

tests/test_artifact.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,23 @@ def test_parse_expire_datetime():
6868

6969
def test_parse_expire_datetime_invalid():
7070
assert grb.parse_expire_date(prefix_discard="artifact/expire/", expiry_formatted="artifact/expire/30d/") == {"date":None, "time":None, "tzoffset":None}
71+
72+
def test_url_redact():
73+
assert grb.url_redact(url="https://foo:pass@service/my/repo.git", replacement="REDACTED") == "https://foo:REDACTED@service/my/repo.git"
74+
assert grb.url_redact(url="https://foo@service/my/repo.git", replacement="REDACTED") == "https://foo@service/my/repo.git"
75+
assert grb.url_redact(url="https://service/my/repo.git", replacement="REDACTED") == "https://service/my/repo.git"
76+
assert grb.url_redact(url="https://service/my/re:po.git", replacement="REDACTED") == "https://service/my/re:po.git"
77+
assert grb.url_redact(url="https://service/my/re:[email protected]", replacement="REDACTED") == "https://service/my/re:[email protected]"
78+
79+
assert grb.url_redact(url="ssh://foo:pass@service/my/repo.git", replacement="REDACTED") == "ssh://foo:REDACTED@service/my/repo.git"
80+
assert grb.url_redact(url="ssh://[foo:pass@service]/my/repo.git", replacement="REDACTED") == "ssh://[foo:REDACTED@service]/my/repo.git"
81+
assert grb.url_redact(url="ssh://foo@service/my/repo.git", replacement="REDACTED") == "ssh://foo@service/my/repo.git"
82+
assert grb.url_redact(url="ssh://service/my/repo.git", replacement="REDACTED") == "ssh://service/my/repo.git"
83+
assert grb.url_redact(url="ssh://service/my/re:po.git", replacement="REDACTED") == "ssh://service/my/re:po.git"
84+
assert grb.url_redact(url="ssh://service/my/re:[email protected]", replacement="REDACTED") == "ssh://service/my/re:[email protected]"
85+
86+
assert grb.url_redact(url="foo:pass@service/my/repo.git", replacement="REDACTED") == "foo:pass@service/my/repo.git"
87+
assert grb.url_redact(url="foo@service/my/repo.git", replacement="REDACTED") == "foo@service/my/repo.git"
88+
assert grb.url_redact(url="service/my/repo.git", replacement="REDACTED") == "service/my/repo.git"
89+
assert grb.url_redact(url="service/my/re:po.git", replacement="REDACTED") == "service/my/re:po.git"
90+
assert grb.url_redact(url="service/my/re:[email protected]", replacement="REDACTED") == "service/my/re:[email protected]"

0 commit comments

Comments
 (0)