Логотип exploitDog
Консоль
Логотип exploitDog

exploitDog

github логотип

GHSA-5xxx-qhh7-9287

Опубликовано: 08 сент. 2026
Источник: github
Github: Прошло ревью
CVSS3: 6.5

Описание

GitPython: Incomplete unsafe_git_revision_options denylist omits --contents/-S, enabling arbitrary file read via Repo.blame()

Summary

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).

Root Cause

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.

Impact

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.

Proof of Concept

result = repo.blame("--contents=/etc/passwd", "a.txt") # result rows carry the victim file's line text

Attack Chain

  1. Entry: app calls repo.blame(rev, file) with attacker rev="--contents=/etc/passwd" (or kwarg contents="/etc/passwd", or -S).
  2. Check: 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.
  3. Sink: self.git.blame(rev, "--", file, p=True, ...). argv (observed): ['git','blame','-p','--contents=<secret>','HEAD','--','a.txt'].
  4. Impact: blame result rows carry the victim file's line text.

Bypass Evidence

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.

Affected Versions

GitPython <= 3.1.58 (denylist present verbatim on the latest release tag).

Suggested Fix

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

Пакеты

Наименование

GitPython

pip
Затронутые версииВерсия исправления

<= 3.1.58

3.1.59

EPSS

Процентиль: 15%
0.0024
Низкий

6.5 Medium

CVSS3

Дефекты

CWE-200
CWE-88

Связанные уязвимости

CVSS3: 6.5
ubuntu
24 дня назад

GitPython versions before 3.1.59 contain an incomplete denylist in the unsafe_git_revision_options guard that omits --contents and -S options, allowing attackers to read arbitrary files by passing these options to Repo.blame(). Attackers can supply revision values like --contents=/etc/passwd to leak file contents through the blame result returned to the caller.

CVSS3: 6.5
redhat
24 дня назад

GitPython versions before 3.1.59 contain an incomplete denylist in the unsafe_git_revision_options guard that omits --contents and -S options, allowing attackers to read arbitrary files by passing these options to Repo.blame(). Attackers can supply revision values like --contents=/etc/passwd to leak file contents through the blame result returned to the caller.

CVSS3: 6.5
nvd
24 дня назад

GitPython versions before 3.1.59 contain an incomplete denylist in the unsafe_git_revision_options guard that omits --contents and -S options, allowing attackers to read arbitrary files by passing these options to Repo.blame(). Attackers can supply revision values like --contents=/etc/passwd to leak file contents through the blame result returned to the caller.

CVSS3: 6.5
debian
24 дня назад

GitPython versions before 3.1.59 contain an incomplete denylist in the ...

CVSS3: 6.5
fstec
около 1 месяца назад

Уязвимость функций Repo.blame() и Repo.blame_incremental() механизма защиты unsafe_git_revision_options библиотеки Python для взаимодействия с git-репозиториями GitPython, позволяющая нарушителю получить несанкционированный доступ к защищаемой информации

EPSS

Процентиль: 15%
0.0024
Низкий

6.5 Medium

CVSS3

Дефекты

CWE-200
CWE-88