<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet href="/static/style.xsl" type="text/xsl"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
  <channel>
    <title>Most recent entries from all</title>
    <link>https://db.gcve.eu</link>
    <description>Contains only the most 10 recent entries.</description>
    <docs>http://www.rssboard.org/rss-specification</docs>
    <generator>python-feedgen</generator>
    <language>en</language>
    <lastBuildDate>Fri, 02 Oct 2026 21:31:18 +0000</lastBuildDate>
    <item>
      <title>CVE-2026-100689 — GitPython before 3.1.62 Path Traversal via gitmodules path</title>
      <link>https://db.gcve.eu/vuln/cve-2026-100689</link>
      <description>&lt;p&gt;&lt;strong&gt;Affected:&lt;/strong&gt; gitpython-developers GitPython&lt;/p&gt;
&lt;p&gt;GitPython before 3.1.62 does not validate the `path` field read from an untrusted .gitmodules file when updating submodules. While a prior fix (GHSA-hmq2-w58f-27jc) added Submodule._validated_name() to constrain the `name` field, and GitPython&amp;#39;s own containment guard Submodule._to_relative_path() is applied in add() and move(), Submodule.update() derives the absolute checkout location from the raw `path` value without that guard. A .gitmodules entry containing directory traversal components (e.g., path = ../../../tmp/escaped) can therefore cause directories to be created via os.makedirs() outside the repository working tree, populated from the submodule URL on the clone path, and removed via shutil.rmtree() when force_remove is used. Exploitation requires an application flow that updates submodules at a non-HEAD commit (such as a historical-commit API); the common clone-then-update flow re-derives the path from a canonical tree lookup and is not affected. The issue is fixed in GitPython 3.1.62.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;&lt;strong&gt;Affected:&lt;/strong&gt; gitpython-developers GitPython&lt;/p&gt;
&lt;p&gt;GitPython before 3.1.62 does not validate the `path` field read from an untrusted .gitmodules file when updating submodules. While a prior fix (GHSA-hmq2-w58f-27jc) added Submodule._validated_name() to constrain the `name` field, and GitPython&amp;#39;s own containment guard Submodule._to_relative_path() is applied in add() and move(), Submodule.update() derives the absolute checkout location from the raw `path` value without that guard. A .gitmodules entry containing directory traversal components (e.g., path = ../../../tmp/escaped) can therefore cause directories to be created via os.makedirs() outside the repository working tree, populated from the submodule URL on the clone path, and removed via shutil.rmtree() when force_remove is used. Exploitation requires an application flow that updates submodules at a non-HEAD commit (such as a historical-commit API); the common clone-then-update flow re-derives the path from a canonical tree lookup and is not affected. The issue is fixed in GitPython 3.1.62.&lt;/p&gt;</content:encoded>
      <guid isPermaLink="false">https://db.gcve.eu/vuln/cve-2026-100689</guid>
    </item>
    <item>
      <title>GHSA-59cr-6r3x-644w — GitPython submodule update path traversal can write outside the repository</title>
      <link>https://db.gcve.eu/vuln/ghsa-59cr-6r3x-644w</link>
      <description>&lt;p&gt;&lt;strong&gt;Affected:&lt;/strong&gt; PyPI: GitPython&lt;/p&gt;
&lt;p&gt;**Affected:** `GitPython` **3.1.61** (latest release) and `main` — `git/objects/submodule/base.py`. `git diff 3.1.61 origin/main -- git/objects/submodule/` is empty, so both are identical here.&lt;/p&gt;
&lt;p&gt;---&lt;/p&gt;
&lt;p&gt;## The gap&lt;/p&gt;
&lt;p&gt;The fix for `GHSA-hmq2-w58f-27jc` added `Submodule._validated_name()` and wired it into `update()` and five siblings, closing the `.gitmodules` **name** → `.git/modules/&amp;lt;name&amp;gt;` traversal. The other attacker-controlled `.gitmodules` field, **`path`**, is read raw:&lt;/p&gt;
&lt;p&gt;```python
# git/objects/submodule/base.py:172-177
def _set_cache_(self, attr):
    if attr in (&amp;#34;path&amp;#34;, &amp;#34;_url&amp;#34;, &amp;#34;_branch_path&amp;#34;):
        reader = self.config_reader()
        self.path = reader.get(&amp;#34;path&amp;#34;)          # raw .gitmodules value
```&lt;/p&gt;
&lt;p&gt;and GitPython&amp;#39;s own containment guard is applied in only two of the places that consume it:&lt;/p&gt;
&lt;p&gt;```
400: def _to_relative_path(cls, parent_repo, path)      # the guard (abspath + commonpath containment)
542:     path = cls._to_relative_path(repo, path)        # add()   — guarded
1041:    module_checkout_path = self._to_relative_path(self.repo, module_path)   # move() — guarded
```&lt;/p&gt;
&lt;p&gt;`update()` validates only the name and then uses the path-derived absolute location directly:&lt;/p&gt;
&lt;p&gt;```
788:  self._validated_name(self.name)                    # NAME only
801:  checkout_module_abspath = self.abspath             # derived from self.path — unguarded
821:  os.makedirs(checkout_module_abspath, exist_ok=True)
```&lt;/p&gt;
&lt;p&gt;So `path = ../../../tmp/escaped` in an attacker-authored `.gitmodules` s…&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;&lt;strong&gt;Affected:&lt;/strong&gt; PyPI: GitPython&lt;/p&gt;
&lt;p&gt;**Affected:** `GitPython` **3.1.61** (latest release) and `main` — `git/objects/submodule/base.py`. `git diff 3.1.61 origin/main -- git/objects/submodule/` is empty, so both are identical here.&lt;/p&gt;
&lt;p&gt;---&lt;/p&gt;
&lt;p&gt;## The gap&lt;/p&gt;
&lt;p&gt;The fix for `GHSA-hmq2-w58f-27jc` added `Submodule._validated_name()` and wired it into `update()` and five siblings, closing the `.gitmodules` **name** → `.git/modules/&amp;lt;name&amp;gt;` traversal. The other attacker-controlled `.gitmodules` field, **`path`**, is read raw:&lt;/p&gt;
&lt;p&gt;```python
# git/objects/submodule/base.py:172-177
def _set_cache_(self, attr):
    if attr in (&amp;#34;path&amp;#34;, &amp;#34;_url&amp;#34;, &amp;#34;_branch_path&amp;#34;):
        reader = self.config_reader()
        self.path = reader.get(&amp;#34;path&amp;#34;)          # raw .gitmodules value
```&lt;/p&gt;
&lt;p&gt;and GitPython&amp;#39;s own containment guard is applied in only two of the places that consume it:&lt;/p&gt;
&lt;p&gt;```
400: def _to_relative_path(cls, parent_repo, path)      # the guard (abspath + commonpath containment)
542:     path = cls._to_relative_path(repo, path)        # add()   — guarded
1041:    module_checkout_path = self._to_relative_path(self.repo, module_path)   # move() — guarded
```&lt;/p&gt;
&lt;p&gt;`update()` validates only the name and then uses the path-derived absolute location directly:&lt;/p&gt;
&lt;p&gt;```
788:  self._validated_name(self.name)                    # NAME only
801:  checkout_module_abspath = self.abspath             # derived from self.path — unguarded
821:  os.makedirs(checkout_module_abspath, exist_ok=True)
```&lt;/p&gt;
&lt;p&gt;So `path = ../../../tmp/escaped` in an attacker-authored `.gitmodules` s…&lt;/p&gt;</content:encoded>
      <guid isPermaLink="false">https://db.gcve.eu/vuln/ghsa-59cr-6r3x-644w</guid>
    </item>
  </channel>
</rss>
