Skip to content

Commit 7a4f5dc

Browse files
codexByron
andcommitted
Block unsafe archive additions and bundle URI
GHSA-539m-9xh6-q6rr reports incomplete unsafe option lists for archive inputs and clone bundle URLs. Caller-controlled archive additions can expose or inject filesystem content, while clone --bundle-uri can dereference an additional caller-controlled URL. Extend the existing archive denylist with --add-file and --add-virtual-file, and the clone denylist with --bundle-uri. Regression coverage exercises archive kwargs plus both clone multi-option and keyword paths. Git baseline: a23bace963d508bd96983cc637131392d3face18. Documentation/git-archive.adoc defines --add-file/--add-virtual-file, and Documentation/git-clone.adoc defines --bundle-uri as fetching from the supplied URI. Co-authored-by: Sebastian Thiel <sebastian.thiel@icloud.com>
1 parent 3af0c25 commit 7a4f5dc

3 files changed

Lines changed: 12 additions & 0 deletions

File tree

git/repo/base.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ class Repo:
151151
"-c",
152152
# Can install hooks that execute during clone:
153153
"--template",
154+
# Fetches from a caller-controlled URL:
155+
"--bundle-uri",
154156
]
155157
"""Options to :manpage:`git-clone(1)` that allow arbitrary commands to be executed.
156158
@@ -172,6 +174,10 @@ class Repo:
172174
# Writes output to a caller-controlled filesystem path.
173175
"--output",
174176
"-o",
177+
# Reads from a caller-controlled filesystem path:
178+
"--add-file",
179+
# Injects a caller-controlled path and contents:
180+
"--add-virtual-file",
175181
]
176182

177183
unsafe_git_revision_options = [

test/test_clone.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ def test_clone_unsafe_options(self, rw_repo):
132132
"-cprotocol.ext.allow=always",
133133
"-vcprotocol.ext.allow=always",
134134
f"--template={tmp_dir}",
135+
f"--bundle-uri=file://{tmp_dir}",
135136
]
136137
for unsafe_option in unsafe_options:
137138
with self.assertRaises(UnsafeOptionError):
@@ -147,6 +148,7 @@ def test_clone_unsafe_options(self, rw_repo):
147148
{"conf": "protocol.ext.allow=always"},
148149
{"c": "protocol.ext.allow=always"},
149150
{"template": tmp_dir},
151+
{"bundle_uri": f"file://{tmp_dir}"},
150152
]
151153
for unsafe_option in unsafe_options:
152154
with self.assertRaises(UnsafeOptionError):

test/test_repo.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,10 @@ def test_archive_rejects_unsafe_options(self):
433433
with self.assertRaises(UnsafeOptionError):
434434
self.rorepo.archive(io.BytesIO(), "0.1.6", output=output_marker)
435435
assert not osp.exists(output_marker)
436+
with self.assertRaises(UnsafeOptionError):
437+
self.rorepo.archive(io.BytesIO(), "0.1.6", add_file=output_marker)
438+
with self.assertRaises(UnsafeOptionError):
439+
self.rorepo.archive(io.BytesIO(), "0.1.6", add_virtual_file="file:content")
436440

437441
def test_archive_rejects_unsafe_remote_protocol(self):
438442
with tempfile.TemporaryDirectory() as tdir:

0 commit comments

Comments
 (0)