GCVE Workshop - 22 September 2026 (14:00-18:00), Luxembourg Before The Vulnopticon Conference - Registration
brew-cobo-cli-cve-2026-76218
Vulnerability from osv_homebrew
Published
2026-08-20 08:43
Modified
2026-09-10 19:01
Summary
GitPython: Unguarded git option forwarding in Repo.init enables arbitrary command execution via --template clone hooks
Details

Summary

Repo.init() forwards **kwargs verbatim to git init with no unsafe-option guard and no allow_unsafe_options parameter. git init --template=<dir> copies <dir>/hooks/* into the new repo's .git/hooks, so an attacker-controlled template kwarg plants a hook that executes on the next git operation → arbitrary code execution. --template is already recognized as unsafe for clone (it is on unsafe_git_clone_options, and GHSA-6p8h-3wgx-97gf covers the clone path), but Repo.init is a distinct method that never received a guard and needs an independent fix.

Root Cause

Repo.init(path, mkdir, odbt, expand_vars, **kwargs) is a bare git.init(**kwargs) (git/repo/base.py:1435) with no check_unsafe_options and no allow_unsafe_options.

Impact

Arbitrary code execution (hook fires on next git op) at the privileges of the host process. Two preconditions raise attack complexity (AC:H): the app must forward a template= kwarg (KEY control) AND the attacker must stage an executable hook directory at a known path — the same profile GHSA-6p8h-3wgx-97gf accepted as HIGH for the clone path. Default allow_unsafe_options is irrelevant here because Repo.init has no guard at all.

Proof of Concept

# attacker stages /evil/hooks/post-commit (executable)
from git import Repo
Repo.init(path, template="/evil")
# next commit runs /evil/hooks/post-commit -> ACE

Attack Chain

  1. Entry: attacker stages /evil/hooks/post-commit (executable) and gets the app to call Repo.init(path, template='/evil').
  2. Check: NONE on Repo.init. Bypass proof: base.py:1435 is a bare git.init(**kwargs). argv (observed): ['git','init','--template=/evil'].
  3. Sink: git copies /evil/hooks/post-commit<repo>/.git/hooks/post-commit.
  4. Impact: next commit runs the hook → arbitrary code execution.

Bypass Evidence

Independently reproduced (gate harness): Repo.init(dst, template='<evil>') → argv ['git','init','--template=<evil>'] unguarded; hook copied into .git/hooks/post-commit; after git commit the INIT_ACE marker was created. --separate-git-dir=<path> is a parallel arbitrary-redirect vector through the same unguarded sink (value control only).

Affected Versions

GitPython <= 3.1.57 (unguarded git.init(**kwargs) present verbatim on the latest release tag).

Suggested Fix

Add a check_unsafe_options guard (with an allow_unsafe_options parameter) to Repo.init, consulting a denylist that includes --template and --separate-git-dir (path-taking / hook-installing options).


Reported by zx (Jace) — GitHub: @manus-use


{
  "affected": [
    {
      "ecosystem_specific": {
        "fix": null,
        "range_state": "affected",
        "resource": "gitpython",
        "resource_purl": "pkg:pypi/gitpython@3.1.50",
        "upstream_fixed_in": "3.1.58"
      },
      "package": {
        "ecosystem": "Homebrew",
        "name": "cobo-cli",
        "purl": "pkg:brew/cobo-cli"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.1.8_7"
            },
            {
              "introduced": "0.1.10"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "database_specific": {
    "confidence": "high",
    "source": "matched",
    "strategy": "registry",
    "upstream_evidence": [
      {
        "ecosystem": "PyPI",
        "key": "pkg:pypi/gitpython@3.1.50",
        "name": "gitpython",
        "resource": "gitpython",
        "strategy": "registry",
        "subject_version": "3.1.50"
      }
    ]
  },
  "details": "## Summary\n`Repo.init()` forwards `**kwargs` verbatim to `git init` with no unsafe-option guard and no `allow_unsafe_options` parameter. `git init --template=\u003cdir\u003e` copies `\u003cdir\u003e/hooks/*` into the new repo\u0027s `.git/hooks`, so an attacker-controlled `template` kwarg plants a hook that executes on the next git operation \u2192 arbitrary code execution. `--template` is already recognized as unsafe for clone (it is on `unsafe_git_clone_options`, and GHSA-6p8h-3wgx-97gf covers the clone path), but `Repo.init` is a distinct method that never received a guard and needs an independent fix.\n\n## Root Cause\n`Repo.init(path, mkdir, odbt, expand_vars, **kwargs)` is a bare `git.init(**kwargs)` (git/repo/base.py:1435) with no `check_unsafe_options` and no `allow_unsafe_options`.\n\n## Impact\nArbitrary code execution (hook fires on next git op) at the privileges of the host process. Two preconditions raise attack complexity (AC:H): the app must forward a `template=` kwarg (KEY control) AND the attacker must stage an executable hook directory at a known path \u2014 the same profile GHSA-6p8h-3wgx-97gf accepted as HIGH for the clone path. Default `allow_unsafe_options` is irrelevant here because `Repo.init` has no guard at all.\n\n## Proof of Concept\n```python\n# attacker stages /evil/hooks/post-commit (executable)\nfrom git import Repo\nRepo.init(path, template=\"/evil\")\n# next commit runs /evil/hooks/post-commit -\u003e ACE\n```\n\n## Attack Chain\n1. Entry: attacker stages `/evil/hooks/post-commit` (executable) and gets the app to call `Repo.init(path, template=\u0027/evil\u0027)`.\n2. Check: NONE on `Repo.init`. Bypass proof: base.py:1435 is a bare `git.init(**kwargs)`. argv (observed): `[\u0027git\u0027,\u0027init\u0027,\u0027--template=/evil\u0027]`.\n3. Sink: git copies `/evil/hooks/post-commit` \u2192 `\u003crepo\u003e/.git/hooks/post-commit`.\n4. Impact: next commit runs the hook \u2192 arbitrary code execution.\n\n## Bypass Evidence\nIndependently reproduced (gate harness): `Repo.init(dst, template=\u0027\u003cevil\u003e\u0027)` \u2192 argv `[\u0027git\u0027,\u0027init\u0027,\u0027--template=\u003cevil\u003e\u0027]` unguarded; hook copied into `.git/hooks/post-commit`; after `git commit` the `INIT_ACE` marker was created. `--separate-git-dir=\u003cpath\u003e` is a parallel arbitrary-redirect vector through the same unguarded sink (value control only).\n\n## Affected Versions\n`GitPython \u003c= 3.1.57` (unguarded `git.init(**kwargs)` present verbatim on the latest release tag).\n\n## Suggested Fix\nAdd a `check_unsafe_options` guard (with an `allow_unsafe_options` parameter) to `Repo.init`, consulting a denylist that includes `--template` and `--separate-git-dir` (path-taking / hook-installing options).\n\n---\nReported by **zx (Jace)** \u2014 GitHub: @manus-use",
  "id": "BREW-cobo-cli-CVE-2026-76218",
  "modified": "2026-09-10T19:01:17Z",
  "published": "2026-08-20T08:43:30Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-9rj7-rf2p-w77r"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-76218"
    },
    {
      "type": "WEB",
      "url": "https://github.com/gitpython-developers/GitPython/pull/2204"
    },
    {
      "type": "WEB",
      "url": "https://github.com/gitpython-developers/GitPython/commit/d9ddb55bdc66"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/gitpython-developers/GitPython"
    },
    {
      "type": "WEB",
      "url": "https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/gitpython-before-remote-code-execution-via-repo-init"
    }
  ],
  "schema_version": "1.7.3",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "GitPython: Unguarded git option forwarding in Repo.init enables arbitrary command execution via --template clone hooks",
  "upstream": [
    "GHSA-9rj7-rf2p-w77r",
    "CVE-2026-76218",
    "PYSEC-2026-3840"
  ]
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…