fix: guard diff output options · gitpython-developers/GitPython@040de4b · GitHub
Skip to content

Commit 040de4b

Browse files
codexByron
authored andcommitted
fix: guard diff output options
Reject unsafe diff options before revision parsing or Git invocation so callers cannot write command output to arbitrary filesystem paths. Cover commit and index diffs, including option-like revisions, and preserve an explicit allow_unsafe_options escape hatch. References GHSA-fjr4-x663-mwxc. Validated against Git baseline a23bace9.
1 parent 19799d0 commit 040de4b

3 files changed

Lines changed: 48 additions & 4 deletions

File tree

git/diff.py

Lines changed: 12 additions & 2 deletions

git/index/base.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from gitdb.db import MemoryDB
2424

2525
from git.compat import defenc, force_bytes
26+
from git.cmd import Git
2627
import git.diff as git_diff
2728
from git.exc import CheckoutError, GitCommandError, GitError, InvalidGitRepositoryError
2829
from git.objects import Blob, Commit, Object, Submodule, Tree
@@ -1492,6 +1493,7 @@ def diff(
14921493
] = git_diff.INDEX,
14931494
paths: Union[PathLike, List[PathLike], Tuple[PathLike, ...], None] = None,
14941495
create_patch: bool = False,
1496+
allow_unsafe_options: bool = False,
14951497
**kwargs: Any,
14961498
) -> git_diff.DiffIndex[git_diff.Diff]:
14971499
"""Diff this index against the working copy or a :class:`~git.objects.tree.Tree`
@@ -1504,6 +1506,12 @@ def diff(
15041506
Will only work with indices that represent the default git index as they
15051507
have not been initialized with a stream.
15061508
"""
1509+
if not allow_unsafe_options:
1510+
Git.check_unsafe_options(
1511+
options=Git._option_candidates([other], kwargs),
1512+
unsafe_options=self.repo.unsafe_git_revision_options,
1513+
)
1514+
15071515
# Only run if we are the default repository index.
15081516
if self._file_path != self._index_path():
15091517
raise AssertionError("Cannot call %r on indices that do not represent the default git index" % self.diff())
@@ -1560,12 +1568,18 @@ def diff(
15601568
# Invert the existing R flag.
15611569
cur_val = kwargs.get("R", False)
15621570
kwargs["R"] = not cur_val
1563-
return other.diff(self.INDEX, paths, create_patch, **kwargs)
1571+
return other.diff(
1572+
self.INDEX,
1573+
paths,
1574+
create_patch,
1575+
allow_unsafe_options=allow_unsafe_options,
1576+
**kwargs,
1577+
)
15641578
# END diff against other item handling
15651579

15661580
# If other is not None here, something is wrong.
15671581
if other is not None:
15681582
raise ValueError("other must be None, Diffable.INDEX, a Tree or Commit, was %r" % other)
15691583

15701584
# Diff against working copy - can be handled by superclass natively.
1571-
return super().diff(other, paths, create_patch, **kwargs)
1585+
return super().diff(other, paths, create_patch, allow_unsafe_options=allow_unsafe_options, **kwargs)

test/test_diff.py

Lines changed: 20 additions & 0 deletions

0 commit comments

Comments
 (0)