| Gói / sản phẩm | Phiên bản bị ảnh hưởng | Phiên bản đã vá |
|---|---|---|
| gitpython | < 3.1.59 | 3.1.59 |
| gitpython | < 3.1.59 | 3.1.59 |
Repo.blame() / Repo.blame_incremental() guard forwarded revision options against unsafe_git_revision_options, but that denylist only contains the file-WRITE options --output/-o. git blame also honors --contents <file> and -S <file>, which cause the file's lines to be echoed into the blame result — an arbitrary file READ. Neither option is in the denylist, so a caller-influenced revision value of --contents=<path> passes the guard and leaks file contents. This is a distinct sink-option and impact class (READ) from GHSA-956x-8gvw-wg5v (which addressed the blame --output WRITE), directly analogous to GHSA-539m-9xh6-q6rr (archive READ gap accepted separately from the archive write/exec advisory).
unsafe_git_revision_options = ["--output","-o"] (git/repo/base.py:188). The rev string is passed to _option_candidates([rev], kwargs) and placed BEFORE the -- separator (base.py:841). The canonical name of --contents=... is contents, which is not on the denylist, so no UnsafeOptionError is raised. The trailing -- protects only the pathspec, not the option before the revision.
Arbitrary local file read at the privileges of the host process; the file's line contents appear in the blame result returned to the caller. Pure VALUE control (the caller forwards a user-influenced revision string). Default allow_unsafe_options=False.
result = repo.blame("--contents=/etc/passwd", "a.txt")
# result rows carry the victim file's line text
repo.blame(rev, file) with attacker rev="--contents=/etc/passwd" (or kwarg contents="/etc/passwd", or -S).Git.check_unsafe_options(_option_candidates([rev,...], kwargs), unsafe_git_revision_options) @ base.py:841. Guard: denylist = ["--output","-o"] only. Bypass proof: canonical name contents ∉ denylist → no error.self.git.blame(rev, "--", file, p=True, ...). argv (observed): ['git','blame','-p','--contents=<secret>','HEAD','--','a.txt'].Bạn đang dùng một trong các sản phẩm này? Quét site để biết có đang lộ phiên bản có lỗ hổng không.
Quét site miễn phíIndependently reproduced (independent test harness, default allow_unsafe_options=False): blame('--contents=<secret>','a.txt') → guard PASSED; result rows = ['GATE_SECRET_LINE_A','GATE_SECRET_LINE_B']. Control: blame('--output=…') still BLOCKED (guard active on this path). -S kwarg argv also reaches git unguarded.
GitPython <= 3.1.58 (denylist present verbatim on the latest release tag).
Prefer an allowlist of blame options; at minimum add --contents/-S (and any other path-taking blame options) to unsafe_git_revision_options, and make the membership rule "the option takes a filesystem path" rather than "the option writes output".
Reported by zx (Jace) — GitHub: @manus-use