gitpython: Exposure of Sensitive Information to an Unauthorized Actor (ghsa:GHSA-whh4-5q6c-9v3x)
Published Sources: Hersteller
What is affected, what to do
Update gitpython to version 3.1.60.
Not sure whether and how you are affected? Ask a question about this vulnerability
Metrics
—
Priority
No value is available for this vulnerability.
—
CVSS v3
No value is available for this vulnerability.
—
EPSS score
No value is available for this vulnerability.
Show all metrics
- Severity
- Medium
Priority (0–325)
The priority score is a consolidated metric that condenses several individual signals into a single, action-guiding ranking: technical severity (CVSS), exploitation likelihood (EPSS), known-exploited status (KEV) and the context of the affected asset. The aim is to answer the only truly important question in vulnerability management: what first?
Read in glossary- 30.00 Methodology
Exploit maturity
An exploit is code or a technique that specifically uses a concrete vulnerability to force unintended behaviour — such as executing code or escalating privileges. It is the tool that turns a theoretical flaw into a practical attack.
Read in glossary- no public PoC known
KEV status
The KEV catalogue is a list maintained by the US authority CISA of vulnerabilities for which active exploitation in the wild has been confirmed. It answers not the question „how severe?“ but „is it already being attacked?“ — thereby sharply prioritising patching.
Read in glossary- —
- Published
CWE
CWE is a catalogue of typical weakness types in software and hardware — such as flawed input validation, unsafe memory handling or poor authentication. Where a CVE names a concrete vulnerability in a concrete product, a CWE describes the underlying class of defect.
Read in glossary- CWE-200, CWE-88
Classification under NIS2 and CRA
Rule-based classification from exploitation status and severity. It does not replace a case-by-case assessment.
NIS2
NIS2 is EU Directive (EU) 2022/2555 to raise the level of cybersecurity across the Union. It substantially broadens obligations compared with the first NIS directive: more sectors, mandatory risk management, staged reporting duties and personal accountability of senior management.
Read in glossary- Handle the vulnerability in regular vulnerability handling under Art. 21(2)(e) NIS2.
CRA
The CRA is EU Regulation (EU) 2024/2847 setting horizontal cybersecurity requirements for „products with digital elements“ — from industrial controllers and software to connected consumer devices. For the first time manufacturers must ensure security across the entire product lifecycle, handle vulnerabilities and provide security updates.
Read in glossary- From 11.12.2027, Annex I Part II CRA requires manufacturers of affected products with digital elements to handle vulnerabilities without delay and provide security updates.
ISO/IEC 27001
ISO/IEC 27001 is the internationally leading standard for an information security management system (ISMS). It describes a risk-based, process-oriented framework to systematically plan, implement, review and improve information security.
Read in glossary- Control A.8.8, management of technical vulnerabilities: assess relevance to your systems, plan remediation and keep evidence.
Description
Summary
GitPython 3.1.59 blocks a previously available local-file read path through unsafe git diff options such as -O/--orderfile.
However, the high-level diff API still permits --no-index with the default allow_unsafe_options=False.
--no-index changes the semantics of the paths arguments: instead of repository-relative pathspecs, Git interprets them as arbitrary filesystem paths.
When combined with the still-allowed -I/--ignore-matching-lines option, this creates a content-dependent Boolean oracle over a caller-selected local file.
This was reproduced against the published GitPython 3.1.59 wheel.
The original unsafe-option path is blocked in 3.1.59, while this alternate path remains reachable without setting allow_unsafe_options=True.
Details
Confirmed API surface:
repo.index.diff( None, no_index=True, I=pattern, paths=[baseline_path, target_path], create_patch=True, )
The relevant behavior is:
- --no-index makes the two values supplied via paths filesystem operands rather than repository pathspecs.
- -I/--ignore-matching-lines makes Git's result depend on whether the supplied regular expression matches the relevant file content.
- GitPython exposes the resulting bit through distinguishable behavior:
- matching condition: normal return with an empty DiffIndex
- non-matching condition: GitCommandError with exit status 1
An application that forwards attacker-influenced diff options and paths and exposes the success/error distinction can therefore be queried repeatedly to recover a guessable local single-line secret.
The issue was confirmed with the default allow_unsafe_options=False.
The behavior does not require the caller to explicitly opt into GitPython's unsafe-option mode.
Verified intended security boundary:
- GitPython 3.1.58 accepts the earlier -O/--orderfile local-file input path.
- GitPython 3.1.59 rejects that same path with UnsafeOptionError.
- GitPython 3.1.59 still permits the --no-index alternate path described above.
This appears to be an alternate route to the same local-file confidentiality property that the 3.1.59 diff option hardening is intended to protect.
PoC
A minimal reproducer, controlled extraction demonstrator, proof matrix, and proposed remediation are included in the attached package.
gitpython-3159-maintainer-evidence.zip
The minimal reproducer creates only temporary researcher-controlled files and demonstrates the following predicate:
correct prefix -> normal GitPython return incorrect prefix -> GitCommandError(status=1)
In the controlled extraction test, I generated three independent random single-line values and recovered all three exactly through repeated calls to the GitPython high-level API.
Result: 3/3 recovered.
The extraction harness also installs a Python audit hook that rejects direct Python open() access to the target file during the oracle phase. The content-dependent read is therefore performed by the child git process invoked through GitPython rather than by the reproduction script directly.
Controls were also tested:
- normal repository-scoped diff: no secret disclosure
- same outside paths without --no-index: no arbitrary-filesystem interpretation
- deliberately incorrect predicate: status 1 as expected
Suggested remediation is to classify --no-index as unsafe for the high-level diff API unless the caller explicitly sets allow_unsafe_options=True.
Impact
Potential impact is disclosure of local files readable by the process running GitPython.
Exploitation requires an embedding application to allow an attacker to influence:
- the relevant diff options,
- both path operands, and
- repeated requests while exposing a distinguishable success/error result.
The demonstrated attack is a blind content oracle rather than a one-request in-band file read. It is particularly applicable to short or structured single-line secrets where the target path and approximate value format are known or guessable.
Confirmed affected release: GitPython 3.1.59.
Source: GitHub Security Advisories
Affected products
The following versions are affected. Older releases of the same product line are also vulnerable unless stated otherwise.
| Affected versions | Fixed in | ||
|---|---|---|---|
| pip | gitpython |
|
|
Weakness classes (CWE)
CWE-200Exposure of Sensitive Information to an Unauthorized Actor
Class
The product exposes sensitive information to an actor that is not explicitly authorized to have access to that information.
Entry at MITRE CWE-200CWE-88Improper Neutralization of Argument Delimiters in a Command ('Argument Injection')
Base
The product constructs a string for a command to be executed by a separate component in another control sphere, but it does not properly delimit the intended arguments, options, or switches within that command string.
Entry at MITRE CWE-88