| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2,6 +2,20 @@ | |||
| 2 | 2 | Changelog | |
| 3 | 3 | ========= | |
| 4 | 4 | ||
| 5 | + 3.1.59 | ||
| 6 | + ====== | ||
| 7 | + | ||
| 8 | + Security fixes for | ||
| 9 | + | ||
| 10 | + * https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-5xxx-qhh7-9287 | ||
| 11 | + * https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-3wxw-xv34-2frg | ||
| 12 | + | ||
| 13 | + If you can, also try and provide feedback on the upcoming v4 branch | ||
| 14 | + https://github.com/gitpython-developers/GitPython/pull/2177 - patches welcome. | ||
| 15 | + | ||
| 16 | + See the following for all changes. | ||
| 17 | + https://github.com/gitpython-developers/GitPython/releases/tag/3.1.59 | ||
| 18 | + | ||
| 5 | 19 | 3.1.58 | |
| 6 | 20 | ====== | |
| 7 | 21 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -652,6 +652,7 @@ class Git(metaclass=_GitMeta): | |||
| 652 | 652 | unsafe_git_ls_remote_options = [ | |
| 653 | 653 | # This option allows arbitrary command execution in git-ls-remote. | |
| 654 | 654 | "--upload-pack", | |
| 655 | + "--exec", | ||
| 655 | 656 | ] | |
| 656 | 657 | ||
| 657 | 658 | unsafe_git_pathspec_from_file_options = [ | |
@@ -976,7 +977,9 @@ def _canonicalize_option_name(cls, option: str) -> str: | |||
| 976 | 977 | return dashify(option_tokens[0]) | |
| 977 | 978 | ||
| 978 | 979 | @classmethod | |
| 979 | - def check_unsafe_options(cls, options: List[str], unsafe_options: List[str]) -> None: | ||
| 980 | + def check_unsafe_options( | ||
| 981 | + cls, options: List[str], unsafe_options: List[str], clusterable_short_options: str = "46flnqsv" | ||
| 982 | + ) -> None: | ||
| 980 | 983 | """Raise :class:`~git.exc.UnsafeOptionError` for blocked option spellings. | |
| 981 | 984 | ||
| 982 | 985 | In addition to exact matches, this rejects abbreviated long options accepted | |
@@ -1011,7 +1014,7 @@ def check_unsafe_options(cls, options: List[str], unsafe_options: List[str]) -> | |||
| 1011 | 1014 | # These value-less Git flags can be clustered before another short option | |
| 1012 | 1015 | # (for example, ``-fuVALUE``). Stop at any other character because it may | |
| 1013 | 1016 | # begin an attached value, as ``o`` does in the safe option ``-oupstream``. | |
| 1014 | - clusterable_short_options = frozenset("46flnqsv") | ||
| 1017 | + clusterable_short_options_set = frozenset(clusterable_short_options) | ||
| 1015 | 1018 | options_are_kwargs = all(not option.startswith("-") for option in options) | |
| 1016 | 1019 | for option in options: | |
| 1017 | 1020 | candidate = cls._canonicalize_option_name(option) | |
@@ -1028,7 +1031,7 @@ def check_unsafe_options(cls, options: List[str], unsafe_options: List[str]) -> | |||
| 1028 | 1031 | raise UnsafeOptionError( | |
| 1029 | 1032 | f"{unsafe_option} is not allowed, use `allow_unsafe_options=True` to allow it." | |
| 1030 | 1033 | ) | |
| 1031 | - if option_char not in clusterable_short_options: | ||
| 1034 | + if option_char not in clusterable_short_options_set: | ||
| 1032 | 1035 | break | |
| 1033 | 1036 | if not (option.startswith("--") or (options_are_kwargs and len(candidate) > 1)): | |
| 1034 | 1037 | continue | |
@@ -1133,7 +1136,7 @@ def ls_remote( | |||
| 1133 | 1136 | """List references in a remote repository. | |
| 1134 | 1137 | ||
| 1135 | 1138 | :param allow_unsafe_options: | |
| 1136 | - Allow unsafe options, like ``--upload-pack``. | ||
| 1139 | + Allow unsafe options, like ``--upload-pack`` or ``--exec``. | ||
| 1137 | 1140 | """ | |
| 1138 | 1141 | if not allow_unsafe_options: | |
| 1139 | 1142 | candidate_options = self._option_candidates(args, kwargs) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -220,8 +220,8 @@ def diff( | |||
| 220 | 220 | to be read and diffed. | |
| 221 | 221 | ||
| 222 | 222 | :param allow_unsafe_options: | |
| 223 | - If ``True``, allow options such as ``--output`` that can write to arbitrary | ||
| 224 | - filesystem paths. | ||
| 223 | + If ``True``, allow options such as ``--output`` and ``-O`` that can write to | ||
| 224 | + or read from arbitrary filesystem paths. | ||
| 225 | 225 | ||
| 226 | 226 | :param kwargs: | |
| 227 | 227 | Additional arguments passed to :manpage:`git-diff(1)`, such as ``R=True`` to | |
@@ -238,7 +238,8 @@ def diff( | |||
| 238 | 238 | if not allow_unsafe_options: | |
| 239 | 239 | Git.check_unsafe_options( | |
| 240 | 240 | options=Git._option_candidates([other], kwargs), | |
| 241 | - unsafe_options=self.repo.unsafe_git_revision_options, | ||
| 241 | + unsafe_options=self.repo.unsafe_git_diff_options, | ||
| 242 | + clusterable_short_options="46abceflmnpqrstuvwzBCDMNRW", | ||
| 242 | 243 | ) | |
| 243 | 244 | ||
| 244 | 245 | args: List[Union[PathLike, Diffable]] = [] | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1567,7 +1567,8 @@ def diff( | |||
| 1567 | 1567 | if not allow_unsafe_options: | |
| 1568 | 1568 | Git.check_unsafe_options( | |
| 1569 | 1569 | options=Git._option_candidates([other], kwargs), | |
| 1570 | - unsafe_options=self.repo.unsafe_git_revision_options, | ||
| 1570 | + unsafe_options=self.repo.unsafe_git_diff_options, | ||
| 1571 | + clusterable_short_options="46abceflmnpqrstuvwzBCDMNRW", | ||
| 1571 | 1572 | ) | |
| 1572 | 1573 | ||
| 1573 | 1574 | # Only run if we are the default repository index. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -134,15 +134,17 @@ def create( | |||
| 134 | 134 | :return: | |
| 135 | 135 | A new :class:`TagReference`. | |
| 136 | 136 | """ | |
| 137 | + legacy_ref = kwargs.pop("ref", None) | ||
| 138 | + if legacy_ref: | ||
| 139 | + reference = legacy_ref | ||
| 140 | + | ||
| 137 | 141 | if not allow_unsafe_options: | |
| 138 | 142 | Git.check_unsafe_options( | |
| 139 | - options=Git._option_candidates([], kwargs), | ||
| 143 | + options=Git._option_candidates([path, reference], kwargs), | ||
| 140 | 144 | unsafe_options=cls.unsafe_git_tag_options, | |
| 145 | + clusterable_short_options="46adefilnqsv", | ||
| 141 | 146 | ) | |
| 142 | 147 | ||
| 143 | - if "ref" in kwargs and kwargs["ref"]: | ||
| 144 | - reference = kwargs["ref"] | ||
| 145 | - | ||
| 146 | 148 | if "message" in kwargs and kwargs["message"]: | |
| 147 | 149 | kwargs["m"] = kwargs["message"] | |
| 148 | 150 | del kwargs["message"] | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -199,6 +199,19 @@ class Repo: | |||
| 199 | 199 | "-o", | |
| 200 | 200 | ] | |
| 201 | 201 | ||
| 202 | + unsafe_git_blame_options = unsafe_git_revision_options + [ | ||
| 203 | + # These options read from arbitrary files and expose their contents through blame output. | ||
| 204 | + "--contents", | ||
| 205 | + "-S", | ||
| 206 | + "--ignore-revs-file", | ||
| 207 | + ] | ||
| 208 | + | ||
| 209 | + unsafe_git_diff_options = unsafe_git_revision_options + [ | ||
| 210 | + # Reads caller-controlled order patterns from an arbitrary file. | ||
| 211 | + "-O", | ||
| 212 | + "--orderfile", | ||
| 213 | + ] | ||
| 214 | + | ||
| 202 | 215 | # Invariants | |
| 203 | 216 | config_level: ConfigLevels_Tup = ("system", "user", "global", "repository") | |
| 204 | 217 | """Represents the configuration level of a configuration file.""" | |
@@ -1149,7 +1162,7 @@ def blame_incremental( | |||
| 1149 | 1162 | :manpage:`git-rev-parse(1)` is a valid option. | |
| 1150 | 1163 | ||
| 1151 | 1164 | :param allow_unsafe_options: | |
| 1152 | - Allow unsafe options in revision argument, like ``--output``. | ||
| 1165 | + Allow unsafe options in revision argument, like ``--output`` or ``--contents``. | ||
| 1153 | 1166 | ||
| 1154 | 1167 | :return: | |
| 1155 | 1168 | Lazy iterator of :class:`BlameEntry` tuples, where the commit indicates the | |
@@ -1161,7 +1174,9 @@ def blame_incremental( | |||
| 1161 | 1174 | """ | |
| 1162 | 1175 | if not allow_unsafe_options: | |
| 1163 | 1176 | Git.check_unsafe_options( | |
| 1164 | - options=Git._option_candidates([rev], kwargs), unsafe_options=self.unsafe_git_revision_options | ||
| 1177 | + options=Git._option_candidates([rev], kwargs), | ||
| 1178 | + unsafe_options=self.unsafe_git_blame_options, | ||
| 1179 | + clusterable_short_options="46bceflnpqstvw", | ||
| 1165 | 1180 | ) | |
| 1166 | 1181 | ||
| 1167 | 1182 | data: bytes = self.git.blame(rev, "--", file, p=True, incremental=True, stdout_as_string=False, **kwargs) | |
@@ -1253,7 +1268,7 @@ def blame( | |||
| 1253 | 1268 | :manpage:`git-rev-parse(1)` is a valid option. | |
| 1254 | 1269 | ||
| 1255 | 1270 | :param allow_unsafe_options: | |
| 1256 | - Allow unsafe options in revision argument, like ``--output``. | ||
| 1271 | + Allow unsafe options in revision argument, like ``--output`` or ``--contents``. | ||
| 1257 | 1272 | ||
| 1258 | 1273 | :return: | |
| 1259 | 1274 | list: [git.Commit, list: [<line>]] | |
@@ -1269,7 +1284,8 @@ def blame( | |||
| 1269 | 1284 | if not allow_unsafe_options: | |
| 1270 | 1285 | Git.check_unsafe_options( | |
| 1271 | 1286 | options=Git._option_candidates([rev, rev_opts_list], kwargs), | |
| 1272 | - unsafe_options=self.unsafe_git_revision_options, | ||
| 1287 | + unsafe_options=self.unsafe_git_blame_options, | ||
| 1288 | + clusterable_short_options="46bceflnpqstvw", | ||
| 1273 | 1289 | ) | |
| 1274 | 1290 | data: bytes = self.git.blame(rev, *rev_opts_list, "--", file, p=True, stdout_as_string=False, **kwargs) | |
| 1275 | 1291 | commits: Dict[str, Commit] = {} | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -376,11 +376,25 @@ def test_diff_submodule(self): | |||
| 376 | 376 | def test_diff_rejects_unsafe_output_options(self): | |
| 377 | 377 | commit = self.rorepo.head.commit | |
| 378 | 378 | ||
| 379 | + commit.diff(S="needle") | ||
| 380 | + | ||
| 379 | 381 | calls = ( | |
| 380 | 382 | lambda target: commit.diff(output=target), | |
| 381 | 383 | lambda target: commit.diff(other=f"--output={target}"), | |
| 384 | + lambda target: commit.diff(O=target), | ||
| 385 | + lambda target: commit.diff(orderfile=target), | ||
| 386 | + lambda target: commit.diff(other=f"--orderfile={target}"), | ||
| 387 | + lambda target: commit.diff(other=f"-pO{target}"), | ||
| 388 | + lambda target: commit.diff(other=f"-uO{target}"), | ||
| 389 | + lambda target: commit.diff(other=f"-DO{target}"), | ||
| 382 | 390 | lambda target: self.rorepo.index.diff(NULL_TREE, output=target), | |
| 383 | 391 | lambda target: self.rorepo.index.diff(f"--output={target}"), | |
| 392 | + lambda target: self.rorepo.index.diff(NULL_TREE, O=target), | ||
| 393 | + lambda target: self.rorepo.index.diff(NULL_TREE, orderfile=target), | ||
| 394 | + lambda target: self.rorepo.index.diff(f"--orderfile={target}"), | ||
| 395 | + lambda target: self.rorepo.index.diff(f"-pO{target}"), | ||
| 396 | + lambda target: self.rorepo.index.diff(f"-uO{target}"), | ||
| 397 | + lambda target: self.rorepo.index.diff(f"-DO{target}"), | ||
| 384 | 398 | ) | |
| 385 | 399 | for index, call in enumerate(calls): | |
| 386 | 400 | target = osp.join(self.repo_dir, f"diff-output-{index}") | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -70,6 +70,21 @@ def test_tag_create_rejects_unsafe_file_options(self, rw_repo): | |||
| 70 | 70 | with self.assertRaises(UnsafeOptionError): | |
| 71 | 71 | TagReference.create(rw_repo, f"unsafe-{index}", **option) | |
| 72 | 72 | ||
| 73 | + for args in ( | ||
| 74 | + ("unsafe-reference", f"--file={message.name}"), | ||
| 75 | + (f"--file={message.name}", "HEAD"), | ||
| 76 | + (f"-eF{message.name}", "HEAD"), | ||
| 77 | + (f"-iF{message.name}", "HEAD"), | ||
| 78 | + ): | ||
| 79 | + with self.assertRaises(UnsafeOptionError): | ||
| 80 | + TagReference.create(rw_repo, *args) | ||
| 81 | + | ||
| 82 | + with self.assertRaises(UnsafeOptionError): | ||
| 83 | + TagReference.create(rw_repo, "unsafe-ref-kwarg", ref=f"--file={message.name}") | ||
| 84 | + | ||
| 85 | + tag = TagReference.create(rw_repo, "legacy-ref", ref="HEAD", allow_unsafe_options=True) | ||
| 86 | + self.assertEqual(tag.commit, rw_repo.head.commit) | ||
| 87 | + | ||
| 73 | 88 | tag = TagReference.create(rw_repo, "allowed-file", F=message.name, allow_unsafe_options=True) | |
| 74 | 89 | self.assertEqual(tag.tag.message, "private tag message") | |
| 75 | 90 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1035,6 +1035,7 @@ def test_ls_remote_unsafe_options(self, rw_repo): | |||
| 1035 | 1035 | {"upload-pack": f"touch {tmp_file}"}, | |
| 1036 | 1036 | {"upload_pack": f"touch {tmp_file}"}, | |
| 1037 | 1037 | {"upl": f"touch {tmp_file}"}, | |
| 1038 | + {"exec": f"touch {tmp_file}"}, | ||
| 1038 | 1039 | ] | |
| 1039 | 1040 | for unsafe_option in unsafe_options: | |
| 1040 | 1041 | with self.assertRaises(UnsafeOptionError): | |
@@ -1047,6 +1048,8 @@ def test_ls_remote_unsafe_options(self, rw_repo): | |||
| 1047 | 1048 | rw_repo.git.ls_remote(f"--upload-pack={tmp_file}", ".") | |
| 1048 | 1049 | with self.assertRaises(UnsafeOptionError): | |
| 1049 | 1050 | rw_repo.git.ls_remote(f"--upl={tmp_file}", ".") | |
| 1051 | + with self.assertRaises(UnsafeOptionError): | ||
| 1052 | + rw_repo.git.ls_remote(f"--exec={tmp_file}", ".") | ||
| 1050 | 1053 | with self.assertRaises(UnsafeOptionError): | |
| 1051 | 1054 | rw_repo.git.ls_remote("--upload-pack", "touch", ".") | |
| 1052 | 1055 | with self.assertRaises(UnsafeOptionError): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -590,8 +590,11 @@ def test_blame_real(self): | |||
| 590 | 590 | def test_blame_rejects_unsafe_revision(self): | |
| 591 | 591 | with tempfile.TemporaryDirectory() as tdir: | |
| 592 | 592 | output_marker = osp.join(tdir, "pwn") | |
| 593 | - with self.assertRaises(UnsafeOptionError): | ||
| 594 | - self.rorepo.blame(f"--output={output_marker}", "README.md") | ||
| 593 | + for option in ("--output", "--contents", "-S", "-wS", "--ignore-revs-file"): | ||
| 594 | + with self.assertRaises(UnsafeOptionError): | ||
| 595 | + self.rorepo.blame(f"{option}={output_marker}", "README.md") | ||
| 596 | + with self.assertRaises(UnsafeOptionError): | ||
| 597 | + list(self.rorepo.blame_incremental(f"{option}={output_marker}", "README.md")) | ||
| 595 | 598 | assert not osp.exists(output_marker) | |
| 596 | 599 | ||
| 597 | 600 | def test_blame_rejects_unsafe_options(self): | |
| Back | FazBrowse Home | New Git URL |
0 commit comments