all:
  children:
    zuul_unreachable:
      hosts: {}
  hosts:
    debian-bookworm:
      ansible_connection: ssh
      ansible_host: 2a13:1a81:8000:3124:f816:3eff:fe9c:8a78
      ansible_port: 22
      ansible_python_interpreter: auto
      ansible_user: zuul
      nodepool:
        az: nova
        cloud: regiocloud-a-ci
        external_id: 691a46e1-2bb5-4e09-99bb-7fd5019a0589
        host_id: 4ba4344415ca7057d9956ea5de826bbc0b830981e82c0e0f191fa07b
        interface_ip: 2a13:1a81:8000:3124:f816:3eff:fe9c:8a78
        label: debian-bookworm
        node_properties: {}
        private_ipv4: 10.128.7.130
        private_ipv6: null
        provider: regiocloud-a
        public_ipv4: 81.163.192.132
        public_ipv6: 2a13:1a81:8000:3124:f816:3eff:fe9c:8a78
        region: null
        slot: null
  vars:
    zuul:
      _inheritance_path:
      - '<Job base explicit: None implied: {MatchAny:{ImpliedBranchMatcher:main}}
        source: osism/zuul-config/zuul.d/jobs.yaml@main#2>'
      - '<Job mypy explicit: None implied: {MatchAny:{ImpliedBranchMatcher:main}}
        source: osism/zuul-jobs/.zuul.yaml@main#42>'
      - '<Job mypy explicit: None implied: None source: osism/python-osism/.zuul.yaml@main#143>'
      ansible_version: '9'
      attempts: 1
      branch: main
      build: 7f1acc74191f4b5bb7089398b257758c
      build_refs:
      - branch: main
        change: '2587'
        change_message: "chore(deps): update dependency gitpython to v3.1.58 [security]\n\nThis
          PR contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/)
          | [Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n|
          [GitPython](https://redirect.github.com/gitpython-developers/GitPython)
          | `==3.1.57` \u2192 `==3.1.58` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/gitpython/3.1.58?slim=true)
          | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/gitpython/3.1.57/3.1.58?slim=true)
          |\n\n---\n\n### GitPython: Unguarded git read-tree option forwarding in
          IndexFile.from_tree/reset/merge_tree enables arbitrary file overwrite\n[GHSA-4gmw-gg2m-w46p](https://redirect.github.com/advisories/GHSA-4gmw-gg2m-w46p)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\n`IndexFile.from_tree`,
          `IndexFile.reset` (\u2192 from_tree) and `IndexFile.merge_tree` append caller-influenced
          treeish strings positionally to `git read-tree` with no unsafe-option guard,
          no `allow_unsafe_options` parameter, and no `--` separator. `git read-tree
          --index-output=<file>` writes the resulting index to an arbitrary path,
          and last-occurrence-wins lets an injected `--index-output` override the
          method's internal temp path \u2014 clobbering an arbitrary file with a valid
          git-index blob. This is a distinct, never-guarded sink: commit `3af0c251`
          (GHSA-3f7w-8rr8-f37f) guarded only `checkout_index` and `tag`; `read_tree`
          was left unprotected (it is among the acknowledged unguarded call sites
          in that advisory's sweep but was never reported or fixed).\n\n##### Root
          Cause\n`from_tree` (index/base.py:388), `reset` (delegates to from_tree),
          and `merge_tree` (index/base.py:291) call `repo.git.read_tree(*arg_list)`
          with no `check_unsafe_options` and no `--`. The treeish is caller-influenced
          and positional.\n\n##### Impact\nArbitrary file overwrite / destruction
          at the privileges of the host process. Content is constrained to a git-index
          blob (not attacker-chosen, so not RCE), but the target path is fully attacker-controlled
          \u2014 corrupting/truncating configs or destroying files at attacker-chosen
          writable locations = I:H + A:H (per the skill's \"overwrite-any-path = I:H\"
          rule). Pure VALUE control (positional treeish). Default configuration.\n\n#####
          Proof of Concept\n```python\nIndexFile.from_tree(repo, \"--index-output=/home/victim/.bashrc\")\n\n#####
          target overwritten with a valid git-index blob (DIRC...)\n```\n\n##### Attack
          Chain\n1. Entry: app calls `IndexFile.from_tree(repo, treeish)` / `reset(commit=\u2026)`
          / `merge_tree(base=\u2026, rhs=\u2026)` with attacker `treeish=\"--index-output=/home/victim/.bashrc\"`.\n2.
          Check: NONE \u2014 the methods have no `allow_unsafe_options` and never
          call `check_unsafe_options`.\n3. Sink: `repo.git.read_tree(*arg_list)` \u2014
          no `--`. argv (from_tree, observed): `['git','read-tree','--index-output=<tmp>','--index-output=/\u2026/victim']`
          (last-wins).\n4. Impact: target path created/overwritten with a valid git-index
          blob; existing content destroyed.\n\n##### Bypass Evidence\nIndependently
          reproduced (gate harness): `IndexFile.from_tree(repo,'--index-output=<victim>')`
          \u2192 victim overwritten; before=`IMPORTANT ORIGINAL CONTENT`, after starts
          `DIRC\\x00\\x00\\x00\\x02\u2026` (destructive clobber, valid index blob).
          `reset(commit=\u2026)` and both `merge_tree` positionals verified. Fix-commit
          read: `3af0c251` touched only `checkout_index`+`tag`; `read_tree` untouched
          on HEAD.\n\n##### Affected Versions\n`GitPython <= 3.1.57` (sinks present
          verbatim on the latest release tag).\n\n##### Suggested Fix\nAdd a `check_unsafe_options`
          guard (with an `allow_unsafe_options` parameter) to `from_tree`/`reset`/`merge_tree`,
          and/or place a `--` separator before the positional treeish arguments; block
          `--index-output` (a path-taking option) on this sink.\n\n---\nReported by
          **zx (Jace)** \u2014 GitHub: @&#8203;manus-use\n\n#### Severity\n- CVSS
          Score: 8.1 / 10 (High)\n- Vector String: `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H`\n\n####
          References\n- [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-4gmw-gg2m-w46p](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-4gmw-gg2m-w46p)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
          [https://github.com/gitpython-developers/GitPython/commit/9b5dcaf85da5946dbf69dcd53f9edba08f760b32](https://redirect.github.com/gitpython-developers/GitPython/commit/9b5dcaf85da5946dbf69dcd53f9edba08f760b32)\n-
          [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
          [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-4gmw-gg2m-w46p)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          GitPython: Unguarded git option forwarding in Repo.init enables arbitrary
          command execution via --template clone hooks\n[GHSA-9rj7-rf2p-w77r](https://redirect.github.com/advisories/GHSA-9rj7-rf2p-w77r)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\n`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 \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\n#####
          attacker stages /evil/hooks/post-commit (executable)\nfrom git import Repo\nRepo.init(path,
          template=\"/evil\")\n\n##### next commit runs /evil/hooks/post-commit ->
          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='/evil')`.\n2.
          Check: NONE on `Repo.init`. Bypass proof: base.py:1435 is a bare `git.init(**kwargs)`.
          argv (observed): `['git','init','--template=/evil']`.\n3. Sink: git copies
          `/evil/hooks/post-commit` \u2192 `<repo>/.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='<evil>')`
          \u2192 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).\n\n##### Affected
          Versions\n`GitPython <= 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:
          @&#8203;manus-use\n\n#### Severity\n- CVSS Score: 7.5 / 10 (High)\n- Vector
          String: `CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H`\n\n#### References\n-
          [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-9rj7-rf2p-w77r](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-9rj7-rf2p-w77r)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
          [https://github.com/gitpython-developers/GitPython/commit/d9ddb55bdc66](https://redirect.github.com/gitpython-developers/GitPython/commit/d9ddb55bdc66)\n-
          [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
          [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-9rj7-rf2p-w77r)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          GitPython: Arbitrary file read via --pathspec-from-file in IndexFile.remove()
          and Head.checkout()\n[GHSA-hh9p-6wh2-4mfc](https://redirect.github.com/advisories/GHSA-hh9p-6wh2-4mfc)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\n\n`IndexFile.remove()`
          and `Head.checkout()` forward `**kwargs` into `git rm` and `git checkout`\nwith
          no guard. Passing `--pathspec-from-file=<file>` **together with `--pathspec-file-nul`**\nmakes
          Git treat the whole file as a single NUL-delimited pathspec, and the unmatched-pathspec\nerror
          quotes it verbatim. GitPython surfaces that through `GitCommandError.stderr`,
          so the\nentire contents of a caller-chosen file are returned to the caller
          in band.\n\nThis is the same primitive as Instance 2 of\n[GHSA-3f7w-8rr8-f37f](https://redirect.github.com/advisories/GHSA-3f7w-8rr8-f37f)
          - `TagReference.create()`\nwith `-F`, arbitrary file read returned in band
          - at two sites that advisory assessed and\ncleared.\n\n##### Prior art,
          and why I am filing rather than commenting\n\nGHSA-3f7w-8rr8-f37f's sweep
          table lists these four sites with the assessment\n*\"`--pathspec-from-file`
          only reads a pathspec; no write or disclosure primitive found\"*:\n\n| Call
          site | git command | that advisory's assessment |\n|---|---|---|\n| `IndexFile.remove()`
          | `rm` | `--pathspec-from-file` only reads a pathspec; no write or disclosure
          primitive found |\n| `IndexFile.move()` | `mv` | same |\n| `HEAD.reset()`
          | `reset` | same |\n| `HEAD.checkout()` | `checkout` | same |\n\nThat assessment
          is very nearly right, and I think that is why it held: with\n`--pathspec-from-file`
          alone, Git splits on newlines and the error quotes only the **first\nline**,
          which reads as an uninteresting partial. Adding `--pathspec-file-nul` -
          a sibling flag\nof the same option, and the documented way to handle paths
          containing newlines - makes the\nwhole file one pathspec.\n\n##### Root
          cause\n\n`git/index/base.py:991-1043`:\n\n```python\ndef remove(self, items,
          working_tree=False, **kwargs):\n    ...\n    removed_paths = self.repo.git.rm(args,
          paths, **kwargs).splitlines()   # line 1043\n```\n\n`git/refs/head.py:237-268`:\n\n```python\ndef
          checkout(self, force: bool = False, **kwargs: Any):\n    ...\n    self.repo.git.checkout(self,
          **kwargs)                                 # line 268\n```\n\nNeither has
          an `allow_unsafe_options` parameter or a `check_unsafe_options()` call.\n\n#####
          Proof of concept\n\n```python\nfrom git import Repo\nfrom git.exc import
          GitCommandError\n\nrepo = Repo(\"/path/to/repo\")\nkw = dict(pathspec_from_file=\"/etc/passwd\",
          pathspec_file_nul=True)\n\ntry:\n    repo.index.remove([], **kw)          #
          or: repo.heads[0].checkout(**kw)\nexcept GitCommandError as e:\n    print(e.stderr)
          \                     # <- entire file contents\n```\n\nObserved on published
          3.1.57, against a canary file holding three marked lines:\n\n```\n[PASS]
          IndexFile.remove() -> `git rm` returns ALL 3 canary lines in-band\n       stderr:
          'fatal: pathspec 'LINE1-CANARY-4242\n       LINE2-SECRET-7777\n       LINE3-TAIL-9999\n
          \      ' did not match any files'\n[PASS] Head.checkout() -> `git checkout`
          returns ALL 3 canary lines in-band\n       stderr: 'error: pathspec 'LINE1-CANARY-4242\n
          \      LINE2-SECRET-7777\n       LINE3-TAIL-9999\n       ' did not match
          any file(s) known to git'\n[PASS] PRECISION: `git status` leaks 0/3 -- not
          every unguarded site discloses\n[PASS] PRECISION: the GUARDED checkout-index
          leaks 0/3\n```\n\nThe two precision controls are there so the result is
          about these sinks and not about the\ncanary being visible everywhere.\n\n#####
          Scope correction to the table above\n\nOf the four sites cleared with that
          sentence, **two disclose and two do not**:\n\n| Call site | disclosed? |\n|---|---|\n|
          `IndexFile.remove()` \u2192 `git rm` | **yes, full file** |\n| `Head.checkout()`
          \u2192 `git checkout` | **yes, full file** |\n| `HEAD.reset()` \u2192 `git
          reset` | no - `git reset` does not error on unmatched pathspecs |\n| `IndexFile.move()`
          \u2192 `git mv` | no |\n\nThe two negatives are mentioned because \"the
          dismissal was wrong\" would overstate it: the\ndismissal was wrong for half
          of what it covered.\n\n#### Severity\n- CVSS Score: 6.5 / 10 (Medium)\n-
          Vector String: `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N`\n\n#### References\n-
          [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-hh9p-6wh2-4mfc](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-hh9p-6wh2-4mfc)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
          [https://github.com/gitpython-developers/GitPython/commit/f2550b65bf60ca087190981e2c7b6865e201f40c](https://redirect.github.com/gitpython-developers/GitPython/commit/f2550b65bf60ca087190981e2c7b6865e201f40c)\n-
          [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
          [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-hh9p-6wh2-4mfc)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          GitPython: Arbitrary Git Repository Creation Outside the Working Tree via
          Unvalidated .gitmodules Submodule Name in GitPython\n[GHSA-hmq2-w58f-27jc](https://redirect.github.com/advisories/GHSA-hmq2-w58f-27jc)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\nGitPython computes
          the on-disk location of a submodule's separate Git directory (`.git/modules/<name>`)
          from the submodule's `.gitmodules` section name with no validation. Because
          that name is fully attacker-controlled content of a cloned repository, a
          malicious repository can set a submodule name to a traversal string (e.g.
          `../../../../home/victim/.something`) and cause GitPython to create and
          initialize a full Git repository at an attacker-chosen filesystem path outside
          the intended clone directory. The only precondition is that a victim clones
          the malicious repository with GitPython and runs submodule initialization
          (`submodule_update(init=True)` / `sm.update(init=True)`), a very common
          and often automatic step. Core Git itself already blocks this exact attack
          class (CVE-2018-11235), but GitPython's independent reimplementation never
          adopted an equivalent check.\n\n##### Details\n`src/GitPython/git/objects/submodule/util.py`
          `sm_name()` strips the `submodule \"` / `\"` wrapper from a `.gitmodules`
          `[submodule \"...\"]` header and returns the result unchecked. `Submodule.iter_items()`
          in `src/GitPython/git/objects/submodule/base.py` reads this via `sm_name(sms)`
          and assigns it to `sm._name`; unlike the submodule `path`, `name` is never
          used for a tree lookup, so it is never implicitly validated. `Submodule._module_abspath()`
          then builds `osp.join(parent_repo.git_dir, \"modules\", name)` - `os.path.join`
          does not normalize `../` sequences. `Submodule._clone_repo()` passes this
          value straight to `os.makedirs()` and to `git clone --separate-git-dir=<module_abspath>`,
          creating and populating a full Git repository (objects, refs, hooks, config)
          at the escaped path. Attack prerequisite: attacker controls a repository
          the victim clones and initializes submodules for.\n\n##### PoC\n1. Environment:
          Docker image built `FROM python:3.11-slim`, with `git` installed via `apt-get
          install -y git` (Debian bookworm packaged version, described in the advisory
          as \"git 2.x\"; the host-side verification separately used system git `2.34.1`,
          but no exact version is pinned for the git binary inside this Docker image).
          GitPython is installed inside the container via `pip install /src/GitPython`
          from this repository's own source, which the advisory states resolved to
          the officially released `GitPython==3.1.57` and `gitdb==4.0.12`.\n2. Configuration
          / preconditions: None beyond what's described - the victim must clone the
          attacker's repository with GitPython and run submodule initialization (`repo.submodules`
          + `sm.update(init=True)`, equivalent to `git submodule update --init`).\n3.
          Commands run (quoted verbatim from the advisory's \"Confirmed test run\"
          section):\n```bash\n$ docker build -f GHSA/testing/Dockerfile -t ghsa-gitpython-poc
          .\n$ docker run --rm ghsa-gitpython-poc\n```\n(Per the Dockerfile, `docker
          run` executes `/work/run_all.sh`, which in turn runs `build_attacker_repo.sh`,
          then `poc_gitpython.py`, then `poc_control_realgit.sh`.)\n4. Full source
          of the PoC script (`GHSA/testing/poc_gitpython.py`), verbatim:\n```python\n\"\"\"GHSA-001
          PoC: GitPython side.\n\nClones the attacker repo and runs the equivalent
          of\n`git submodule update --init` via GitPython, then checks whether a git\nrepository
          was created outside the clone directory.\n\"\"\"\nimport os\nimport shutil\n\nimport
          git\n\nCLONE_DIR = '/work/victim_clone/repo'\nESCAPE_TARGET = '/tmp/gitpython_poc_escaped_root'\n\ndef
          main():\n    shutil.rmtree(os.path.dirname(CLONE_DIR), ignore_errors=True)\n
          \   shutil.rmtree(ESCAPE_TARGET, ignore_errors=True)\n    os.makedirs(os.path.dirname(CLONE_DIR),
          exist_ok=True)\n\n    print(f'GitPython version: {git.__version__}')\n    repo
          = git.Repo.clone_from('/work/attacker_repo', CLONE_DIR)\n    print('Cloned
          into:', repo.working_tree_dir)\n\n    sms = list(repo.submodules)\n    for
          sm in sms:\n        print('  submodule name:', repr(sm.name))\n        print('
          \ submodule path:', repr(sm.path))\n\n    print('escape_target exists before
          update:', os.path.exists(ESCAPE_TARGET))\n\n    for sm in sms:\n        try:\n
          \           sm.update(init=True)\n        except Exception as e:\n            print('sm.update
          raised:', repr(e))\n\n    exists = os.path.exists(ESCAPE_TARGET)\n    print('escape_target
          exists after update:', exists)\n    if exists:\n        print('escape_target
          contents:', os.listdir(ESCAPE_TARGET))\n\n    print('POC_RESULT=VULNERABLE'
          if exists else 'POC_RESULT=SAFE')\n\nif __name__ == '__main__':\n    main()\n```\n5.
          Exact captured terminal output (verbatim, from the original advisory's \"Confirmed
          test run (Docker, released package)\" section):\n```\n=== GitPython PoC
          (vulnerable path) ===\nGitPython version: 3.1.57\nCloned into: /work/victim_clone/repo\n
          \ submodule name: '../../../../../../tmp/gitpython_poc_escaped_root/modules_dir'\n
          \ submodule path: 'legit_dir'\nescape_target exists before update: False\nescape_target
          exists after update: True\nescape_target contents: ['modules_dir']\nPOC_RESULT=VULNERABLE\n\n===
          Control: real git CLI on identical repo ===\nwarning: ignoring suspicious
          submodule name: ../../../../../../tmp/gitpython_poc_escaped_root/modules_dir\nwarning:
          ignoring suspicious submodule name: ../../../../../../tmp/gitpython_poc_escaped_root/modules_dir\nfatal:
          No url found for submodule path 'legit_dir' in .gitmodules\nCONTROL_RESULT=SAFE
          (real git correctly refused)\n```\n6. Payload: the attacker rewrites the
          `.gitmodules` section header from `[submodule \"legit_dir\"]` to `[submodule
          \"../../../../../../tmp/gitpython_poc_escaped_root/modules_dir\"]` (built
          by `build_attacker_repo.sh`, part of the harness in `GHSA/testing/`). The
          malicious part is the `../../../../../../` traversal sequence embedded in
          the submodule *name* (not the tree-validated `path`), which becomes the
          on-disk target for the submodule's separate git directory.\n7. Expected
          vs. observed: A safe implementation (as demonstrated by the real `git` CLI
          control run) rejects the submodule name with \"ignoring suspicious submodule
          name\" and refuses to create anything outside the repository. GitPython
          instead created the escape-target directory and a fully-initialized Git
          repository at `/tmp/gitpython_poc_escaped_root/modules_dir`, confirmed by
          `escape_target exists after update: True` and its listed contents.\n8. Security
          impact demonstrated: arbitrary filesystem directory and Git-repository creation
          at an attacker-chosen absolute path outside the victim's intended clone
          directory, populated with attacker-controlled content sourced from the submodule's
          own (also attacker-controlled) `url`.\n\n##### Impact\nPath traversal (CWE-22)
          / external control of file path (CWE-73) leading to arbitrary directory
          and Git-repository creation outside the intended clone directory. Integrity
          impact is High (attacker chooses destination path and, via the submodule
          URL, much of the written content); Confidentiality impact is None (only
          creation was demonstrated); Availability impact is Low-Medium (disk-exhaustion
          potential). No authentication is required; the attacker only needs to control
          a repository the victim clones and initializes submodules for - a routine,
          often fully-automatic operation in CI pipelines, IDE integrations, and dependency-management
          tooling.\n\n#### Severity\n- CVSS Score: 8.2 / 10 (High)\n- Vector String:
          `CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:N/I:H/A:L`\n\n#### References\n- [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-hmq2-w58f-27jc](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-hmq2-w58f-27jc)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2202](https://redirect.github.com/gitpython-developers/GitPython/pull/2202)\n-
          [https://github.com/gitpython-developers/GitPython/commit/4299c990e1ca21896f9485277caf7bb0ae5b404c](https://redirect.github.com/gitpython-developers/GitPython/commit/4299c990e1ca21896f9485277caf7bb0ae5b404c)\n-
          [https://github.com/gitpython-developers/GitPython/commit/e4b8e7d026ca6abb4cf604f8e77093432ce23c06](https://redirect.github.com/gitpython-developers/GitPython/commit/e4b8e7d026ca6abb4cf604f8e77093432ce23c06)\n-
          [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
          [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-hmq2-w58f-27jc)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          GitPython: git-config OPTION-name injection via =/#/whitespace bypasses
          name validator, enabling forged core.sshCommand/hooksPath (RCE)\n[GHSA-jm78-9fvv-mhgr](https://redirect.github.com/advisories/GHSA-jm78-9fvv-mhgr)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\nGitPython's config-name
          validator only neutralizes CR/LF/NUL for the `\"option\"` label; it does
          not reject `=`, `#`, `;`, `[`, `]`, or whitespace in an **option name**.
          `write_section` writes the option name verbatim into the config file, so
          an option name such as `sshCommand = touch <cmd> #` is written as `\\tsshCommand
          = touch <cmd> # = <value>`, which git parses as `core.sshCommand = touch
          <cmd>` (the trailing `#` comments out the intended value). This forges arbitrary
          config directives (`core.sshCommand`, `core.hooksPath`, `alias.*`) \u2192
          RCE on the next git operation. This is a distinct field (option name, not
          section name) and distinct character class (`=`/`#`/space, not newline/bracket)
          from GHSA-3rp5-jjmw-4wv2 (section-name bracket injection) and GHSA-mv93-w799-cj2w
          / GHSA-v87r-6q3f-2j67 (newline injection).\n\n##### Root Cause\n`_assure_config_name_safe(name,
          label)` (`git/config.py:897`) applies the bracket/quote state machine ONLY
          when `label == \"section\"`; for the `\"option\"` label it falls through
          with just the `UNSAFE_CONFIG_CHARS_RE = [\\r\\n\\x00]` regex. `write_section`
          then writes the option name verbatim into `\"\\t%s = %s\\n\"` (config.py:702).\n\n#####
          Impact\nArbitrary git-config directive injection \u2192 remote code execution
          via `core.sshCommand` (fires on any ssh git operation, no staged file needed)
          or `core.hooksPath` (with a staged hook). Requires the embedding application
          to forward a caller-influenced OPTION NAME into the config writer (name-control
          model, the same name-control model accepted by the related published advisories
          GHSA-3rp5-jjmw-4wv2 and GHSA-mv93-w799-cj2w). Default configuration.\n\n#####
          Proof of Concept\n```python\nwith repo.config_writer() as cw:\n    cw.set_value(\"core\",
          \"sshCommand = touch /tmp/RCE #\", \"x\")\n\n##### git config --get core.sshCommand
          \ ->  touch /tmp/RCE\n```\n\n##### Attack Chain\n1. Entry: app calls config
          writer with attacker-controlled OPTION name: `set_value(\"core\", \"sshCommand
          = touch /tmp/RCE #\", \"x\")`.\n2. Check: `_assure_config_name_safe(option,
          \"option\")` @&#8203; config.py. Guard: regex matches only `[\\r\\n\\x00]`;
          bracket/quote state machine is gated on `label==\"section\"`. Bypass proof:
          `=`,`#`,space pass \u2192 no `ValueError`.\n3. Sink: `write_section` writes
          `\"\\tsshCommand = touch /tmp/RCE # = x\\n\"` (config.py:702).\n4. Impact:
          git parses `core.sshCommand=touch /tmp/RCE` \u2192 arbitrary code execution
          on next git op.\n\n##### Bypass Evidence\nIndependently reproduced (gate
          harness): `set_value('core','sshCommand = touch <RCE> #','x')` \u2192 no
          `ValueError`; file line `sshCommand = touch <RCE> # = x`; `git config --get
          core.sshCommand` \u2192 `touch <RCE>` (rc=0). Also verified `core.hooksPath`
          via both `GitConfigParser` and `repo.config_writer()`. Fix-commit read:
          bracket/quote checks are inside `if label == \"section\"`; the `\"option\"`
          label is not covered.\n\n##### Affected Versions\n`GitPython <= 3.1.57`
          (validator present verbatim on the latest release tag).\n\n##### Suggested
          Fix\nApply the section-name safety checks (reject `=`, `#`, `;`, `[`, `]`,
          whitespace) to the `\"option\"` label as well, or validate the fully-rendered
          config line after substitution.\n\n---\nReported by **zx (Jace)** \u2014
          GitHub: @&#8203;manus-use\n\n#### Severity\n- CVSS Score: 8.8 / 10 (High)\n-
          Vector String: `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H`\n\n#### References\n-
          [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-jm78-9fvv-mhgr](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-jm78-9fvv-mhgr)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
          [https://github.com/gitpython-developers/GitPython/commit/a495ccd3b547ccd60b2187215823b72a9c0188bf](https://redirect.github.com/gitpython-developers/GitPython/commit/a495ccd3b547ccd60b2187215823b72a9c0188bf)\n-
          [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
          [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-jm78-9fvv-mhgr)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          GitPython: Unsafe git option guard bypass via split_single_char_options=False
          short-option token smuggling enables command execution\n[GHSA-wvpp-8hx9-p66j](https://redirect.github.com/advisories/GHSA-wvpp-8hx9-p66j)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\nThe `check_unsafe_options`
          guard can be bypassed on every guarded method (clone/clone_from, fetch/pull/push,
          ls_remote, iter_commits, blame, archive) by combining a single-character
          kwarg with `split_single_char_options=False`. The guard's candidate list
          omits the smuggled option, but `transform_kwarg` emits a JOINED `-n<value>`
          argv token that git parses as `--upload-pack=<cmd>`, yielding arbitrary
          command execution at the default `allow_unsafe_options=False`. This is an
          incomplete-fix bypass of commit `e8d0fbf7` (the fix for GHSA-r9mr-m37c-5fr3),
          which only emits value-derived candidates when `split_single_char_options`
          is True.\n\n##### Root Cause\n`_option_candidates` derives value-token candidates
          only under `if len(key)==1 and split_single_char_options:` (cmd.py:1048,
          added by `e8d0fbf7`). With `split_single_char_options=False`, `_option_candidates([],
          {\"n\":\"utouch <cmd>;git-upload-pack\"})` returns only `['-n']` (not on
          the denylist), so the guard passes. But `transform_kwarg('n', value, split_single_char_options=False)`
          emits the JOINED token `-nutouch <cmd>;git-upload-pack` (cmd.py:1631). git
          clusters value-less short flags then parses `-u<cmd>` = `--upload-pack=<cmd>`
          \u2192 command execution. The hardened guard WOULD block the joined token
          if it saw it \u2014 the flaw is it never receives it.\n\n##### Impact\nArbitrary
          OS command execution as the host process (via `--upload-pack`) at default
          `allow_unsafe_options=False`, affecting all guarded methods that forward
          kwargs. Precondition: the app forwards a user-controlled kwargs dict containing
          `split_single_char_options=False` plus a single-char key (same user-dict-forwarding
          model GHSA-r9mr-m37c-5fr3 accepts).\n\n##### Proof of Concept\n```python\nfrom
          git import Repo\nRepo.clone_from(src, dst,\n    n=\"utouch /tmp/ACE;git-upload-pack\",\n
          \   split_single_char_options=False)   # /tmp/ACE created -> ACE\n```\n\n#####
          Attack Chain\n1. Entry: app forwards user kwargs to `Repo.clone_from(url,
          path, **kwargs)`: `{split_single_char_options: False, n: 'utouch /tmp/ACE;git-upload-pack'}`.\n2.
          Check: `check_unsafe_options(_option_candidates([], kwargs), unsafe_git_clone_options)`.
          Guard: denylist includes `--upload-pack`/`-u`. Bypass proof: `_option_candidates`
          yields only `['-n']` (value token skipped because `split=False`); guard
          never sees `-u`.\n3. Sink: `transform_kwarg` emits joined token (cmd.py:1631).
          argv (observed): `['git','clone','-v','-nutouch /tmp/ACE;git-upload-pack','--','<src>','<dst>']`.\n4.
          Impact: git clusters `-n` + `-u<cmd>` \u2192 runs upload-pack command \u2192
          ACE.\n\n##### Bypass Evidence\nIndependently reproduced (gate harness, default
          `allow_unsafe_options=False`): the `split=False` payload created the marker
          `VH05_GATE_ACE` (ACE); the clone returned normally (guard bypassed). Control:
          `n='--upload-pack=\u2026'` (split default True) \u2192 `UnsafeOptionError:
          --upload-pack is not allowed`. Fix-commit read: `e8d0fbf7` extends candidates
          only under `if len(key)==1 and split_single_char_options:` \u2014 split=False
          skips value emission. Also confirmed the earlier clustering-parse fix (commit
          `56806080`) does not cover this because the guard only ever receives `['-n']`.\n\n#####
          Affected Versions\n`GitPython <= 3.1.57` (code present verbatim on the latest
          release tag).\n\n##### Suggested Fix\nMake `_option_candidates` emit value-derived
          candidates regardless of `split_single_char_options` (i.e. also for the
          joined `-n<value>` form), OR run `check_unsafe_options` over the fully-transformed
          argv rather than the reconstructed name-only candidate list.\n\n---\nReported
          by **zx (Jace)** \u2014 GitHub: @&#8203;manus-use\n\n#### Severity\n- CVSS
          Score: 8.8 / 10 (High)\n- Vector String: `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H`\n\n####
          References\n- [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-wvpp-8hx9-p66j](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-wvpp-8hx9-p66j)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
          [https://github.com/gitpython-developers/GitPython/commit/96a888f4d782cb2f80452148e48e60ce4af6d541](https://redirect.github.com/gitpython-developers/GitPython/commit/96a888f4d782cb2f80452148e48e60ce4af6d541)\n-
          [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
          [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-wvpp-8hx9-p66j)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          Release Notes\n\n<details>\n<summary>gitpython-developers/GitPython (GitPython)</summary>\n\n###
          [`v3.1.58`](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58):
          Security and Fixes\n\n[Compare Source](https://redirect.github.com/gitpython-developers/GitPython/compare/3.1.57...3.1.58)\n\n#####
          What's Changed\n\n- test: allow Python startup before timeout by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2195](https://redirect.github.com/gitpython-developers/GitPython/pull/2195)\n-
          Resolve Windows hook Bash through PATH by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2199](https://redirect.github.com/gitpython-developers/GitPython/pull/2199)\n-
          Revert \"Resolve Windows hook Bash through PATH\" by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2200](https://redirect.github.com/gitpython-developers/GitPython/pull/2200)\n-
          test: focus pytest summary on unexpected failures by [@&#8203;raisulchowdhury](https://redirect.github.com/raisulchowdhury)
          in [#&#8203;2203](https://redirect.github.com/gitpython-developers/GitPython/pull/2203)\n-
          Validate submodule names before filesystem operations by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2202](https://redirect.github.com/gitpython-developers/GitPython/pull/2202)\n-
          Handle invalid submodule names during recursive updates by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2205](https://redirect.github.com/gitpython-developers/GitPython/pull/2205)\n-
          Fix Windows path handling on Python 3.13+ by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2196](https://redirect.github.com/gitpython-developers/GitPython/pull/2196)\n-
          fixup 2202 by [@&#8203;Byron](https://redirect.github.com/Byron) in [#&#8203;2206](https://redirect.github.com/gitpython-developers/GitPython/pull/2206)\n-
          Correct Windows hook Bash precedence by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2201](https://redirect.github.com/gitpython-developers/GitPython/pull/2201)\n-
          Harden config and Git option validation by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
          Skip tests that need symlink privileges instead of erroring by [@&#8203;Cyrus580529](https://redirect.github.com/Cyrus580529)
          in [#&#8203;2197](https://redirect.github.com/gitpython-developers/GitPython/pull/2197)\n\n#####
          New Contributors\n\n- [@&#8203;raisulchowdhury](https://redirect.github.com/raisulchowdhury)
          made their first contribution in [#&#8203;2203](https://redirect.github.com/gitpython-developers/GitPython/pull/2203)\n-
          [@&#8203;Cyrus580529](https://redirect.github.com/Cyrus580529) made their
          first contribution in [#&#8203;2197](https://redirect.github.com/gitpython-developers/GitPython/pull/2197)\n\n**Full
          Changelog**: <https://github.com/gitpython-developers/GitPython/compare/3.1.57...3.1.58>\n\n</details>\n\n---\n\n###
          Configuration\n\n\U0001F4C5 **Schedule**: (UTC)\n\n- Branch creation\n  -
          At any time (no schedule defined)\n- Automerge\n  - At any time (no schedule
          defined)\n\n\U0001F6A6 **Automerge**: Disabled by config. Please merge this
          manually once you are satisfied.\n\n\u267B **Rebasing**: Whenever PR becomes
          conflicted, or you tick the rebase/retry checkbox.\n\n\U0001F515 **Ignore**:
          Close this PR and you won't be reminded about these updates again.\n\n---\n\n
          - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this
          box\n\n---\n\nThis PR was generated by [Mend Renovate](https://mend.io/renovate/).
          View the [repository job log](https://developer.mend.io/github/osism/python-osism).\n<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMi4wIiwidXBkYXRlZEluVmVyIjoiNDQuMTIuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsicmVub3ZhdGUiXX0=-->\n"
        change_url: https://github.com/osism/python-osism/pull/2587
        commit_id: 8f8d2989b17d7199dea1d0770f90e6edaa6b261f
        patchset: 8f8d2989b17d7199dea1d0770f90e6edaa6b261f
        project:
          canonical_hostname: github.com
          canonical_name: github.com/osism/python-osism
          name: osism/python-osism
          short_name: python-osism
        src_dir: src/github.com/osism/python-osism
        topic: null
      buildset: f68017e6009747ba9d06de3c2196fa4f
      buildset_refs:
      - branch: main
        change: '2587'
        change_message: "chore(deps): update dependency gitpython to v3.1.58 [security]\n\nThis
          PR contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/)
          | [Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n|
          [GitPython](https://redirect.github.com/gitpython-developers/GitPython)
          | `==3.1.57` \u2192 `==3.1.58` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/gitpython/3.1.58?slim=true)
          | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/gitpython/3.1.57/3.1.58?slim=true)
          |\n\n---\n\n### GitPython: Unguarded git read-tree option forwarding in
          IndexFile.from_tree/reset/merge_tree enables arbitrary file overwrite\n[GHSA-4gmw-gg2m-w46p](https://redirect.github.com/advisories/GHSA-4gmw-gg2m-w46p)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\n`IndexFile.from_tree`,
          `IndexFile.reset` (\u2192 from_tree) and `IndexFile.merge_tree` append caller-influenced
          treeish strings positionally to `git read-tree` with no unsafe-option guard,
          no `allow_unsafe_options` parameter, and no `--` separator. `git read-tree
          --index-output=<file>` writes the resulting index to an arbitrary path,
          and last-occurrence-wins lets an injected `--index-output` override the
          method's internal temp path \u2014 clobbering an arbitrary file with a valid
          git-index blob. This is a distinct, never-guarded sink: commit `3af0c251`
          (GHSA-3f7w-8rr8-f37f) guarded only `checkout_index` and `tag`; `read_tree`
          was left unprotected (it is among the acknowledged unguarded call sites
          in that advisory's sweep but was never reported or fixed).\n\n##### Root
          Cause\n`from_tree` (index/base.py:388), `reset` (delegates to from_tree),
          and `merge_tree` (index/base.py:291) call `repo.git.read_tree(*arg_list)`
          with no `check_unsafe_options` and no `--`. The treeish is caller-influenced
          and positional.\n\n##### Impact\nArbitrary file overwrite / destruction
          at the privileges of the host process. Content is constrained to a git-index
          blob (not attacker-chosen, so not RCE), but the target path is fully attacker-controlled
          \u2014 corrupting/truncating configs or destroying files at attacker-chosen
          writable locations = I:H + A:H (per the skill's \"overwrite-any-path = I:H\"
          rule). Pure VALUE control (positional treeish). Default configuration.\n\n#####
          Proof of Concept\n```python\nIndexFile.from_tree(repo, \"--index-output=/home/victim/.bashrc\")\n\n#####
          target overwritten with a valid git-index blob (DIRC...)\n```\n\n##### Attack
          Chain\n1. Entry: app calls `IndexFile.from_tree(repo, treeish)` / `reset(commit=\u2026)`
          / `merge_tree(base=\u2026, rhs=\u2026)` with attacker `treeish=\"--index-output=/home/victim/.bashrc\"`.\n2.
          Check: NONE \u2014 the methods have no `allow_unsafe_options` and never
          call `check_unsafe_options`.\n3. Sink: `repo.git.read_tree(*arg_list)` \u2014
          no `--`. argv (from_tree, observed): `['git','read-tree','--index-output=<tmp>','--index-output=/\u2026/victim']`
          (last-wins).\n4. Impact: target path created/overwritten with a valid git-index
          blob; existing content destroyed.\n\n##### Bypass Evidence\nIndependently
          reproduced (gate harness): `IndexFile.from_tree(repo,'--index-output=<victim>')`
          \u2192 victim overwritten; before=`IMPORTANT ORIGINAL CONTENT`, after starts
          `DIRC\\x00\\x00\\x00\\x02\u2026` (destructive clobber, valid index blob).
          `reset(commit=\u2026)` and both `merge_tree` positionals verified. Fix-commit
          read: `3af0c251` touched only `checkout_index`+`tag`; `read_tree` untouched
          on HEAD.\n\n##### Affected Versions\n`GitPython <= 3.1.57` (sinks present
          verbatim on the latest release tag).\n\n##### Suggested Fix\nAdd a `check_unsafe_options`
          guard (with an `allow_unsafe_options` parameter) to `from_tree`/`reset`/`merge_tree`,
          and/or place a `--` separator before the positional treeish arguments; block
          `--index-output` (a path-taking option) on this sink.\n\n---\nReported by
          **zx (Jace)** \u2014 GitHub: @&#8203;manus-use\n\n#### Severity\n- CVSS
          Score: 8.1 / 10 (High)\n- Vector String: `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H`\n\n####
          References\n- [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-4gmw-gg2m-w46p](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-4gmw-gg2m-w46p)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
          [https://github.com/gitpython-developers/GitPython/commit/9b5dcaf85da5946dbf69dcd53f9edba08f760b32](https://redirect.github.com/gitpython-developers/GitPython/commit/9b5dcaf85da5946dbf69dcd53f9edba08f760b32)\n-
          [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
          [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-4gmw-gg2m-w46p)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          GitPython: Unguarded git option forwarding in Repo.init enables arbitrary
          command execution via --template clone hooks\n[GHSA-9rj7-rf2p-w77r](https://redirect.github.com/advisories/GHSA-9rj7-rf2p-w77r)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\n`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 \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\n#####
          attacker stages /evil/hooks/post-commit (executable)\nfrom git import Repo\nRepo.init(path,
          template=\"/evil\")\n\n##### next commit runs /evil/hooks/post-commit ->
          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='/evil')`.\n2.
          Check: NONE on `Repo.init`. Bypass proof: base.py:1435 is a bare `git.init(**kwargs)`.
          argv (observed): `['git','init','--template=/evil']`.\n3. Sink: git copies
          `/evil/hooks/post-commit` \u2192 `<repo>/.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='<evil>')`
          \u2192 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).\n\n##### Affected
          Versions\n`GitPython <= 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:
          @&#8203;manus-use\n\n#### Severity\n- CVSS Score: 7.5 / 10 (High)\n- Vector
          String: `CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H`\n\n#### References\n-
          [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-9rj7-rf2p-w77r](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-9rj7-rf2p-w77r)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
          [https://github.com/gitpython-developers/GitPython/commit/d9ddb55bdc66](https://redirect.github.com/gitpython-developers/GitPython/commit/d9ddb55bdc66)\n-
          [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
          [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-9rj7-rf2p-w77r)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          GitPython: Arbitrary file read via --pathspec-from-file in IndexFile.remove()
          and Head.checkout()\n[GHSA-hh9p-6wh2-4mfc](https://redirect.github.com/advisories/GHSA-hh9p-6wh2-4mfc)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\n\n`IndexFile.remove()`
          and `Head.checkout()` forward `**kwargs` into `git rm` and `git checkout`\nwith
          no guard. Passing `--pathspec-from-file=<file>` **together with `--pathspec-file-nul`**\nmakes
          Git treat the whole file as a single NUL-delimited pathspec, and the unmatched-pathspec\nerror
          quotes it verbatim. GitPython surfaces that through `GitCommandError.stderr`,
          so the\nentire contents of a caller-chosen file are returned to the caller
          in band.\n\nThis is the same primitive as Instance 2 of\n[GHSA-3f7w-8rr8-f37f](https://redirect.github.com/advisories/GHSA-3f7w-8rr8-f37f)
          - `TagReference.create()`\nwith `-F`, arbitrary file read returned in band
          - at two sites that advisory assessed and\ncleared.\n\n##### Prior art,
          and why I am filing rather than commenting\n\nGHSA-3f7w-8rr8-f37f's sweep
          table lists these four sites with the assessment\n*\"`--pathspec-from-file`
          only reads a pathspec; no write or disclosure primitive found\"*:\n\n| Call
          site | git command | that advisory's assessment |\n|---|---|---|\n| `IndexFile.remove()`
          | `rm` | `--pathspec-from-file` only reads a pathspec; no write or disclosure
          primitive found |\n| `IndexFile.move()` | `mv` | same |\n| `HEAD.reset()`
          | `reset` | same |\n| `HEAD.checkout()` | `checkout` | same |\n\nThat assessment
          is very nearly right, and I think that is why it held: with\n`--pathspec-from-file`
          alone, Git splits on newlines and the error quotes only the **first\nline**,
          which reads as an uninteresting partial. Adding `--pathspec-file-nul` -
          a sibling flag\nof the same option, and the documented way to handle paths
          containing newlines - makes the\nwhole file one pathspec.\n\n##### Root
          cause\n\n`git/index/base.py:991-1043`:\n\n```python\ndef remove(self, items,
          working_tree=False, **kwargs):\n    ...\n    removed_paths = self.repo.git.rm(args,
          paths, **kwargs).splitlines()   # line 1043\n```\n\n`git/refs/head.py:237-268`:\n\n```python\ndef
          checkout(self, force: bool = False, **kwargs: Any):\n    ...\n    self.repo.git.checkout(self,
          **kwargs)                                 # line 268\n```\n\nNeither has
          an `allow_unsafe_options` parameter or a `check_unsafe_options()` call.\n\n#####
          Proof of concept\n\n```python\nfrom git import Repo\nfrom git.exc import
          GitCommandError\n\nrepo = Repo(\"/path/to/repo\")\nkw = dict(pathspec_from_file=\"/etc/passwd\",
          pathspec_file_nul=True)\n\ntry:\n    repo.index.remove([], **kw)          #
          or: repo.heads[0].checkout(**kw)\nexcept GitCommandError as e:\n    print(e.stderr)
          \                     # <- entire file contents\n```\n\nObserved on published
          3.1.57, against a canary file holding three marked lines:\n\n```\n[PASS]
          IndexFile.remove() -> `git rm` returns ALL 3 canary lines in-band\n       stderr:
          'fatal: pathspec 'LINE1-CANARY-4242\n       LINE2-SECRET-7777\n       LINE3-TAIL-9999\n
          \      ' did not match any files'\n[PASS] Head.checkout() -> `git checkout`
          returns ALL 3 canary lines in-band\n       stderr: 'error: pathspec 'LINE1-CANARY-4242\n
          \      LINE2-SECRET-7777\n       LINE3-TAIL-9999\n       ' did not match
          any file(s) known to git'\n[PASS] PRECISION: `git status` leaks 0/3 -- not
          every unguarded site discloses\n[PASS] PRECISION: the GUARDED checkout-index
          leaks 0/3\n```\n\nThe two precision controls are there so the result is
          about these sinks and not about the\ncanary being visible everywhere.\n\n#####
          Scope correction to the table above\n\nOf the four sites cleared with that
          sentence, **two disclose and two do not**:\n\n| Call site | disclosed? |\n|---|---|\n|
          `IndexFile.remove()` \u2192 `git rm` | **yes, full file** |\n| `Head.checkout()`
          \u2192 `git checkout` | **yes, full file** |\n| `HEAD.reset()` \u2192 `git
          reset` | no - `git reset` does not error on unmatched pathspecs |\n| `IndexFile.move()`
          \u2192 `git mv` | no |\n\nThe two negatives are mentioned because \"the
          dismissal was wrong\" would overstate it: the\ndismissal was wrong for half
          of what it covered.\n\n#### Severity\n- CVSS Score: 6.5 / 10 (Medium)\n-
          Vector String: `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N`\n\n#### References\n-
          [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-hh9p-6wh2-4mfc](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-hh9p-6wh2-4mfc)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
          [https://github.com/gitpython-developers/GitPython/commit/f2550b65bf60ca087190981e2c7b6865e201f40c](https://redirect.github.com/gitpython-developers/GitPython/commit/f2550b65bf60ca087190981e2c7b6865e201f40c)\n-
          [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
          [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-hh9p-6wh2-4mfc)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          GitPython: Arbitrary Git Repository Creation Outside the Working Tree via
          Unvalidated .gitmodules Submodule Name in GitPython\n[GHSA-hmq2-w58f-27jc](https://redirect.github.com/advisories/GHSA-hmq2-w58f-27jc)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\nGitPython computes
          the on-disk location of a submodule's separate Git directory (`.git/modules/<name>`)
          from the submodule's `.gitmodules` section name with no validation. Because
          that name is fully attacker-controlled content of a cloned repository, a
          malicious repository can set a submodule name to a traversal string (e.g.
          `../../../../home/victim/.something`) and cause GitPython to create and
          initialize a full Git repository at an attacker-chosen filesystem path outside
          the intended clone directory. The only precondition is that a victim clones
          the malicious repository with GitPython and runs submodule initialization
          (`submodule_update(init=True)` / `sm.update(init=True)`), a very common
          and often automatic step. Core Git itself already blocks this exact attack
          class (CVE-2018-11235), but GitPython's independent reimplementation never
          adopted an equivalent check.\n\n##### Details\n`src/GitPython/git/objects/submodule/util.py`
          `sm_name()` strips the `submodule \"` / `\"` wrapper from a `.gitmodules`
          `[submodule \"...\"]` header and returns the result unchecked. `Submodule.iter_items()`
          in `src/GitPython/git/objects/submodule/base.py` reads this via `sm_name(sms)`
          and assigns it to `sm._name`; unlike the submodule `path`, `name` is never
          used for a tree lookup, so it is never implicitly validated. `Submodule._module_abspath()`
          then builds `osp.join(parent_repo.git_dir, \"modules\", name)` - `os.path.join`
          does not normalize `../` sequences. `Submodule._clone_repo()` passes this
          value straight to `os.makedirs()` and to `git clone --separate-git-dir=<module_abspath>`,
          creating and populating a full Git repository (objects, refs, hooks, config)
          at the escaped path. Attack prerequisite: attacker controls a repository
          the victim clones and initializes submodules for.\n\n##### PoC\n1. Environment:
          Docker image built `FROM python:3.11-slim`, with `git` installed via `apt-get
          install -y git` (Debian bookworm packaged version, described in the advisory
          as \"git 2.x\"; the host-side verification separately used system git `2.34.1`,
          but no exact version is pinned for the git binary inside this Docker image).
          GitPython is installed inside the container via `pip install /src/GitPython`
          from this repository's own source, which the advisory states resolved to
          the officially released `GitPython==3.1.57` and `gitdb==4.0.12`.\n2. Configuration
          / preconditions: None beyond what's described - the victim must clone the
          attacker's repository with GitPython and run submodule initialization (`repo.submodules`
          + `sm.update(init=True)`, equivalent to `git submodule update --init`).\n3.
          Commands run (quoted verbatim from the advisory's \"Confirmed test run\"
          section):\n```bash\n$ docker build -f GHSA/testing/Dockerfile -t ghsa-gitpython-poc
          .\n$ docker run --rm ghsa-gitpython-poc\n```\n(Per the Dockerfile, `docker
          run` executes `/work/run_all.sh`, which in turn runs `build_attacker_repo.sh`,
          then `poc_gitpython.py`, then `poc_control_realgit.sh`.)\n4. Full source
          of the PoC script (`GHSA/testing/poc_gitpython.py`), verbatim:\n```python\n\"\"\"GHSA-001
          PoC: GitPython side.\n\nClones the attacker repo and runs the equivalent
          of\n`git submodule update --init` via GitPython, then checks whether a git\nrepository
          was created outside the clone directory.\n\"\"\"\nimport os\nimport shutil\n\nimport
          git\n\nCLONE_DIR = '/work/victim_clone/repo'\nESCAPE_TARGET = '/tmp/gitpython_poc_escaped_root'\n\ndef
          main():\n    shutil.rmtree(os.path.dirname(CLONE_DIR), ignore_errors=True)\n
          \   shutil.rmtree(ESCAPE_TARGET, ignore_errors=True)\n    os.makedirs(os.path.dirname(CLONE_DIR),
          exist_ok=True)\n\n    print(f'GitPython version: {git.__version__}')\n    repo
          = git.Repo.clone_from('/work/attacker_repo', CLONE_DIR)\n    print('Cloned
          into:', repo.working_tree_dir)\n\n    sms = list(repo.submodules)\n    for
          sm in sms:\n        print('  submodule name:', repr(sm.name))\n        print('
          \ submodule path:', repr(sm.path))\n\n    print('escape_target exists before
          update:', os.path.exists(ESCAPE_TARGET))\n\n    for sm in sms:\n        try:\n
          \           sm.update(init=True)\n        except Exception as e:\n            print('sm.update
          raised:', repr(e))\n\n    exists = os.path.exists(ESCAPE_TARGET)\n    print('escape_target
          exists after update:', exists)\n    if exists:\n        print('escape_target
          contents:', os.listdir(ESCAPE_TARGET))\n\n    print('POC_RESULT=VULNERABLE'
          if exists else 'POC_RESULT=SAFE')\n\nif __name__ == '__main__':\n    main()\n```\n5.
          Exact captured terminal output (verbatim, from the original advisory's \"Confirmed
          test run (Docker, released package)\" section):\n```\n=== GitPython PoC
          (vulnerable path) ===\nGitPython version: 3.1.57\nCloned into: /work/victim_clone/repo\n
          \ submodule name: '../../../../../../tmp/gitpython_poc_escaped_root/modules_dir'\n
          \ submodule path: 'legit_dir'\nescape_target exists before update: False\nescape_target
          exists after update: True\nescape_target contents: ['modules_dir']\nPOC_RESULT=VULNERABLE\n\n===
          Control: real git CLI on identical repo ===\nwarning: ignoring suspicious
          submodule name: ../../../../../../tmp/gitpython_poc_escaped_root/modules_dir\nwarning:
          ignoring suspicious submodule name: ../../../../../../tmp/gitpython_poc_escaped_root/modules_dir\nfatal:
          No url found for submodule path 'legit_dir' in .gitmodules\nCONTROL_RESULT=SAFE
          (real git correctly refused)\n```\n6. Payload: the attacker rewrites the
          `.gitmodules` section header from `[submodule \"legit_dir\"]` to `[submodule
          \"../../../../../../tmp/gitpython_poc_escaped_root/modules_dir\"]` (built
          by `build_attacker_repo.sh`, part of the harness in `GHSA/testing/`). The
          malicious part is the `../../../../../../` traversal sequence embedded in
          the submodule *name* (not the tree-validated `path`), which becomes the
          on-disk target for the submodule's separate git directory.\n7. Expected
          vs. observed: A safe implementation (as demonstrated by the real `git` CLI
          control run) rejects the submodule name with \"ignoring suspicious submodule
          name\" and refuses to create anything outside the repository. GitPython
          instead created the escape-target directory and a fully-initialized Git
          repository at `/tmp/gitpython_poc_escaped_root/modules_dir`, confirmed by
          `escape_target exists after update: True` and its listed contents.\n8. Security
          impact demonstrated: arbitrary filesystem directory and Git-repository creation
          at an attacker-chosen absolute path outside the victim's intended clone
          directory, populated with attacker-controlled content sourced from the submodule's
          own (also attacker-controlled) `url`.\n\n##### Impact\nPath traversal (CWE-22)
          / external control of file path (CWE-73) leading to arbitrary directory
          and Git-repository creation outside the intended clone directory. Integrity
          impact is High (attacker chooses destination path and, via the submodule
          URL, much of the written content); Confidentiality impact is None (only
          creation was demonstrated); Availability impact is Low-Medium (disk-exhaustion
          potential). No authentication is required; the attacker only needs to control
          a repository the victim clones and initializes submodules for - a routine,
          often fully-automatic operation in CI pipelines, IDE integrations, and dependency-management
          tooling.\n\n#### Severity\n- CVSS Score: 8.2 / 10 (High)\n- Vector String:
          `CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:N/I:H/A:L`\n\n#### References\n- [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-hmq2-w58f-27jc](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-hmq2-w58f-27jc)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2202](https://redirect.github.com/gitpython-developers/GitPython/pull/2202)\n-
          [https://github.com/gitpython-developers/GitPython/commit/4299c990e1ca21896f9485277caf7bb0ae5b404c](https://redirect.github.com/gitpython-developers/GitPython/commit/4299c990e1ca21896f9485277caf7bb0ae5b404c)\n-
          [https://github.com/gitpython-developers/GitPython/commit/e4b8e7d026ca6abb4cf604f8e77093432ce23c06](https://redirect.github.com/gitpython-developers/GitPython/commit/e4b8e7d026ca6abb4cf604f8e77093432ce23c06)\n-
          [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
          [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-hmq2-w58f-27jc)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          GitPython: git-config OPTION-name injection via =/#/whitespace bypasses
          name validator, enabling forged core.sshCommand/hooksPath (RCE)\n[GHSA-jm78-9fvv-mhgr](https://redirect.github.com/advisories/GHSA-jm78-9fvv-mhgr)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\nGitPython's config-name
          validator only neutralizes CR/LF/NUL for the `\"option\"` label; it does
          not reject `=`, `#`, `;`, `[`, `]`, or whitespace in an **option name**.
          `write_section` writes the option name verbatim into the config file, so
          an option name such as `sshCommand = touch <cmd> #` is written as `\\tsshCommand
          = touch <cmd> # = <value>`, which git parses as `core.sshCommand = touch
          <cmd>` (the trailing `#` comments out the intended value). This forges arbitrary
          config directives (`core.sshCommand`, `core.hooksPath`, `alias.*`) \u2192
          RCE on the next git operation. This is a distinct field (option name, not
          section name) and distinct character class (`=`/`#`/space, not newline/bracket)
          from GHSA-3rp5-jjmw-4wv2 (section-name bracket injection) and GHSA-mv93-w799-cj2w
          / GHSA-v87r-6q3f-2j67 (newline injection).\n\n##### Root Cause\n`_assure_config_name_safe(name,
          label)` (`git/config.py:897`) applies the bracket/quote state machine ONLY
          when `label == \"section\"`; for the `\"option\"` label it falls through
          with just the `UNSAFE_CONFIG_CHARS_RE = [\\r\\n\\x00]` regex. `write_section`
          then writes the option name verbatim into `\"\\t%s = %s\\n\"` (config.py:702).\n\n#####
          Impact\nArbitrary git-config directive injection \u2192 remote code execution
          via `core.sshCommand` (fires on any ssh git operation, no staged file needed)
          or `core.hooksPath` (with a staged hook). Requires the embedding application
          to forward a caller-influenced OPTION NAME into the config writer (name-control
          model, the same name-control model accepted by the related published advisories
          GHSA-3rp5-jjmw-4wv2 and GHSA-mv93-w799-cj2w). Default configuration.\n\n#####
          Proof of Concept\n```python\nwith repo.config_writer() as cw:\n    cw.set_value(\"core\",
          \"sshCommand = touch /tmp/RCE #\", \"x\")\n\n##### git config --get core.sshCommand
          \ ->  touch /tmp/RCE\n```\n\n##### Attack Chain\n1. Entry: app calls config
          writer with attacker-controlled OPTION name: `set_value(\"core\", \"sshCommand
          = touch /tmp/RCE #\", \"x\")`.\n2. Check: `_assure_config_name_safe(option,
          \"option\")` @&#8203; config.py. Guard: regex matches only `[\\r\\n\\x00]`;
          bracket/quote state machine is gated on `label==\"section\"`. Bypass proof:
          `=`,`#`,space pass \u2192 no `ValueError`.\n3. Sink: `write_section` writes
          `\"\\tsshCommand = touch /tmp/RCE # = x\\n\"` (config.py:702).\n4. Impact:
          git parses `core.sshCommand=touch /tmp/RCE` \u2192 arbitrary code execution
          on next git op.\n\n##### Bypass Evidence\nIndependently reproduced (gate
          harness): `set_value('core','sshCommand = touch <RCE> #','x')` \u2192 no
          `ValueError`; file line `sshCommand = touch <RCE> # = x`; `git config --get
          core.sshCommand` \u2192 `touch <RCE>` (rc=0). Also verified `core.hooksPath`
          via both `GitConfigParser` and `repo.config_writer()`. Fix-commit read:
          bracket/quote checks are inside `if label == \"section\"`; the `\"option\"`
          label is not covered.\n\n##### Affected Versions\n`GitPython <= 3.1.57`
          (validator present verbatim on the latest release tag).\n\n##### Suggested
          Fix\nApply the section-name safety checks (reject `=`, `#`, `;`, `[`, `]`,
          whitespace) to the `\"option\"` label as well, or validate the fully-rendered
          config line after substitution.\n\n---\nReported by **zx (Jace)** \u2014
          GitHub: @&#8203;manus-use\n\n#### Severity\n- CVSS Score: 8.8 / 10 (High)\n-
          Vector String: `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H`\n\n#### References\n-
          [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-jm78-9fvv-mhgr](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-jm78-9fvv-mhgr)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
          [https://github.com/gitpython-developers/GitPython/commit/a495ccd3b547ccd60b2187215823b72a9c0188bf](https://redirect.github.com/gitpython-developers/GitPython/commit/a495ccd3b547ccd60b2187215823b72a9c0188bf)\n-
          [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
          [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-jm78-9fvv-mhgr)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          GitPython: Unsafe git option guard bypass via split_single_char_options=False
          short-option token smuggling enables command execution\n[GHSA-wvpp-8hx9-p66j](https://redirect.github.com/advisories/GHSA-wvpp-8hx9-p66j)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\nThe `check_unsafe_options`
          guard can be bypassed on every guarded method (clone/clone_from, fetch/pull/push,
          ls_remote, iter_commits, blame, archive) by combining a single-character
          kwarg with `split_single_char_options=False`. The guard's candidate list
          omits the smuggled option, but `transform_kwarg` emits a JOINED `-n<value>`
          argv token that git parses as `--upload-pack=<cmd>`, yielding arbitrary
          command execution at the default `allow_unsafe_options=False`. This is an
          incomplete-fix bypass of commit `e8d0fbf7` (the fix for GHSA-r9mr-m37c-5fr3),
          which only emits value-derived candidates when `split_single_char_options`
          is True.\n\n##### Root Cause\n`_option_candidates` derives value-token candidates
          only under `if len(key)==1 and split_single_char_options:` (cmd.py:1048,
          added by `e8d0fbf7`). With `split_single_char_options=False`, `_option_candidates([],
          {\"n\":\"utouch <cmd>;git-upload-pack\"})` returns only `['-n']` (not on
          the denylist), so the guard passes. But `transform_kwarg('n', value, split_single_char_options=False)`
          emits the JOINED token `-nutouch <cmd>;git-upload-pack` (cmd.py:1631). git
          clusters value-less short flags then parses `-u<cmd>` = `--upload-pack=<cmd>`
          \u2192 command execution. The hardened guard WOULD block the joined token
          if it saw it \u2014 the flaw is it never receives it.\n\n##### Impact\nArbitrary
          OS command execution as the host process (via `--upload-pack`) at default
          `allow_unsafe_options=False`, affecting all guarded methods that forward
          kwargs. Precondition: the app forwards a user-controlled kwargs dict containing
          `split_single_char_options=False` plus a single-char key (same user-dict-forwarding
          model GHSA-r9mr-m37c-5fr3 accepts).\n\n##### Proof of Concept\n```python\nfrom
          git import Repo\nRepo.clone_from(src, dst,\n    n=\"utouch /tmp/ACE;git-upload-pack\",\n
          \   split_single_char_options=False)   # /tmp/ACE created -> ACE\n```\n\n#####
          Attack Chain\n1. Entry: app forwards user kwargs to `Repo.clone_from(url,
          path, **kwargs)`: `{split_single_char_options: False, n: 'utouch /tmp/ACE;git-upload-pack'}`.\n2.
          Check: `check_unsafe_options(_option_candidates([], kwargs), unsafe_git_clone_options)`.
          Guard: denylist includes `--upload-pack`/`-u`. Bypass proof: `_option_candidates`
          yields only `['-n']` (value token skipped because `split=False`); guard
          never sees `-u`.\n3. Sink: `transform_kwarg` emits joined token (cmd.py:1631).
          argv (observed): `['git','clone','-v','-nutouch /tmp/ACE;git-upload-pack','--','<src>','<dst>']`.\n4.
          Impact: git clusters `-n` + `-u<cmd>` \u2192 runs upload-pack command \u2192
          ACE.\n\n##### Bypass Evidence\nIndependently reproduced (gate harness, default
          `allow_unsafe_options=False`): the `split=False` payload created the marker
          `VH05_GATE_ACE` (ACE); the clone returned normally (guard bypassed). Control:
          `n='--upload-pack=\u2026'` (split default True) \u2192 `UnsafeOptionError:
          --upload-pack is not allowed`. Fix-commit read: `e8d0fbf7` extends candidates
          only under `if len(key)==1 and split_single_char_options:` \u2014 split=False
          skips value emission. Also confirmed the earlier clustering-parse fix (commit
          `56806080`) does not cover this because the guard only ever receives `['-n']`.\n\n#####
          Affected Versions\n`GitPython <= 3.1.57` (code present verbatim on the latest
          release tag).\n\n##### Suggested Fix\nMake `_option_candidates` emit value-derived
          candidates regardless of `split_single_char_options` (i.e. also for the
          joined `-n<value>` form), OR run `check_unsafe_options` over the fully-transformed
          argv rather than the reconstructed name-only candidate list.\n\n---\nReported
          by **zx (Jace)** \u2014 GitHub: @&#8203;manus-use\n\n#### Severity\n- CVSS
          Score: 8.8 / 10 (High)\n- Vector String: `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H`\n\n####
          References\n- [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-wvpp-8hx9-p66j](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-wvpp-8hx9-p66j)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
          [https://github.com/gitpython-developers/GitPython/commit/96a888f4d782cb2f80452148e48e60ce4af6d541](https://redirect.github.com/gitpython-developers/GitPython/commit/96a888f4d782cb2f80452148e48e60ce4af6d541)\n-
          [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
          [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-wvpp-8hx9-p66j)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          Release Notes\n\n<details>\n<summary>gitpython-developers/GitPython (GitPython)</summary>\n\n###
          [`v3.1.58`](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58):
          Security and Fixes\n\n[Compare Source](https://redirect.github.com/gitpython-developers/GitPython/compare/3.1.57...3.1.58)\n\n#####
          What's Changed\n\n- test: allow Python startup before timeout by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2195](https://redirect.github.com/gitpython-developers/GitPython/pull/2195)\n-
          Resolve Windows hook Bash through PATH by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2199](https://redirect.github.com/gitpython-developers/GitPython/pull/2199)\n-
          Revert \"Resolve Windows hook Bash through PATH\" by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2200](https://redirect.github.com/gitpython-developers/GitPython/pull/2200)\n-
          test: focus pytest summary on unexpected failures by [@&#8203;raisulchowdhury](https://redirect.github.com/raisulchowdhury)
          in [#&#8203;2203](https://redirect.github.com/gitpython-developers/GitPython/pull/2203)\n-
          Validate submodule names before filesystem operations by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2202](https://redirect.github.com/gitpython-developers/GitPython/pull/2202)\n-
          Handle invalid submodule names during recursive updates by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2205](https://redirect.github.com/gitpython-developers/GitPython/pull/2205)\n-
          Fix Windows path handling on Python 3.13+ by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2196](https://redirect.github.com/gitpython-developers/GitPython/pull/2196)\n-
          fixup 2202 by [@&#8203;Byron](https://redirect.github.com/Byron) in [#&#8203;2206](https://redirect.github.com/gitpython-developers/GitPython/pull/2206)\n-
          Correct Windows hook Bash precedence by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2201](https://redirect.github.com/gitpython-developers/GitPython/pull/2201)\n-
          Harden config and Git option validation by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
          Skip tests that need symlink privileges instead of erroring by [@&#8203;Cyrus580529](https://redirect.github.com/Cyrus580529)
          in [#&#8203;2197](https://redirect.github.com/gitpython-developers/GitPython/pull/2197)\n\n#####
          New Contributors\n\n- [@&#8203;raisulchowdhury](https://redirect.github.com/raisulchowdhury)
          made their first contribution in [#&#8203;2203](https://redirect.github.com/gitpython-developers/GitPython/pull/2203)\n-
          [@&#8203;Cyrus580529](https://redirect.github.com/Cyrus580529) made their
          first contribution in [#&#8203;2197](https://redirect.github.com/gitpython-developers/GitPython/pull/2197)\n\n**Full
          Changelog**: <https://github.com/gitpython-developers/GitPython/compare/3.1.57...3.1.58>\n\n</details>\n\n---\n\n###
          Configuration\n\n\U0001F4C5 **Schedule**: (UTC)\n\n- Branch creation\n  -
          At any time (no schedule defined)\n- Automerge\n  - At any time (no schedule
          defined)\n\n\U0001F6A6 **Automerge**: Disabled by config. Please merge this
          manually once you are satisfied.\n\n\u267B **Rebasing**: Whenever PR becomes
          conflicted, or you tick the rebase/retry checkbox.\n\n\U0001F515 **Ignore**:
          Close this PR and you won't be reminded about these updates again.\n\n---\n\n
          - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this
          box\n\n---\n\nThis PR was generated by [Mend Renovate](https://mend.io/renovate/).
          View the [repository job log](https://developer.mend.io/github/osism/python-osism).\n<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMi4wIiwidXBkYXRlZEluVmVyIjoiNDQuMTIuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsicmVub3ZhdGUiXX0=-->\n"
        change_url: https://github.com/osism/python-osism/pull/2587
        commit_id: 8f8d2989b17d7199dea1d0770f90e6edaa6b261f
        patchset: 8f8d2989b17d7199dea1d0770f90e6edaa6b261f
        project:
          canonical_hostname: github.com
          canonical_name: github.com/osism/python-osism
          name: osism/python-osism
          short_name: python-osism
        src_dir: src/github.com/osism/python-osism
        topic: null
      change: '2587'
      change_message: "chore(deps): update dependency gitpython to v3.1.58 [security]\n\nThis
        PR contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/)
        | [Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n|
        [GitPython](https://redirect.github.com/gitpython-developers/GitPython) |
        `==3.1.57` \u2192 `==3.1.58` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/gitpython/3.1.58?slim=true)
        | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/gitpython/3.1.57/3.1.58?slim=true)
        |\n\n---\n\n### GitPython: Unguarded git read-tree option forwarding in IndexFile.from_tree/reset/merge_tree
        enables arbitrary file overwrite\n[GHSA-4gmw-gg2m-w46p](https://redirect.github.com/advisories/GHSA-4gmw-gg2m-w46p)\n\n<details>\n<summary>More
        information</summary>\n\n#### Details\n##### Summary\n`IndexFile.from_tree`,
        `IndexFile.reset` (\u2192 from_tree) and `IndexFile.merge_tree` append caller-influenced
        treeish strings positionally to `git read-tree` with no unsafe-option guard,
        no `allow_unsafe_options` parameter, and no `--` separator. `git read-tree
        --index-output=<file>` writes the resulting index to an arbitrary path, and
        last-occurrence-wins lets an injected `--index-output` override the method's
        internal temp path \u2014 clobbering an arbitrary file with a valid git-index
        blob. This is a distinct, never-guarded sink: commit `3af0c251` (GHSA-3f7w-8rr8-f37f)
        guarded only `checkout_index` and `tag`; `read_tree` was left unprotected
        (it is among the acknowledged unguarded call sites in that advisory's sweep
        but was never reported or fixed).\n\n##### Root Cause\n`from_tree` (index/base.py:388),
        `reset` (delegates to from_tree), and `merge_tree` (index/base.py:291) call
        `repo.git.read_tree(*arg_list)` with no `check_unsafe_options` and no `--`.
        The treeish is caller-influenced and positional.\n\n##### Impact\nArbitrary
        file overwrite / destruction at the privileges of the host process. Content
        is constrained to a git-index blob (not attacker-chosen, so not RCE), but
        the target path is fully attacker-controlled \u2014 corrupting/truncating
        configs or destroying files at attacker-chosen writable locations = I:H +
        A:H (per the skill's \"overwrite-any-path = I:H\" rule). Pure VALUE control
        (positional treeish). Default configuration.\n\n##### Proof of Concept\n```python\nIndexFile.from_tree(repo,
        \"--index-output=/home/victim/.bashrc\")\n\n##### target overwritten with
        a valid git-index blob (DIRC...)\n```\n\n##### Attack Chain\n1. Entry: app
        calls `IndexFile.from_tree(repo, treeish)` / `reset(commit=\u2026)` / `merge_tree(base=\u2026,
        rhs=\u2026)` with attacker `treeish=\"--index-output=/home/victim/.bashrc\"`.\n2.
        Check: NONE \u2014 the methods have no `allow_unsafe_options` and never call
        `check_unsafe_options`.\n3. Sink: `repo.git.read_tree(*arg_list)` \u2014 no
        `--`. argv (from_tree, observed): `['git','read-tree','--index-output=<tmp>','--index-output=/\u2026/victim']`
        (last-wins).\n4. Impact: target path created/overwritten with a valid git-index
        blob; existing content destroyed.\n\n##### Bypass Evidence\nIndependently
        reproduced (gate harness): `IndexFile.from_tree(repo,'--index-output=<victim>')`
        \u2192 victim overwritten; before=`IMPORTANT ORIGINAL CONTENT`, after starts
        `DIRC\\x00\\x00\\x00\\x02\u2026` (destructive clobber, valid index blob).
        `reset(commit=\u2026)` and both `merge_tree` positionals verified. Fix-commit
        read: `3af0c251` touched only `checkout_index`+`tag`; `read_tree` untouched
        on HEAD.\n\n##### Affected Versions\n`GitPython <= 3.1.57` (sinks present
        verbatim on the latest release tag).\n\n##### Suggested Fix\nAdd a `check_unsafe_options`
        guard (with an `allow_unsafe_options` parameter) to `from_tree`/`reset`/`merge_tree`,
        and/or place a `--` separator before the positional treeish arguments; block
        `--index-output` (a path-taking option) on this sink.\n\n---\nReported by
        **zx (Jace)** \u2014 GitHub: @&#8203;manus-use\n\n#### Severity\n- CVSS Score:
        8.1 / 10 (High)\n- Vector String: `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H`\n\n####
        References\n- [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-4gmw-gg2m-w46p](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-4gmw-gg2m-w46p)\n-
        [https://github.com/gitpython-developers/GitPython/pull/2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
        [https://github.com/gitpython-developers/GitPython/commit/9b5dcaf85da5946dbf69dcd53f9edba08f760b32](https://redirect.github.com/gitpython-developers/GitPython/commit/9b5dcaf85da5946dbf69dcd53f9edba08f760b32)\n-
        [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
        [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
        data is provided by [OSV](https://osv.dev/vulnerability/GHSA-4gmw-gg2m-w46p)
        and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
        ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
        GitPython: Unguarded git option forwarding in Repo.init enables arbitrary
        command execution via --template clone hooks\n[GHSA-9rj7-rf2p-w77r](https://redirect.github.com/advisories/GHSA-9rj7-rf2p-w77r)\n\n<details>\n<summary>More
        information</summary>\n\n#### Details\n##### Summary\n`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 \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\n##### attacker
        stages /evil/hooks/post-commit (executable)\nfrom git import Repo\nRepo.init(path,
        template=\"/evil\")\n\n##### next commit runs /evil/hooks/post-commit -> 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='/evil')`.\n2. Check: NONE
        on `Repo.init`. Bypass proof: base.py:1435 is a bare `git.init(**kwargs)`.
        argv (observed): `['git','init','--template=/evil']`.\n3. Sink: git copies
        `/evil/hooks/post-commit` \u2192 `<repo>/.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='<evil>')`
        \u2192 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).\n\n##### Affected Versions\n`GitPython
        <= 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: @&#8203;manus-use\n\n####
        Severity\n- CVSS Score: 7.5 / 10 (High)\n- Vector String: `CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H`\n\n####
        References\n- [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-9rj7-rf2p-w77r](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-9rj7-rf2p-w77r)\n-
        [https://github.com/gitpython-developers/GitPython/pull/2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
        [https://github.com/gitpython-developers/GitPython/commit/d9ddb55bdc66](https://redirect.github.com/gitpython-developers/GitPython/commit/d9ddb55bdc66)\n-
        [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
        [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
        data is provided by [OSV](https://osv.dev/vulnerability/GHSA-9rj7-rf2p-w77r)
        and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
        ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
        GitPython: Arbitrary file read via --pathspec-from-file in IndexFile.remove()
        and Head.checkout()\n[GHSA-hh9p-6wh2-4mfc](https://redirect.github.com/advisories/GHSA-hh9p-6wh2-4mfc)\n\n<details>\n<summary>More
        information</summary>\n\n#### Details\n##### Summary\n\n`IndexFile.remove()`
        and `Head.checkout()` forward `**kwargs` into `git rm` and `git checkout`\nwith
        no guard. Passing `--pathspec-from-file=<file>` **together with `--pathspec-file-nul`**\nmakes
        Git treat the whole file as a single NUL-delimited pathspec, and the unmatched-pathspec\nerror
        quotes it verbatim. GitPython surfaces that through `GitCommandError.stderr`,
        so the\nentire contents of a caller-chosen file are returned to the caller
        in band.\n\nThis is the same primitive as Instance 2 of\n[GHSA-3f7w-8rr8-f37f](https://redirect.github.com/advisories/GHSA-3f7w-8rr8-f37f)
        - `TagReference.create()`\nwith `-F`, arbitrary file read returned in band
        - at two sites that advisory assessed and\ncleared.\n\n##### Prior art, and
        why I am filing rather than commenting\n\nGHSA-3f7w-8rr8-f37f's sweep table
        lists these four sites with the assessment\n*\"`--pathspec-from-file` only
        reads a pathspec; no write or disclosure primitive found\"*:\n\n| Call site
        | git command | that advisory's assessment |\n|---|---|---|\n| `IndexFile.remove()`
        | `rm` | `--pathspec-from-file` only reads a pathspec; no write or disclosure
        primitive found |\n| `IndexFile.move()` | `mv` | same |\n| `HEAD.reset()`
        | `reset` | same |\n| `HEAD.checkout()` | `checkout` | same |\n\nThat assessment
        is very nearly right, and I think that is why it held: with\n`--pathspec-from-file`
        alone, Git splits on newlines and the error quotes only the **first\nline**,
        which reads as an uninteresting partial. Adding `--pathspec-file-nul` - a
        sibling flag\nof the same option, and the documented way to handle paths containing
        newlines - makes the\nwhole file one pathspec.\n\n##### Root cause\n\n`git/index/base.py:991-1043`:\n\n```python\ndef
        remove(self, items, working_tree=False, **kwargs):\n    ...\n    removed_paths
        = self.repo.git.rm(args, paths, **kwargs).splitlines()   # line 1043\n```\n\n`git/refs/head.py:237-268`:\n\n```python\ndef
        checkout(self, force: bool = False, **kwargs: Any):\n    ...\n    self.repo.git.checkout(self,
        **kwargs)                                 # line 268\n```\n\nNeither has an
        `allow_unsafe_options` parameter or a `check_unsafe_options()` call.\n\n#####
        Proof of concept\n\n```python\nfrom git import Repo\nfrom git.exc import GitCommandError\n\nrepo
        = Repo(\"/path/to/repo\")\nkw = dict(pathspec_from_file=\"/etc/passwd\", pathspec_file_nul=True)\n\ntry:\n
        \   repo.index.remove([], **kw)          # or: repo.heads[0].checkout(**kw)\nexcept
        GitCommandError as e:\n    print(e.stderr)                      # <- entire
        file contents\n```\n\nObserved on published 3.1.57, against a canary file
        holding three marked lines:\n\n```\n[PASS] IndexFile.remove() -> `git rm`
        returns ALL 3 canary lines in-band\n       stderr: 'fatal: pathspec 'LINE1-CANARY-4242\n
        \      LINE2-SECRET-7777\n       LINE3-TAIL-9999\n       ' did not match any
        files'\n[PASS] Head.checkout() -> `git checkout` returns ALL 3 canary lines
        in-band\n       stderr: 'error: pathspec 'LINE1-CANARY-4242\n       LINE2-SECRET-7777\n
        \      LINE3-TAIL-9999\n       ' did not match any file(s) known to git'\n[PASS]
        PRECISION: `git status` leaks 0/3 -- not every unguarded site discloses\n[PASS]
        PRECISION: the GUARDED checkout-index leaks 0/3\n```\n\nThe two precision
        controls are there so the result is about these sinks and not about the\ncanary
        being visible everywhere.\n\n##### Scope correction to the table above\n\nOf
        the four sites cleared with that sentence, **two disclose and two do not**:\n\n|
        Call site | disclosed? |\n|---|---|\n| `IndexFile.remove()` \u2192 `git rm`
        | **yes, full file** |\n| `Head.checkout()` \u2192 `git checkout` | **yes,
        full file** |\n| `HEAD.reset()` \u2192 `git reset` | no - `git reset` does
        not error on unmatched pathspecs |\n| `IndexFile.move()` \u2192 `git mv` |
        no |\n\nThe two negatives are mentioned because \"the dismissal was wrong\"
        would overstate it: the\ndismissal was wrong for half of what it covered.\n\n####
        Severity\n- CVSS Score: 6.5 / 10 (Medium)\n- Vector String: `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N`\n\n####
        References\n- [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-hh9p-6wh2-4mfc](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-hh9p-6wh2-4mfc)\n-
        [https://github.com/gitpython-developers/GitPython/pull/2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
        [https://github.com/gitpython-developers/GitPython/commit/f2550b65bf60ca087190981e2c7b6865e201f40c](https://redirect.github.com/gitpython-developers/GitPython/commit/f2550b65bf60ca087190981e2c7b6865e201f40c)\n-
        [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
        [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
        data is provided by [OSV](https://osv.dev/vulnerability/GHSA-hh9p-6wh2-4mfc)
        and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
        ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
        GitPython: Arbitrary Git Repository Creation Outside the Working Tree via
        Unvalidated .gitmodules Submodule Name in GitPython\n[GHSA-hmq2-w58f-27jc](https://redirect.github.com/advisories/GHSA-hmq2-w58f-27jc)\n\n<details>\n<summary>More
        information</summary>\n\n#### Details\n##### Summary\nGitPython computes the
        on-disk location of a submodule's separate Git directory (`.git/modules/<name>`)
        from the submodule's `.gitmodules` section name with no validation. Because
        that name is fully attacker-controlled content of a cloned repository, a malicious
        repository can set a submodule name to a traversal string (e.g. `../../../../home/victim/.something`)
        and cause GitPython to create and initialize a full Git repository at an attacker-chosen
        filesystem path outside the intended clone directory. The only precondition
        is that a victim clones the malicious repository with GitPython and runs submodule
        initialization (`submodule_update(init=True)` / `sm.update(init=True)`), a
        very common and often automatic step. Core Git itself already blocks this
        exact attack class (CVE-2018-11235), but GitPython's independent reimplementation
        never adopted an equivalent check.\n\n##### Details\n`src/GitPython/git/objects/submodule/util.py`
        `sm_name()` strips the `submodule \"` / `\"` wrapper from a `.gitmodules`
        `[submodule \"...\"]` header and returns the result unchecked. `Submodule.iter_items()`
        in `src/GitPython/git/objects/submodule/base.py` reads this via `sm_name(sms)`
        and assigns it to `sm._name`; unlike the submodule `path`, `name` is never
        used for a tree lookup, so it is never implicitly validated. `Submodule._module_abspath()`
        then builds `osp.join(parent_repo.git_dir, \"modules\", name)` - `os.path.join`
        does not normalize `../` sequences. `Submodule._clone_repo()` passes this
        value straight to `os.makedirs()` and to `git clone --separate-git-dir=<module_abspath>`,
        creating and populating a full Git repository (objects, refs, hooks, config)
        at the escaped path. Attack prerequisite: attacker controls a repository the
        victim clones and initializes submodules for.\n\n##### PoC\n1. Environment:
        Docker image built `FROM python:3.11-slim`, with `git` installed via `apt-get
        install -y git` (Debian bookworm packaged version, described in the advisory
        as \"git 2.x\"; the host-side verification separately used system git `2.34.1`,
        but no exact version is pinned for the git binary inside this Docker image).
        GitPython is installed inside the container via `pip install /src/GitPython`
        from this repository's own source, which the advisory states resolved to the
        officially released `GitPython==3.1.57` and `gitdb==4.0.12`.\n2. Configuration
        / preconditions: None beyond what's described - the victim must clone the
        attacker's repository with GitPython and run submodule initialization (`repo.submodules`
        + `sm.update(init=True)`, equivalent to `git submodule update --init`).\n3.
        Commands run (quoted verbatim from the advisory's \"Confirmed test run\" section):\n```bash\n$
        docker build -f GHSA/testing/Dockerfile -t ghsa-gitpython-poc .\n$ docker
        run --rm ghsa-gitpython-poc\n```\n(Per the Dockerfile, `docker run` executes
        `/work/run_all.sh`, which in turn runs `build_attacker_repo.sh`, then `poc_gitpython.py`,
        then `poc_control_realgit.sh`.)\n4. Full source of the PoC script (`GHSA/testing/poc_gitpython.py`),
        verbatim:\n```python\n\"\"\"GHSA-001 PoC: GitPython side.\n\nClones the attacker
        repo and runs the equivalent of\n`git submodule update --init` via GitPython,
        then checks whether a git\nrepository was created outside the clone directory.\n\"\"\"\nimport
        os\nimport shutil\n\nimport git\n\nCLONE_DIR = '/work/victim_clone/repo'\nESCAPE_TARGET
        = '/tmp/gitpython_poc_escaped_root'\n\ndef main():\n    shutil.rmtree(os.path.dirname(CLONE_DIR),
        ignore_errors=True)\n    shutil.rmtree(ESCAPE_TARGET, ignore_errors=True)\n
        \   os.makedirs(os.path.dirname(CLONE_DIR), exist_ok=True)\n\n    print(f'GitPython
        version: {git.__version__}')\n    repo = git.Repo.clone_from('/work/attacker_repo',
        CLONE_DIR)\n    print('Cloned into:', repo.working_tree_dir)\n\n    sms =
        list(repo.submodules)\n    for sm in sms:\n        print('  submodule name:',
        repr(sm.name))\n        print('  submodule path:', repr(sm.path))\n\n    print('escape_target
        exists before update:', os.path.exists(ESCAPE_TARGET))\n\n    for sm in sms:\n
        \       try:\n            sm.update(init=True)\n        except Exception as
        e:\n            print('sm.update raised:', repr(e))\n\n    exists = os.path.exists(ESCAPE_TARGET)\n
        \   print('escape_target exists after update:', exists)\n    if exists:\n
        \       print('escape_target contents:', os.listdir(ESCAPE_TARGET))\n\n    print('POC_RESULT=VULNERABLE'
        if exists else 'POC_RESULT=SAFE')\n\nif __name__ == '__main__':\n    main()\n```\n5.
        Exact captured terminal output (verbatim, from the original advisory's \"Confirmed
        test run (Docker, released package)\" section):\n```\n=== GitPython PoC (vulnerable
        path) ===\nGitPython version: 3.1.57\nCloned into: /work/victim_clone/repo\n
        \ submodule name: '../../../../../../tmp/gitpython_poc_escaped_root/modules_dir'\n
        \ submodule path: 'legit_dir'\nescape_target exists before update: False\nescape_target
        exists after update: True\nescape_target contents: ['modules_dir']\nPOC_RESULT=VULNERABLE\n\n===
        Control: real git CLI on identical repo ===\nwarning: ignoring suspicious
        submodule name: ../../../../../../tmp/gitpython_poc_escaped_root/modules_dir\nwarning:
        ignoring suspicious submodule name: ../../../../../../tmp/gitpython_poc_escaped_root/modules_dir\nfatal:
        No url found for submodule path 'legit_dir' in .gitmodules\nCONTROL_RESULT=SAFE
        (real git correctly refused)\n```\n6. Payload: the attacker rewrites the `.gitmodules`
        section header from `[submodule \"legit_dir\"]` to `[submodule \"../../../../../../tmp/gitpython_poc_escaped_root/modules_dir\"]`
        (built by `build_attacker_repo.sh`, part of the harness in `GHSA/testing/`).
        The malicious part is the `../../../../../../` traversal sequence embedded
        in the submodule *name* (not the tree-validated `path`), which becomes the
        on-disk target for the submodule's separate git directory.\n7. Expected vs.
        observed: A safe implementation (as demonstrated by the real `git` CLI control
        run) rejects the submodule name with \"ignoring suspicious submodule name\"
        and refuses to create anything outside the repository. GitPython instead created
        the escape-target directory and a fully-initialized Git repository at `/tmp/gitpython_poc_escaped_root/modules_dir`,
        confirmed by `escape_target exists after update: True` and its listed contents.\n8.
        Security impact demonstrated: arbitrary filesystem directory and Git-repository
        creation at an attacker-chosen absolute path outside the victim's intended
        clone directory, populated with attacker-controlled content sourced from the
        submodule's own (also attacker-controlled) `url`.\n\n##### Impact\nPath traversal
        (CWE-22) / external control of file path (CWE-73) leading to arbitrary directory
        and Git-repository creation outside the intended clone directory. Integrity
        impact is High (attacker chooses destination path and, via the submodule URL,
        much of the written content); Confidentiality impact is None (only creation
        was demonstrated); Availability impact is Low-Medium (disk-exhaustion potential).
        No authentication is required; the attacker only needs to control a repository
        the victim clones and initializes submodules for - a routine, often fully-automatic
        operation in CI pipelines, IDE integrations, and dependency-management tooling.\n\n####
        Severity\n- CVSS Score: 8.2 / 10 (High)\n- Vector String: `CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:N/I:H/A:L`\n\n####
        References\n- [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-hmq2-w58f-27jc](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-hmq2-w58f-27jc)\n-
        [https://github.com/gitpython-developers/GitPython/pull/2202](https://redirect.github.com/gitpython-developers/GitPython/pull/2202)\n-
        [https://github.com/gitpython-developers/GitPython/commit/4299c990e1ca21896f9485277caf7bb0ae5b404c](https://redirect.github.com/gitpython-developers/GitPython/commit/4299c990e1ca21896f9485277caf7bb0ae5b404c)\n-
        [https://github.com/gitpython-developers/GitPython/commit/e4b8e7d026ca6abb4cf604f8e77093432ce23c06](https://redirect.github.com/gitpython-developers/GitPython/commit/e4b8e7d026ca6abb4cf604f8e77093432ce23c06)\n-
        [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
        [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
        data is provided by [OSV](https://osv.dev/vulnerability/GHSA-hmq2-w58f-27jc)
        and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
        ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
        GitPython: git-config OPTION-name injection via =/#/whitespace bypasses name
        validator, enabling forged core.sshCommand/hooksPath (RCE)\n[GHSA-jm78-9fvv-mhgr](https://redirect.github.com/advisories/GHSA-jm78-9fvv-mhgr)\n\n<details>\n<summary>More
        information</summary>\n\n#### Details\n##### Summary\nGitPython's config-name
        validator only neutralizes CR/LF/NUL for the `\"option\"` label; it does not
        reject `=`, `#`, `;`, `[`, `]`, or whitespace in an **option name**. `write_section`
        writes the option name verbatim into the config file, so an option name such
        as `sshCommand = touch <cmd> #` is written as `\\tsshCommand = touch <cmd>
        # = <value>`, which git parses as `core.sshCommand = touch <cmd>` (the trailing
        `#` comments out the intended value). This forges arbitrary config directives
        (`core.sshCommand`, `core.hooksPath`, `alias.*`) \u2192 RCE on the next git
        operation. This is a distinct field (option name, not section name) and distinct
        character class (`=`/`#`/space, not newline/bracket) from GHSA-3rp5-jjmw-4wv2
        (section-name bracket injection) and GHSA-mv93-w799-cj2w / GHSA-v87r-6q3f-2j67
        (newline injection).\n\n##### Root Cause\n`_assure_config_name_safe(name,
        label)` (`git/config.py:897`) applies the bracket/quote state machine ONLY
        when `label == \"section\"`; for the `\"option\"` label it falls through with
        just the `UNSAFE_CONFIG_CHARS_RE = [\\r\\n\\x00]` regex. `write_section` then
        writes the option name verbatim into `\"\\t%s = %s\\n\"` (config.py:702).\n\n#####
        Impact\nArbitrary git-config directive injection \u2192 remote code execution
        via `core.sshCommand` (fires on any ssh git operation, no staged file needed)
        or `core.hooksPath` (with a staged hook). Requires the embedding application
        to forward a caller-influenced OPTION NAME into the config writer (name-control
        model, the same name-control model accepted by the related published advisories
        GHSA-3rp5-jjmw-4wv2 and GHSA-mv93-w799-cj2w). Default configuration.\n\n#####
        Proof of Concept\n```python\nwith repo.config_writer() as cw:\n    cw.set_value(\"core\",
        \"sshCommand = touch /tmp/RCE #\", \"x\")\n\n##### git config --get core.sshCommand
        \ ->  touch /tmp/RCE\n```\n\n##### Attack Chain\n1. Entry: app calls config
        writer with attacker-controlled OPTION name: `set_value(\"core\", \"sshCommand
        = touch /tmp/RCE #\", \"x\")`.\n2. Check: `_assure_config_name_safe(option,
        \"option\")` @&#8203; config.py. Guard: regex matches only `[\\r\\n\\x00]`;
        bracket/quote state machine is gated on `label==\"section\"`. Bypass proof:
        `=`,`#`,space pass \u2192 no `ValueError`.\n3. Sink: `write_section` writes
        `\"\\tsshCommand = touch /tmp/RCE # = x\\n\"` (config.py:702).\n4. Impact:
        git parses `core.sshCommand=touch /tmp/RCE` \u2192 arbitrary code execution
        on next git op.\n\n##### Bypass Evidence\nIndependently reproduced (gate harness):
        `set_value('core','sshCommand = touch <RCE> #','x')` \u2192 no `ValueError`;
        file line `sshCommand = touch <RCE> # = x`; `git config --get core.sshCommand`
        \u2192 `touch <RCE>` (rc=0). Also verified `core.hooksPath` via both `GitConfigParser`
        and `repo.config_writer()`. Fix-commit read: bracket/quote checks are inside
        `if label == \"section\"`; the `\"option\"` label is not covered.\n\n#####
        Affected Versions\n`GitPython <= 3.1.57` (validator present verbatim on the
        latest release tag).\n\n##### Suggested Fix\nApply the section-name safety
        checks (reject `=`, `#`, `;`, `[`, `]`, whitespace) to the `\"option\"` label
        as well, or validate the fully-rendered config line after substitution.\n\n---\nReported
        by **zx (Jace)** \u2014 GitHub: @&#8203;manus-use\n\n#### Severity\n- CVSS
        Score: 8.8 / 10 (High)\n- Vector String: `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H`\n\n####
        References\n- [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-jm78-9fvv-mhgr](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-jm78-9fvv-mhgr)\n-
        [https://github.com/gitpython-developers/GitPython/pull/2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
        [https://github.com/gitpython-developers/GitPython/commit/a495ccd3b547ccd60b2187215823b72a9c0188bf](https://redirect.github.com/gitpython-developers/GitPython/commit/a495ccd3b547ccd60b2187215823b72a9c0188bf)\n-
        [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
        [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
        data is provided by [OSV](https://osv.dev/vulnerability/GHSA-jm78-9fvv-mhgr)
        and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
        ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
        GitPython: Unsafe git option guard bypass via split_single_char_options=False
        short-option token smuggling enables command execution\n[GHSA-wvpp-8hx9-p66j](https://redirect.github.com/advisories/GHSA-wvpp-8hx9-p66j)\n\n<details>\n<summary>More
        information</summary>\n\n#### Details\n##### Summary\nThe `check_unsafe_options`
        guard can be bypassed on every guarded method (clone/clone_from, fetch/pull/push,
        ls_remote, iter_commits, blame, archive) by combining a single-character kwarg
        with `split_single_char_options=False`. The guard's candidate list omits the
        smuggled option, but `transform_kwarg` emits a JOINED `-n<value>` argv token
        that git parses as `--upload-pack=<cmd>`, yielding arbitrary command execution
        at the default `allow_unsafe_options=False`. This is an incomplete-fix bypass
        of commit `e8d0fbf7` (the fix for GHSA-r9mr-m37c-5fr3), which only emits value-derived
        candidates when `split_single_char_options` is True.\n\n##### Root Cause\n`_option_candidates`
        derives value-token candidates only under `if len(key)==1 and split_single_char_options:`
        (cmd.py:1048, added by `e8d0fbf7`). With `split_single_char_options=False`,
        `_option_candidates([], {\"n\":\"utouch <cmd>;git-upload-pack\"})` returns
        only `['-n']` (not on the denylist), so the guard passes. But `transform_kwarg('n',
        value, split_single_char_options=False)` emits the JOINED token `-nutouch
        <cmd>;git-upload-pack` (cmd.py:1631). git clusters value-less short flags
        then parses `-u<cmd>` = `--upload-pack=<cmd>` \u2192 command execution. The
        hardened guard WOULD block the joined token if it saw it \u2014 the flaw is
        it never receives it.\n\n##### Impact\nArbitrary OS command execution as the
        host process (via `--upload-pack`) at default `allow_unsafe_options=False`,
        affecting all guarded methods that forward kwargs. Precondition: the app forwards
        a user-controlled kwargs dict containing `split_single_char_options=False`
        plus a single-char key (same user-dict-forwarding model GHSA-r9mr-m37c-5fr3
        accepts).\n\n##### Proof of Concept\n```python\nfrom git import Repo\nRepo.clone_from(src,
        dst,\n    n=\"utouch /tmp/ACE;git-upload-pack\",\n    split_single_char_options=False)
        \  # /tmp/ACE created -> ACE\n```\n\n##### Attack Chain\n1. Entry: app forwards
        user kwargs to `Repo.clone_from(url, path, **kwargs)`: `{split_single_char_options:
        False, n: 'utouch /tmp/ACE;git-upload-pack'}`.\n2. Check: `check_unsafe_options(_option_candidates([],
        kwargs), unsafe_git_clone_options)`. Guard: denylist includes `--upload-pack`/`-u`.
        Bypass proof: `_option_candidates` yields only `['-n']` (value token skipped
        because `split=False`); guard never sees `-u`.\n3. Sink: `transform_kwarg`
        emits joined token (cmd.py:1631). argv (observed): `['git','clone','-v','-nutouch
        /tmp/ACE;git-upload-pack','--','<src>','<dst>']`.\n4. Impact: git clusters
        `-n` + `-u<cmd>` \u2192 runs upload-pack command \u2192 ACE.\n\n##### Bypass
        Evidence\nIndependently reproduced (gate harness, default `allow_unsafe_options=False`):
        the `split=False` payload created the marker `VH05_GATE_ACE` (ACE); the clone
        returned normally (guard bypassed). Control: `n='--upload-pack=\u2026'` (split
        default True) \u2192 `UnsafeOptionError: --upload-pack is not allowed`. Fix-commit
        read: `e8d0fbf7` extends candidates only under `if len(key)==1 and split_single_char_options:`
        \u2014 split=False skips value emission. Also confirmed the earlier clustering-parse
        fix (commit `56806080`) does not cover this because the guard only ever receives
        `['-n']`.\n\n##### Affected Versions\n`GitPython <= 3.1.57` (code present
        verbatim on the latest release tag).\n\n##### Suggested Fix\nMake `_option_candidates`
        emit value-derived candidates regardless of `split_single_char_options` (i.e.
        also for the joined `-n<value>` form), OR run `check_unsafe_options` over
        the fully-transformed argv rather than the reconstructed name-only candidate
        list.\n\n---\nReported by **zx (Jace)** \u2014 GitHub: @&#8203;manus-use\n\n####
        Severity\n- CVSS Score: 8.8 / 10 (High)\n- Vector String: `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H`\n\n####
        References\n- [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-wvpp-8hx9-p66j](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-wvpp-8hx9-p66j)\n-
        [https://github.com/gitpython-developers/GitPython/pull/2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
        [https://github.com/gitpython-developers/GitPython/commit/96a888f4d782cb2f80452148e48e60ce4af6d541](https://redirect.github.com/gitpython-developers/GitPython/commit/96a888f4d782cb2f80452148e48e60ce4af6d541)\n-
        [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
        [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
        data is provided by [OSV](https://osv.dev/vulnerability/GHSA-wvpp-8hx9-p66j)
        and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
        ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
        Release Notes\n\n<details>\n<summary>gitpython-developers/GitPython (GitPython)</summary>\n\n###
        [`v3.1.58`](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58):
        Security and Fixes\n\n[Compare Source](https://redirect.github.com/gitpython-developers/GitPython/compare/3.1.57...3.1.58)\n\n#####
        What's Changed\n\n- test: allow Python startup before timeout by [@&#8203;Byron](https://redirect.github.com/Byron)
        in [#&#8203;2195](https://redirect.github.com/gitpython-developers/GitPython/pull/2195)\n-
        Resolve Windows hook Bash through PATH by [@&#8203;Byron](https://redirect.github.com/Byron)
        in [#&#8203;2199](https://redirect.github.com/gitpython-developers/GitPython/pull/2199)\n-
        Revert \"Resolve Windows hook Bash through PATH\" by [@&#8203;Byron](https://redirect.github.com/Byron)
        in [#&#8203;2200](https://redirect.github.com/gitpython-developers/GitPython/pull/2200)\n-
        test: focus pytest summary on unexpected failures by [@&#8203;raisulchowdhury](https://redirect.github.com/raisulchowdhury)
        in [#&#8203;2203](https://redirect.github.com/gitpython-developers/GitPython/pull/2203)\n-
        Validate submodule names before filesystem operations by [@&#8203;Byron](https://redirect.github.com/Byron)
        in [#&#8203;2202](https://redirect.github.com/gitpython-developers/GitPython/pull/2202)\n-
        Handle invalid submodule names during recursive updates by [@&#8203;Byron](https://redirect.github.com/Byron)
        in [#&#8203;2205](https://redirect.github.com/gitpython-developers/GitPython/pull/2205)\n-
        Fix Windows path handling on Python 3.13+ by [@&#8203;Byron](https://redirect.github.com/Byron)
        in [#&#8203;2196](https://redirect.github.com/gitpython-developers/GitPython/pull/2196)\n-
        fixup 2202 by [@&#8203;Byron](https://redirect.github.com/Byron) in [#&#8203;2206](https://redirect.github.com/gitpython-developers/GitPython/pull/2206)\n-
        Correct Windows hook Bash precedence by [@&#8203;Byron](https://redirect.github.com/Byron)
        in [#&#8203;2201](https://redirect.github.com/gitpython-developers/GitPython/pull/2201)\n-
        Harden config and Git option validation by [@&#8203;Byron](https://redirect.github.com/Byron)
        in [#&#8203;2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
        Skip tests that need symlink privileges instead of erroring by [@&#8203;Cyrus580529](https://redirect.github.com/Cyrus580529)
        in [#&#8203;2197](https://redirect.github.com/gitpython-developers/GitPython/pull/2197)\n\n#####
        New Contributors\n\n- [@&#8203;raisulchowdhury](https://redirect.github.com/raisulchowdhury)
        made their first contribution in [#&#8203;2203](https://redirect.github.com/gitpython-developers/GitPython/pull/2203)\n-
        [@&#8203;Cyrus580529](https://redirect.github.com/Cyrus580529) made their
        first contribution in [#&#8203;2197](https://redirect.github.com/gitpython-developers/GitPython/pull/2197)\n\n**Full
        Changelog**: <https://github.com/gitpython-developers/GitPython/compare/3.1.57...3.1.58>\n\n</details>\n\n---\n\n###
        Configuration\n\n\U0001F4C5 **Schedule**: (UTC)\n\n- Branch creation\n  -
        At any time (no schedule defined)\n- Automerge\n  - At any time (no schedule
        defined)\n\n\U0001F6A6 **Automerge**: Disabled by config. Please merge this
        manually once you are satisfied.\n\n\u267B **Rebasing**: Whenever PR becomes
        conflicted, or you tick the rebase/retry checkbox.\n\n\U0001F515 **Ignore**:
        Close this PR and you won't be reminded about these updates again.\n\n---\n\n
        - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this
        box\n\n---\n\nThis PR was generated by [Mend Renovate](https://mend.io/renovate/).
        View the [repository job log](https://developer.mend.io/github/osism/python-osism).\n<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMi4wIiwidXBkYXRlZEluVmVyIjoiNDQuMTIuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsicmVub3ZhdGUiXX0=-->\n"
      change_url: https://github.com/osism/python-osism/pull/2587
      child_jobs: []
      commit_id: 8f8d2989b17d7199dea1d0770f90e6edaa6b261f
      event_id: c5018050-928d-11f1-9d05-b18d5710138f
      executor:
        hostname: 521e9411259a
        inventory_file: /var/lib/zuul/builds/7f1acc74191f4b5bb7089398b257758c/ansible/inventory.yaml
        log_root: /var/lib/zuul/builds/7f1acc74191f4b5bb7089398b257758c/work/logs
        result_data_file: /var/lib/zuul/builds/7f1acc74191f4b5bb7089398b257758c/work/results.json
        src_root: /var/lib/zuul/builds/7f1acc74191f4b5bb7089398b257758c/work/src
        work_root: /var/lib/zuul/builds/7f1acc74191f4b5bb7089398b257758c/work
      include_vars: []
      items:
      - branch: main
        change: '2587'
        change_message: "chore(deps): update dependency gitpython to v3.1.58 [security]\n\nThis
          PR contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/)
          | [Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n|
          [GitPython](https://redirect.github.com/gitpython-developers/GitPython)
          | `==3.1.57` \u2192 `==3.1.58` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/gitpython/3.1.58?slim=true)
          | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/gitpython/3.1.57/3.1.58?slim=true)
          |\n\n---\n\n### GitPython: Unguarded git read-tree option forwarding in
          IndexFile.from_tree/reset/merge_tree enables arbitrary file overwrite\n[GHSA-4gmw-gg2m-w46p](https://redirect.github.com/advisories/GHSA-4gmw-gg2m-w46p)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\n`IndexFile.from_tree`,
          `IndexFile.reset` (\u2192 from_tree) and `IndexFile.merge_tree` append caller-influenced
          treeish strings positionally to `git read-tree` with no unsafe-option guard,
          no `allow_unsafe_options` parameter, and no `--` separator. `git read-tree
          --index-output=<file>` writes the resulting index to an arbitrary path,
          and last-occurrence-wins lets an injected `--index-output` override the
          method's internal temp path \u2014 clobbering an arbitrary file with a valid
          git-index blob. This is a distinct, never-guarded sink: commit `3af0c251`
          (GHSA-3f7w-8rr8-f37f) guarded only `checkout_index` and `tag`; `read_tree`
          was left unprotected (it is among the acknowledged unguarded call sites
          in that advisory's sweep but was never reported or fixed).\n\n##### Root
          Cause\n`from_tree` (index/base.py:388), `reset` (delegates to from_tree),
          and `merge_tree` (index/base.py:291) call `repo.git.read_tree(*arg_list)`
          with no `check_unsafe_options` and no `--`. The treeish is caller-influenced
          and positional.\n\n##### Impact\nArbitrary file overwrite / destruction
          at the privileges of the host process. Content is constrained to a git-index
          blob (not attacker-chosen, so not RCE), but the target path is fully attacker-controlled
          \u2014 corrupting/truncating configs or destroying files at attacker-chosen
          writable locations = I:H + A:H (per the skill's \"overwrite-any-path = I:H\"
          rule). Pure VALUE control (positional treeish). Default configuration.\n\n#####
          Proof of Concept\n```python\nIndexFile.from_tree(repo, \"--index-output=/home/victim/.bashrc\")\n\n#####
          target overwritten with a valid git-index blob (DIRC...)\n```\n\n##### Attack
          Chain\n1. Entry: app calls `IndexFile.from_tree(repo, treeish)` / `reset(commit=\u2026)`
          / `merge_tree(base=\u2026, rhs=\u2026)` with attacker `treeish=\"--index-output=/home/victim/.bashrc\"`.\n2.
          Check: NONE \u2014 the methods have no `allow_unsafe_options` and never
          call `check_unsafe_options`.\n3. Sink: `repo.git.read_tree(*arg_list)` \u2014
          no `--`. argv (from_tree, observed): `['git','read-tree','--index-output=<tmp>','--index-output=/\u2026/victim']`
          (last-wins).\n4. Impact: target path created/overwritten with a valid git-index
          blob; existing content destroyed.\n\n##### Bypass Evidence\nIndependently
          reproduced (gate harness): `IndexFile.from_tree(repo,'--index-output=<victim>')`
          \u2192 victim overwritten; before=`IMPORTANT ORIGINAL CONTENT`, after starts
          `DIRC\\x00\\x00\\x00\\x02\u2026` (destructive clobber, valid index blob).
          `reset(commit=\u2026)` and both `merge_tree` positionals verified. Fix-commit
          read: `3af0c251` touched only `checkout_index`+`tag`; `read_tree` untouched
          on HEAD.\n\n##### Affected Versions\n`GitPython <= 3.1.57` (sinks present
          verbatim on the latest release tag).\n\n##### Suggested Fix\nAdd a `check_unsafe_options`
          guard (with an `allow_unsafe_options` parameter) to `from_tree`/`reset`/`merge_tree`,
          and/or place a `--` separator before the positional treeish arguments; block
          `--index-output` (a path-taking option) on this sink.\n\n---\nReported by
          **zx (Jace)** \u2014 GitHub: @&#8203;manus-use\n\n#### Severity\n- CVSS
          Score: 8.1 / 10 (High)\n- Vector String: `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H`\n\n####
          References\n- [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-4gmw-gg2m-w46p](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-4gmw-gg2m-w46p)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
          [https://github.com/gitpython-developers/GitPython/commit/9b5dcaf85da5946dbf69dcd53f9edba08f760b32](https://redirect.github.com/gitpython-developers/GitPython/commit/9b5dcaf85da5946dbf69dcd53f9edba08f760b32)\n-
          [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
          [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-4gmw-gg2m-w46p)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          GitPython: Unguarded git option forwarding in Repo.init enables arbitrary
          command execution via --template clone hooks\n[GHSA-9rj7-rf2p-w77r](https://redirect.github.com/advisories/GHSA-9rj7-rf2p-w77r)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\n`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 \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\n#####
          attacker stages /evil/hooks/post-commit (executable)\nfrom git import Repo\nRepo.init(path,
          template=\"/evil\")\n\n##### next commit runs /evil/hooks/post-commit ->
          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='/evil')`.\n2.
          Check: NONE on `Repo.init`. Bypass proof: base.py:1435 is a bare `git.init(**kwargs)`.
          argv (observed): `['git','init','--template=/evil']`.\n3. Sink: git copies
          `/evil/hooks/post-commit` \u2192 `<repo>/.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='<evil>')`
          \u2192 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).\n\n##### Affected
          Versions\n`GitPython <= 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:
          @&#8203;manus-use\n\n#### Severity\n- CVSS Score: 7.5 / 10 (High)\n- Vector
          String: `CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H`\n\n#### References\n-
          [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-9rj7-rf2p-w77r](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-9rj7-rf2p-w77r)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
          [https://github.com/gitpython-developers/GitPython/commit/d9ddb55bdc66](https://redirect.github.com/gitpython-developers/GitPython/commit/d9ddb55bdc66)\n-
          [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
          [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-9rj7-rf2p-w77r)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          GitPython: Arbitrary file read via --pathspec-from-file in IndexFile.remove()
          and Head.checkout()\n[GHSA-hh9p-6wh2-4mfc](https://redirect.github.com/advisories/GHSA-hh9p-6wh2-4mfc)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\n\n`IndexFile.remove()`
          and `Head.checkout()` forward `**kwargs` into `git rm` and `git checkout`\nwith
          no guard. Passing `--pathspec-from-file=<file>` **together with `--pathspec-file-nul`**\nmakes
          Git treat the whole file as a single NUL-delimited pathspec, and the unmatched-pathspec\nerror
          quotes it verbatim. GitPython surfaces that through `GitCommandError.stderr`,
          so the\nentire contents of a caller-chosen file are returned to the caller
          in band.\n\nThis is the same primitive as Instance 2 of\n[GHSA-3f7w-8rr8-f37f](https://redirect.github.com/advisories/GHSA-3f7w-8rr8-f37f)
          - `TagReference.create()`\nwith `-F`, arbitrary file read returned in band
          - at two sites that advisory assessed and\ncleared.\n\n##### Prior art,
          and why I am filing rather than commenting\n\nGHSA-3f7w-8rr8-f37f's sweep
          table lists these four sites with the assessment\n*\"`--pathspec-from-file`
          only reads a pathspec; no write or disclosure primitive found\"*:\n\n| Call
          site | git command | that advisory's assessment |\n|---|---|---|\n| `IndexFile.remove()`
          | `rm` | `--pathspec-from-file` only reads a pathspec; no write or disclosure
          primitive found |\n| `IndexFile.move()` | `mv` | same |\n| `HEAD.reset()`
          | `reset` | same |\n| `HEAD.checkout()` | `checkout` | same |\n\nThat assessment
          is very nearly right, and I think that is why it held: with\n`--pathspec-from-file`
          alone, Git splits on newlines and the error quotes only the **first\nline**,
          which reads as an uninteresting partial. Adding `--pathspec-file-nul` -
          a sibling flag\nof the same option, and the documented way to handle paths
          containing newlines - makes the\nwhole file one pathspec.\n\n##### Root
          cause\n\n`git/index/base.py:991-1043`:\n\n```python\ndef remove(self, items,
          working_tree=False, **kwargs):\n    ...\n    removed_paths = self.repo.git.rm(args,
          paths, **kwargs).splitlines()   # line 1043\n```\n\n`git/refs/head.py:237-268`:\n\n```python\ndef
          checkout(self, force: bool = False, **kwargs: Any):\n    ...\n    self.repo.git.checkout(self,
          **kwargs)                                 # line 268\n```\n\nNeither has
          an `allow_unsafe_options` parameter or a `check_unsafe_options()` call.\n\n#####
          Proof of concept\n\n```python\nfrom git import Repo\nfrom git.exc import
          GitCommandError\n\nrepo = Repo(\"/path/to/repo\")\nkw = dict(pathspec_from_file=\"/etc/passwd\",
          pathspec_file_nul=True)\n\ntry:\n    repo.index.remove([], **kw)          #
          or: repo.heads[0].checkout(**kw)\nexcept GitCommandError as e:\n    print(e.stderr)
          \                     # <- entire file contents\n```\n\nObserved on published
          3.1.57, against a canary file holding three marked lines:\n\n```\n[PASS]
          IndexFile.remove() -> `git rm` returns ALL 3 canary lines in-band\n       stderr:
          'fatal: pathspec 'LINE1-CANARY-4242\n       LINE2-SECRET-7777\n       LINE3-TAIL-9999\n
          \      ' did not match any files'\n[PASS] Head.checkout() -> `git checkout`
          returns ALL 3 canary lines in-band\n       stderr: 'error: pathspec 'LINE1-CANARY-4242\n
          \      LINE2-SECRET-7777\n       LINE3-TAIL-9999\n       ' did not match
          any file(s) known to git'\n[PASS] PRECISION: `git status` leaks 0/3 -- not
          every unguarded site discloses\n[PASS] PRECISION: the GUARDED checkout-index
          leaks 0/3\n```\n\nThe two precision controls are there so the result is
          about these sinks and not about the\ncanary being visible everywhere.\n\n#####
          Scope correction to the table above\n\nOf the four sites cleared with that
          sentence, **two disclose and two do not**:\n\n| Call site | disclosed? |\n|---|---|\n|
          `IndexFile.remove()` \u2192 `git rm` | **yes, full file** |\n| `Head.checkout()`
          \u2192 `git checkout` | **yes, full file** |\n| `HEAD.reset()` \u2192 `git
          reset` | no - `git reset` does not error on unmatched pathspecs |\n| `IndexFile.move()`
          \u2192 `git mv` | no |\n\nThe two negatives are mentioned because \"the
          dismissal was wrong\" would overstate it: the\ndismissal was wrong for half
          of what it covered.\n\n#### Severity\n- CVSS Score: 6.5 / 10 (Medium)\n-
          Vector String: `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N`\n\n#### References\n-
          [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-hh9p-6wh2-4mfc](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-hh9p-6wh2-4mfc)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
          [https://github.com/gitpython-developers/GitPython/commit/f2550b65bf60ca087190981e2c7b6865e201f40c](https://redirect.github.com/gitpython-developers/GitPython/commit/f2550b65bf60ca087190981e2c7b6865e201f40c)\n-
          [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
          [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-hh9p-6wh2-4mfc)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          GitPython: Arbitrary Git Repository Creation Outside the Working Tree via
          Unvalidated .gitmodules Submodule Name in GitPython\n[GHSA-hmq2-w58f-27jc](https://redirect.github.com/advisories/GHSA-hmq2-w58f-27jc)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\nGitPython computes
          the on-disk location of a submodule's separate Git directory (`.git/modules/<name>`)
          from the submodule's `.gitmodules` section name with no validation. Because
          that name is fully attacker-controlled content of a cloned repository, a
          malicious repository can set a submodule name to a traversal string (e.g.
          `../../../../home/victim/.something`) and cause GitPython to create and
          initialize a full Git repository at an attacker-chosen filesystem path outside
          the intended clone directory. The only precondition is that a victim clones
          the malicious repository with GitPython and runs submodule initialization
          (`submodule_update(init=True)` / `sm.update(init=True)`), a very common
          and often automatic step. Core Git itself already blocks this exact attack
          class (CVE-2018-11235), but GitPython's independent reimplementation never
          adopted an equivalent check.\n\n##### Details\n`src/GitPython/git/objects/submodule/util.py`
          `sm_name()` strips the `submodule \"` / `\"` wrapper from a `.gitmodules`
          `[submodule \"...\"]` header and returns the result unchecked. `Submodule.iter_items()`
          in `src/GitPython/git/objects/submodule/base.py` reads this via `sm_name(sms)`
          and assigns it to `sm._name`; unlike the submodule `path`, `name` is never
          used for a tree lookup, so it is never implicitly validated. `Submodule._module_abspath()`
          then builds `osp.join(parent_repo.git_dir, \"modules\", name)` - `os.path.join`
          does not normalize `../` sequences. `Submodule._clone_repo()` passes this
          value straight to `os.makedirs()` and to `git clone --separate-git-dir=<module_abspath>`,
          creating and populating a full Git repository (objects, refs, hooks, config)
          at the escaped path. Attack prerequisite: attacker controls a repository
          the victim clones and initializes submodules for.\n\n##### PoC\n1. Environment:
          Docker image built `FROM python:3.11-slim`, with `git` installed via `apt-get
          install -y git` (Debian bookworm packaged version, described in the advisory
          as \"git 2.x\"; the host-side verification separately used system git `2.34.1`,
          but no exact version is pinned for the git binary inside this Docker image).
          GitPython is installed inside the container via `pip install /src/GitPython`
          from this repository's own source, which the advisory states resolved to
          the officially released `GitPython==3.1.57` and `gitdb==4.0.12`.\n2. Configuration
          / preconditions: None beyond what's described - the victim must clone the
          attacker's repository with GitPython and run submodule initialization (`repo.submodules`
          + `sm.update(init=True)`, equivalent to `git submodule update --init`).\n3.
          Commands run (quoted verbatim from the advisory's \"Confirmed test run\"
          section):\n```bash\n$ docker build -f GHSA/testing/Dockerfile -t ghsa-gitpython-poc
          .\n$ docker run --rm ghsa-gitpython-poc\n```\n(Per the Dockerfile, `docker
          run` executes `/work/run_all.sh`, which in turn runs `build_attacker_repo.sh`,
          then `poc_gitpython.py`, then `poc_control_realgit.sh`.)\n4. Full source
          of the PoC script (`GHSA/testing/poc_gitpython.py`), verbatim:\n```python\n\"\"\"GHSA-001
          PoC: GitPython side.\n\nClones the attacker repo and runs the equivalent
          of\n`git submodule update --init` via GitPython, then checks whether a git\nrepository
          was created outside the clone directory.\n\"\"\"\nimport os\nimport shutil\n\nimport
          git\n\nCLONE_DIR = '/work/victim_clone/repo'\nESCAPE_TARGET = '/tmp/gitpython_poc_escaped_root'\n\ndef
          main():\n    shutil.rmtree(os.path.dirname(CLONE_DIR), ignore_errors=True)\n
          \   shutil.rmtree(ESCAPE_TARGET, ignore_errors=True)\n    os.makedirs(os.path.dirname(CLONE_DIR),
          exist_ok=True)\n\n    print(f'GitPython version: {git.__version__}')\n    repo
          = git.Repo.clone_from('/work/attacker_repo', CLONE_DIR)\n    print('Cloned
          into:', repo.working_tree_dir)\n\n    sms = list(repo.submodules)\n    for
          sm in sms:\n        print('  submodule name:', repr(sm.name))\n        print('
          \ submodule path:', repr(sm.path))\n\n    print('escape_target exists before
          update:', os.path.exists(ESCAPE_TARGET))\n\n    for sm in sms:\n        try:\n
          \           sm.update(init=True)\n        except Exception as e:\n            print('sm.update
          raised:', repr(e))\n\n    exists = os.path.exists(ESCAPE_TARGET)\n    print('escape_target
          exists after update:', exists)\n    if exists:\n        print('escape_target
          contents:', os.listdir(ESCAPE_TARGET))\n\n    print('POC_RESULT=VULNERABLE'
          if exists else 'POC_RESULT=SAFE')\n\nif __name__ == '__main__':\n    main()\n```\n5.
          Exact captured terminal output (verbatim, from the original advisory's \"Confirmed
          test run (Docker, released package)\" section):\n```\n=== GitPython PoC
          (vulnerable path) ===\nGitPython version: 3.1.57\nCloned into: /work/victim_clone/repo\n
          \ submodule name: '../../../../../../tmp/gitpython_poc_escaped_root/modules_dir'\n
          \ submodule path: 'legit_dir'\nescape_target exists before update: False\nescape_target
          exists after update: True\nescape_target contents: ['modules_dir']\nPOC_RESULT=VULNERABLE\n\n===
          Control: real git CLI on identical repo ===\nwarning: ignoring suspicious
          submodule name: ../../../../../../tmp/gitpython_poc_escaped_root/modules_dir\nwarning:
          ignoring suspicious submodule name: ../../../../../../tmp/gitpython_poc_escaped_root/modules_dir\nfatal:
          No url found for submodule path 'legit_dir' in .gitmodules\nCONTROL_RESULT=SAFE
          (real git correctly refused)\n```\n6. Payload: the attacker rewrites the
          `.gitmodules` section header from `[submodule \"legit_dir\"]` to `[submodule
          \"../../../../../../tmp/gitpython_poc_escaped_root/modules_dir\"]` (built
          by `build_attacker_repo.sh`, part of the harness in `GHSA/testing/`). The
          malicious part is the `../../../../../../` traversal sequence embedded in
          the submodule *name* (not the tree-validated `path`), which becomes the
          on-disk target for the submodule's separate git directory.\n7. Expected
          vs. observed: A safe implementation (as demonstrated by the real `git` CLI
          control run) rejects the submodule name with \"ignoring suspicious submodule
          name\" and refuses to create anything outside the repository. GitPython
          instead created the escape-target directory and a fully-initialized Git
          repository at `/tmp/gitpython_poc_escaped_root/modules_dir`, confirmed by
          `escape_target exists after update: True` and its listed contents.\n8. Security
          impact demonstrated: arbitrary filesystem directory and Git-repository creation
          at an attacker-chosen absolute path outside the victim's intended clone
          directory, populated with attacker-controlled content sourced from the submodule's
          own (also attacker-controlled) `url`.\n\n##### Impact\nPath traversal (CWE-22)
          / external control of file path (CWE-73) leading to arbitrary directory
          and Git-repository creation outside the intended clone directory. Integrity
          impact is High (attacker chooses destination path and, via the submodule
          URL, much of the written content); Confidentiality impact is None (only
          creation was demonstrated); Availability impact is Low-Medium (disk-exhaustion
          potential). No authentication is required; the attacker only needs to control
          a repository the victim clones and initializes submodules for - a routine,
          often fully-automatic operation in CI pipelines, IDE integrations, and dependency-management
          tooling.\n\n#### Severity\n- CVSS Score: 8.2 / 10 (High)\n- Vector String:
          `CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:N/I:H/A:L`\n\n#### References\n- [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-hmq2-w58f-27jc](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-hmq2-w58f-27jc)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2202](https://redirect.github.com/gitpython-developers/GitPython/pull/2202)\n-
          [https://github.com/gitpython-developers/GitPython/commit/4299c990e1ca21896f9485277caf7bb0ae5b404c](https://redirect.github.com/gitpython-developers/GitPython/commit/4299c990e1ca21896f9485277caf7bb0ae5b404c)\n-
          [https://github.com/gitpython-developers/GitPython/commit/e4b8e7d026ca6abb4cf604f8e77093432ce23c06](https://redirect.github.com/gitpython-developers/GitPython/commit/e4b8e7d026ca6abb4cf604f8e77093432ce23c06)\n-
          [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
          [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-hmq2-w58f-27jc)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          GitPython: git-config OPTION-name injection via =/#/whitespace bypasses
          name validator, enabling forged core.sshCommand/hooksPath (RCE)\n[GHSA-jm78-9fvv-mhgr](https://redirect.github.com/advisories/GHSA-jm78-9fvv-mhgr)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\nGitPython's config-name
          validator only neutralizes CR/LF/NUL for the `\"option\"` label; it does
          not reject `=`, `#`, `;`, `[`, `]`, or whitespace in an **option name**.
          `write_section` writes the option name verbatim into the config file, so
          an option name such as `sshCommand = touch <cmd> #` is written as `\\tsshCommand
          = touch <cmd> # = <value>`, which git parses as `core.sshCommand = touch
          <cmd>` (the trailing `#` comments out the intended value). This forges arbitrary
          config directives (`core.sshCommand`, `core.hooksPath`, `alias.*`) \u2192
          RCE on the next git operation. This is a distinct field (option name, not
          section name) and distinct character class (`=`/`#`/space, not newline/bracket)
          from GHSA-3rp5-jjmw-4wv2 (section-name bracket injection) and GHSA-mv93-w799-cj2w
          / GHSA-v87r-6q3f-2j67 (newline injection).\n\n##### Root Cause\n`_assure_config_name_safe(name,
          label)` (`git/config.py:897`) applies the bracket/quote state machine ONLY
          when `label == \"section\"`; for the `\"option\"` label it falls through
          with just the `UNSAFE_CONFIG_CHARS_RE = [\\r\\n\\x00]` regex. `write_section`
          then writes the option name verbatim into `\"\\t%s = %s\\n\"` (config.py:702).\n\n#####
          Impact\nArbitrary git-config directive injection \u2192 remote code execution
          via `core.sshCommand` (fires on any ssh git operation, no staged file needed)
          or `core.hooksPath` (with a staged hook). Requires the embedding application
          to forward a caller-influenced OPTION NAME into the config writer (name-control
          model, the same name-control model accepted by the related published advisories
          GHSA-3rp5-jjmw-4wv2 and GHSA-mv93-w799-cj2w). Default configuration.\n\n#####
          Proof of Concept\n```python\nwith repo.config_writer() as cw:\n    cw.set_value(\"core\",
          \"sshCommand = touch /tmp/RCE #\", \"x\")\n\n##### git config --get core.sshCommand
          \ ->  touch /tmp/RCE\n```\n\n##### Attack Chain\n1. Entry: app calls config
          writer with attacker-controlled OPTION name: `set_value(\"core\", \"sshCommand
          = touch /tmp/RCE #\", \"x\")`.\n2. Check: `_assure_config_name_safe(option,
          \"option\")` @&#8203; config.py. Guard: regex matches only `[\\r\\n\\x00]`;
          bracket/quote state machine is gated on `label==\"section\"`. Bypass proof:
          `=`,`#`,space pass \u2192 no `ValueError`.\n3. Sink: `write_section` writes
          `\"\\tsshCommand = touch /tmp/RCE # = x\\n\"` (config.py:702).\n4. Impact:
          git parses `core.sshCommand=touch /tmp/RCE` \u2192 arbitrary code execution
          on next git op.\n\n##### Bypass Evidence\nIndependently reproduced (gate
          harness): `set_value('core','sshCommand = touch <RCE> #','x')` \u2192 no
          `ValueError`; file line `sshCommand = touch <RCE> # = x`; `git config --get
          core.sshCommand` \u2192 `touch <RCE>` (rc=0). Also verified `core.hooksPath`
          via both `GitConfigParser` and `repo.config_writer()`. Fix-commit read:
          bracket/quote checks are inside `if label == \"section\"`; the `\"option\"`
          label is not covered.\n\n##### Affected Versions\n`GitPython <= 3.1.57`
          (validator present verbatim on the latest release tag).\n\n##### Suggested
          Fix\nApply the section-name safety checks (reject `=`, `#`, `;`, `[`, `]`,
          whitespace) to the `\"option\"` label as well, or validate the fully-rendered
          config line after substitution.\n\n---\nReported by **zx (Jace)** \u2014
          GitHub: @&#8203;manus-use\n\n#### Severity\n- CVSS Score: 8.8 / 10 (High)\n-
          Vector String: `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H`\n\n#### References\n-
          [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-jm78-9fvv-mhgr](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-jm78-9fvv-mhgr)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
          [https://github.com/gitpython-developers/GitPython/commit/a495ccd3b547ccd60b2187215823b72a9c0188bf](https://redirect.github.com/gitpython-developers/GitPython/commit/a495ccd3b547ccd60b2187215823b72a9c0188bf)\n-
          [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
          [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-jm78-9fvv-mhgr)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          GitPython: Unsafe git option guard bypass via split_single_char_options=False
          short-option token smuggling enables command execution\n[GHSA-wvpp-8hx9-p66j](https://redirect.github.com/advisories/GHSA-wvpp-8hx9-p66j)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\nThe `check_unsafe_options`
          guard can be bypassed on every guarded method (clone/clone_from, fetch/pull/push,
          ls_remote, iter_commits, blame, archive) by combining a single-character
          kwarg with `split_single_char_options=False`. The guard's candidate list
          omits the smuggled option, but `transform_kwarg` emits a JOINED `-n<value>`
          argv token that git parses as `--upload-pack=<cmd>`, yielding arbitrary
          command execution at the default `allow_unsafe_options=False`. This is an
          incomplete-fix bypass of commit `e8d0fbf7` (the fix for GHSA-r9mr-m37c-5fr3),
          which only emits value-derived candidates when `split_single_char_options`
          is True.\n\n##### Root Cause\n`_option_candidates` derives value-token candidates
          only under `if len(key)==1 and split_single_char_options:` (cmd.py:1048,
          added by `e8d0fbf7`). With `split_single_char_options=False`, `_option_candidates([],
          {\"n\":\"utouch <cmd>;git-upload-pack\"})` returns only `['-n']` (not on
          the denylist), so the guard passes. But `transform_kwarg('n', value, split_single_char_options=False)`
          emits the JOINED token `-nutouch <cmd>;git-upload-pack` (cmd.py:1631). git
          clusters value-less short flags then parses `-u<cmd>` = `--upload-pack=<cmd>`
          \u2192 command execution. The hardened guard WOULD block the joined token
          if it saw it \u2014 the flaw is it never receives it.\n\n##### Impact\nArbitrary
          OS command execution as the host process (via `--upload-pack`) at default
          `allow_unsafe_options=False`, affecting all guarded methods that forward
          kwargs. Precondition: the app forwards a user-controlled kwargs dict containing
          `split_single_char_options=False` plus a single-char key (same user-dict-forwarding
          model GHSA-r9mr-m37c-5fr3 accepts).\n\n##### Proof of Concept\n```python\nfrom
          git import Repo\nRepo.clone_from(src, dst,\n    n=\"utouch /tmp/ACE;git-upload-pack\",\n
          \   split_single_char_options=False)   # /tmp/ACE created -> ACE\n```\n\n#####
          Attack Chain\n1. Entry: app forwards user kwargs to `Repo.clone_from(url,
          path, **kwargs)`: `{split_single_char_options: False, n: 'utouch /tmp/ACE;git-upload-pack'}`.\n2.
          Check: `check_unsafe_options(_option_candidates([], kwargs), unsafe_git_clone_options)`.
          Guard: denylist includes `--upload-pack`/`-u`. Bypass proof: `_option_candidates`
          yields only `['-n']` (value token skipped because `split=False`); guard
          never sees `-u`.\n3. Sink: `transform_kwarg` emits joined token (cmd.py:1631).
          argv (observed): `['git','clone','-v','-nutouch /tmp/ACE;git-upload-pack','--','<src>','<dst>']`.\n4.
          Impact: git clusters `-n` + `-u<cmd>` \u2192 runs upload-pack command \u2192
          ACE.\n\n##### Bypass Evidence\nIndependently reproduced (gate harness, default
          `allow_unsafe_options=False`): the `split=False` payload created the marker
          `VH05_GATE_ACE` (ACE); the clone returned normally (guard bypassed). Control:
          `n='--upload-pack=\u2026'` (split default True) \u2192 `UnsafeOptionError:
          --upload-pack is not allowed`. Fix-commit read: `e8d0fbf7` extends candidates
          only under `if len(key)==1 and split_single_char_options:` \u2014 split=False
          skips value emission. Also confirmed the earlier clustering-parse fix (commit
          `56806080`) does not cover this because the guard only ever receives `['-n']`.\n\n#####
          Affected Versions\n`GitPython <= 3.1.57` (code present verbatim on the latest
          release tag).\n\n##### Suggested Fix\nMake `_option_candidates` emit value-derived
          candidates regardless of `split_single_char_options` (i.e. also for the
          joined `-n<value>` form), OR run `check_unsafe_options` over the fully-transformed
          argv rather than the reconstructed name-only candidate list.\n\n---\nReported
          by **zx (Jace)** \u2014 GitHub: @&#8203;manus-use\n\n#### Severity\n- CVSS
          Score: 8.8 / 10 (High)\n- Vector String: `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H`\n\n####
          References\n- [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-wvpp-8hx9-p66j](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-wvpp-8hx9-p66j)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
          [https://github.com/gitpython-developers/GitPython/commit/96a888f4d782cb2f80452148e48e60ce4af6d541](https://redirect.github.com/gitpython-developers/GitPython/commit/96a888f4d782cb2f80452148e48e60ce4af6d541)\n-
          [https://github.com/gitpython-developers/GitPython](https://redirect.github.com/gitpython-developers/GitPython)\n-
          [https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-wvpp-8hx9-p66j)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          Release Notes\n\n<details>\n<summary>gitpython-developers/GitPython (GitPython)</summary>\n\n###
          [`v3.1.58`](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.58):
          Security and Fixes\n\n[Compare Source](https://redirect.github.com/gitpython-developers/GitPython/compare/3.1.57...3.1.58)\n\n#####
          What's Changed\n\n- test: allow Python startup before timeout by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2195](https://redirect.github.com/gitpython-developers/GitPython/pull/2195)\n-
          Resolve Windows hook Bash through PATH by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2199](https://redirect.github.com/gitpython-developers/GitPython/pull/2199)\n-
          Revert \"Resolve Windows hook Bash through PATH\" by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2200](https://redirect.github.com/gitpython-developers/GitPython/pull/2200)\n-
          test: focus pytest summary on unexpected failures by [@&#8203;raisulchowdhury](https://redirect.github.com/raisulchowdhury)
          in [#&#8203;2203](https://redirect.github.com/gitpython-developers/GitPython/pull/2203)\n-
          Validate submodule names before filesystem operations by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2202](https://redirect.github.com/gitpython-developers/GitPython/pull/2202)\n-
          Handle invalid submodule names during recursive updates by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2205](https://redirect.github.com/gitpython-developers/GitPython/pull/2205)\n-
          Fix Windows path handling on Python 3.13+ by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2196](https://redirect.github.com/gitpython-developers/GitPython/pull/2196)\n-
          fixup 2202 by [@&#8203;Byron](https://redirect.github.com/Byron) in [#&#8203;2206](https://redirect.github.com/gitpython-developers/GitPython/pull/2206)\n-
          Correct Windows hook Bash precedence by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2201](https://redirect.github.com/gitpython-developers/GitPython/pull/2201)\n-
          Harden config and Git option validation by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2204](https://redirect.github.com/gitpython-developers/GitPython/pull/2204)\n-
          Skip tests that need symlink privileges instead of erroring by [@&#8203;Cyrus580529](https://redirect.github.com/Cyrus580529)
          in [#&#8203;2197](https://redirect.github.com/gitpython-developers/GitPython/pull/2197)\n\n#####
          New Contributors\n\n- [@&#8203;raisulchowdhury](https://redirect.github.com/raisulchowdhury)
          made their first contribution in [#&#8203;2203](https://redirect.github.com/gitpython-developers/GitPython/pull/2203)\n-
          [@&#8203;Cyrus580529](https://redirect.github.com/Cyrus580529) made their
          first contribution in [#&#8203;2197](https://redirect.github.com/gitpython-developers/GitPython/pull/2197)\n\n**Full
          Changelog**: <https://github.com/gitpython-developers/GitPython/compare/3.1.57...3.1.58>\n\n</details>\n\n---\n\n###
          Configuration\n\n\U0001F4C5 **Schedule**: (UTC)\n\n- Branch creation\n  -
          At any time (no schedule defined)\n- Automerge\n  - At any time (no schedule
          defined)\n\n\U0001F6A6 **Automerge**: Disabled by config. Please merge this
          manually once you are satisfied.\n\n\u267B **Rebasing**: Whenever PR becomes
          conflicted, or you tick the rebase/retry checkbox.\n\n\U0001F515 **Ignore**:
          Close this PR and you won't be reminded about these updates again.\n\n---\n\n
          - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this
          box\n\n---\n\nThis PR was generated by [Mend Renovate](https://mend.io/renovate/).
          View the [repository job log](https://developer.mend.io/github/osism/python-osism).\n<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMi4wIiwidXBkYXRlZEluVmVyIjoiNDQuMTIuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsicmVub3ZhdGUiXX0=-->\n"
        change_url: https://github.com/osism/python-osism/pull/2587
        commit_id: 8f8d2989b17d7199dea1d0770f90e6edaa6b261f
        patchset: 8f8d2989b17d7199dea1d0770f90e6edaa6b261f
        project:
          canonical_hostname: github.com
          canonical_name: github.com/osism/python-osism
          name: osism/python-osism
          short_name: python-osism
          src_dir: src/github.com/osism/python-osism
        topic: null
      job: mypy
      jobtags: []
      max_attempts: 3
      message: Y2hvcmUoZGVwcyk6IHVwZGF0ZSBkZXBlbmRlbmN5IGdpdHB5dGhvbiB0byB2My4xLjU4IFtzZWN1cml0eV0KClRoaXMgUFIgY29udGFpbnMgdGhlIGZvbGxvd2luZyB1cGRhdGVzOgoKfCBQYWNrYWdlIHwgQ2hhbmdlIHwgW0FnZV0oaHR0cHM6Ly9kb2NzLnJlbm92YXRlYm90LmNvbS9tZXJnZS1jb25maWRlbmNlLykgfCBbQ29uZmlkZW5jZV0oaHR0cHM6Ly9kb2NzLnJlbm92YXRlYm90LmNvbS9tZXJnZS1jb25maWRlbmNlLykgfAp8LS0tfC0tLXwtLS18LS0tfAp8IFtHaXRQeXRob25dKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24pIHwgYD09My4xLjU3YCDihpIgYD09My4xLjU4YCB8ICFbYWdlXShodHRwczovL2RldmVsb3Blci5tZW5kLmlvL2FwaS9tYy9iYWRnZXMvYWdlL3B5cGkvZ2l0cHl0aG9uLzMuMS41OD9zbGltPXRydWUpIHwgIVtjb25maWRlbmNlXShodHRwczovL2RldmVsb3Blci5tZW5kLmlvL2FwaS9tYy9iYWRnZXMvY29uZmlkZW5jZS9weXBpL2dpdHB5dGhvbi8zLjEuNTcvMy4xLjU4P3NsaW09dHJ1ZSkgfAoKLS0tCgojIyMgR2l0UHl0aG9uOiBVbmd1YXJkZWQgZ2l0IHJlYWQtdHJlZSBvcHRpb24gZm9yd2FyZGluZyBpbiBJbmRleEZpbGUuZnJvbV90cmVlL3Jlc2V0L21lcmdlX3RyZWUgZW5hYmxlcyBhcmJpdHJhcnkgZmlsZSBvdmVyd3JpdGUKW0dIU0EtNGdtdy1nZzJtLXc0NnBdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9hZHZpc29yaWVzL0dIU0EtNGdtdy1nZzJtLXc0NnApCgo8ZGV0YWlscz4KPHN1bW1hcnk+TW9yZSBpbmZvcm1hdGlvbjwvc3VtbWFyeT4KCiMjIyMgRGV0YWlscwojIyMjIyBTdW1tYXJ5CmBJbmRleEZpbGUuZnJvbV90cmVlYCwgYEluZGV4RmlsZS5yZXNldGAgKOKGkiBmcm9tX3RyZWUpIGFuZCBgSW5kZXhGaWxlLm1lcmdlX3RyZWVgIGFwcGVuZCBjYWxsZXItaW5mbHVlbmNlZCB0cmVlaXNoIHN0cmluZ3MgcG9zaXRpb25hbGx5IHRvIGBnaXQgcmVhZC10cmVlYCB3aXRoIG5vIHVuc2FmZS1vcHRpb24gZ3VhcmQsIG5vIGBhbGxvd191bnNhZmVfb3B0aW9uc2AgcGFyYW1ldGVyLCBhbmQgbm8gYC0tYCBzZXBhcmF0b3IuIGBnaXQgcmVhZC10cmVlIC0taW5kZXgtb3V0cHV0PTxmaWxlPmAgd3JpdGVzIHRoZSByZXN1bHRpbmcgaW5kZXggdG8gYW4gYXJiaXRyYXJ5IHBhdGgsIGFuZCBsYXN0LW9jY3VycmVuY2Utd2lucyBsZXRzIGFuIGluamVjdGVkIGAtLWluZGV4LW91dHB1dGAgb3ZlcnJpZGUgdGhlIG1ldGhvZCdzIGludGVybmFsIHRlbXAgcGF0aCDigJQgY2xvYmJlcmluZyBhbiBhcmJpdHJhcnkgZmlsZSB3aXRoIGEgdmFsaWQgZ2l0LWluZGV4IGJsb2IuIFRoaXMgaXMgYSBkaXN0aW5jdCwgbmV2ZXItZ3VhcmRlZCBzaW5rOiBjb21taXQgYDNhZjBjMjUxYCAoR0hTQS0zZjd3LThycjgtZjM3ZikgZ3VhcmRlZCBvbmx5IGBjaGVja291dF9pbmRleGAgYW5kIGB0YWdgOyBgcmVhZF90cmVlYCB3YXMgbGVmdCB1bnByb3RlY3RlZCAoaXQgaXMgYW1vbmcgdGhlIGFja25vd2xlZGdlZCB1bmd1YXJkZWQgY2FsbCBzaXRlcyBpbiB0aGF0IGFkdmlzb3J5J3Mgc3dlZXAgYnV0IHdhcyBuZXZlciByZXBvcnRlZCBvciBmaXhlZCkuCgojIyMjIyBSb290IENhdXNlCmBmcm9tX3RyZWVgIChpbmRleC9iYXNlLnB5OjM4OCksIGByZXNldGAgKGRlbGVnYXRlcyB0byBmcm9tX3RyZWUpLCBhbmQgYG1lcmdlX3RyZWVgIChpbmRleC9iYXNlLnB5OjI5MSkgY2FsbCBgcmVwby5naXQucmVhZF90cmVlKCphcmdfbGlzdClgIHdpdGggbm8gYGNoZWNrX3Vuc2FmZV9vcHRpb25zYCBhbmQgbm8gYC0tYC4gVGhlIHRyZWVpc2ggaXMgY2FsbGVyLWluZmx1ZW5jZWQgYW5kIHBvc2l0aW9uYWwuCgojIyMjIyBJbXBhY3QKQXJiaXRyYXJ5IGZpbGUgb3ZlcndyaXRlIC8gZGVzdHJ1Y3Rpb24gYXQgdGhlIHByaXZpbGVnZXMgb2YgdGhlIGhvc3QgcHJvY2Vzcy4gQ29udGVudCBpcyBjb25zdHJhaW5lZCB0byBhIGdpdC1pbmRleCBibG9iIChub3QgYXR0YWNrZXItY2hvc2VuLCBzbyBub3QgUkNFKSwgYnV0IHRoZSB0YXJnZXQgcGF0aCBpcyBmdWxseSBhdHRhY2tlci1jb250cm9sbGVkIOKAlCBjb3JydXB0aW5nL3RydW5jYXRpbmcgY29uZmlncyBvciBkZXN0cm95aW5nIGZpbGVzIGF0IGF0dGFja2VyLWNob3NlbiB3cml0YWJsZSBsb2NhdGlvbnMgPSBJOkggKyBBOkggKHBlciB0aGUgc2tpbGwncyAib3ZlcndyaXRlLWFueS1wYXRoID0gSTpIIiBydWxlKS4gUHVyZSBWQUxVRSBjb250cm9sIChwb3NpdGlvbmFsIHRyZWVpc2gpLiBEZWZhdWx0IGNvbmZpZ3VyYXRpb24uCgojIyMjIyBQcm9vZiBvZiBDb25jZXB0CmBgYHB5dGhvbgpJbmRleEZpbGUuZnJvbV90cmVlKHJlcG8sICItLWluZGV4LW91dHB1dD0vaG9tZS92aWN0aW0vLmJhc2hyYyIpCgojIyMjIyB0YXJnZXQgb3ZlcndyaXR0ZW4gd2l0aCBhIHZhbGlkIGdpdC1pbmRleCBibG9iIChESVJDLi4uKQpgYGAKCiMjIyMjIEF0dGFjayBDaGFpbgoxLiBFbnRyeTogYXBwIGNhbGxzIGBJbmRleEZpbGUuZnJvbV90cmVlKHJlcG8sIHRyZWVpc2gpYCAvIGByZXNldChjb21taXQ94oCmKWAgLyBgbWVyZ2VfdHJlZShiYXNlPeKApiwgcmhzPeKApilgIHdpdGggYXR0YWNrZXIgYHRyZWVpc2g9Ii0taW5kZXgtb3V0cHV0PS9ob21lL3ZpY3RpbS8uYmFzaHJjImAuCjIuIENoZWNrOiBOT05FIOKAlCB0aGUgbWV0aG9kcyBoYXZlIG5vIGBhbGxvd191bnNhZmVfb3B0aW9uc2AgYW5kIG5ldmVyIGNhbGwgYGNoZWNrX3Vuc2FmZV9vcHRpb25zYC4KMy4gU2luazogYHJlcG8uZ2l0LnJlYWRfdHJlZSgqYXJnX2xpc3QpYCDigJQgbm8gYC0tYC4gYXJndiAoZnJvbV90cmVlLCBvYnNlcnZlZCk6IGBbJ2dpdCcsJ3JlYWQtdHJlZScsJy0taW5kZXgtb3V0cHV0PTx0bXA+JywnLS1pbmRleC1vdXRwdXQ9L+KApi92aWN0aW0nXWAgKGxhc3Qtd2lucykuCjQuIEltcGFjdDogdGFyZ2V0IHBhdGggY3JlYXRlZC9vdmVyd3JpdHRlbiB3aXRoIGEgdmFsaWQgZ2l0LWluZGV4IGJsb2I7IGV4aXN0aW5nIGNvbnRlbnQgZGVzdHJveWVkLgoKIyMjIyMgQnlwYXNzIEV2aWRlbmNlCkluZGVwZW5kZW50bHkgcmVwcm9kdWNlZCAoZ2F0ZSBoYXJuZXNzKTogYEluZGV4RmlsZS5mcm9tX3RyZWUocmVwbywnLS1pbmRleC1vdXRwdXQ9PHZpY3RpbT4nKWAg4oaSIHZpY3RpbSBvdmVyd3JpdHRlbjsgYmVmb3JlPWBJTVBPUlRBTlQgT1JJR0lOQUwgQ09OVEVOVGAsIGFmdGVyIHN0YXJ0cyBgRElSQ1x4MDBceDAwXHgwMFx4MDLigKZgIChkZXN0cnVjdGl2ZSBjbG9iYmVyLCB2YWxpZCBpbmRleCBibG9iKS4gYHJlc2V0KGNvbW1pdD3igKYpYCBhbmQgYm90aCBgbWVyZ2VfdHJlZWAgcG9zaXRpb25hbHMgdmVyaWZpZWQuIEZpeC1jb21taXQgcmVhZDogYDNhZjBjMjUxYCB0b3VjaGVkIG9ubHkgYGNoZWNrb3V0X2luZGV4YCtgdGFnYDsgYHJlYWRfdHJlZWAgdW50b3VjaGVkIG9uIEhFQUQuCgojIyMjIyBBZmZlY3RlZCBWZXJzaW9ucwpgR2l0UHl0aG9uIDw9IDMuMS41N2AgKHNpbmtzIHByZXNlbnQgdmVyYmF0aW0gb24gdGhlIGxhdGVzdCByZWxlYXNlIHRhZykuCgojIyMjIyBTdWdnZXN0ZWQgRml4CkFkZCBhIGBjaGVja191bnNhZmVfb3B0aW9uc2AgZ3VhcmQgKHdpdGggYW4gYGFsbG93X3Vuc2FmZV9vcHRpb25zYCBwYXJhbWV0ZXIpIHRvIGBmcm9tX3RyZWVgL2ByZXNldGAvYG1lcmdlX3RyZWVgLCBhbmQvb3IgcGxhY2UgYSBgLS1gIHNlcGFyYXRvciBiZWZvcmUgdGhlIHBvc2l0aW9uYWwgdHJlZWlzaCBhcmd1bWVudHM7IGJsb2NrIGAtLWluZGV4LW91dHB1dGAgKGEgcGF0aC10YWtpbmcgb3B0aW9uKSBvbiB0aGlzIHNpbmsuCgotLS0KUmVwb3J0ZWQgYnkgKip6eCAoSmFjZSkqKiDigJQgR2l0SHViOiBAJiM4MjAzO21hbnVzLXVzZQoKIyMjIyBTZXZlcml0eQotIENWU1MgU2NvcmU6IDguMSAvIDEwIChIaWdoKQotIFZlY3RvciBTdHJpbmc6IGBDVlNTOjMuMS9BVjpOL0FDOkwvUFI6TC9VSTpOL1M6VS9DOk4vSTpIL0E6SGAKCiMjIyMgUmVmZXJlbmNlcwotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3NlY3VyaXR5L2Fkdmlzb3JpZXMvR0hTQS00Z213LWdnMm0tdzQ2cF0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9zZWN1cml0eS9hZHZpc29yaWVzL0dIU0EtNGdtdy1nZzJtLXc0NnApCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcHVsbC8yMjA0XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3B1bGwvMjIwNCkKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9jb21taXQvOWI1ZGNhZjg1ZGE1OTQ2ZGJmNjlkY2Q1M2Y5ZWRiYTA4Zjc2MGIzMl0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9jb21taXQvOWI1ZGNhZjg1ZGE1OTQ2ZGJmNjlkY2Q1M2Y5ZWRiYTA4Zjc2MGIzMikKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbl0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbikKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9yZWxlYXNlcy90YWcvMy4xLjU4XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3JlbGVhc2VzL3RhZy8zLjEuNTgpCgpUaGlzIGRhdGEgaXMgcHJvdmlkZWQgYnkgW09TVl0oaHR0cHM6Ly9vc3YuZGV2L3Z1bG5lcmFiaWxpdHkvR0hTQS00Z213LWdnMm0tdzQ2cCkgYW5kIHRoZSBbR2l0SHViIEFkdmlzb3J5IERhdGFiYXNlXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0aHViL2Fkdmlzb3J5LWRhdGFiYXNlKSAoW0NDLUJZIDQuMF0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdGh1Yi9hZHZpc29yeS1kYXRhYmFzZS9ibG9iL21haW4vTElDRU5TRS5tZCkpLgo8L2RldGFpbHM+CgotLS0KCiMjIyBHaXRQeXRob246IFVuZ3VhcmRlZCBnaXQgb3B0aW9uIGZvcndhcmRpbmcgaW4gUmVwby5pbml0IGVuYWJsZXMgYXJiaXRyYXJ5IGNvbW1hbmQgZXhlY3V0aW9uIHZpYSAtLXRlbXBsYXRlIGNsb25lIGhvb2tzCltHSFNBLTlyajctcmYycC13NzdyXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vYWR2aXNvcmllcy9HSFNBLTlyajctcmYycC13NzdyKQoKPGRldGFpbHM+CjxzdW1tYXJ5Pk1vcmUgaW5mb3JtYXRpb248L3N1bW1hcnk+CgojIyMjIERldGFpbHMKIyMjIyMgU3VtbWFyeQpgUmVwby5pbml0KClgIGZvcndhcmRzIGAqKmt3YXJnc2AgdmVyYmF0aW0gdG8gYGdpdCBpbml0YCB3aXRoIG5vIHVuc2FmZS1vcHRpb24gZ3VhcmQgYW5kIG5vIGBhbGxvd191bnNhZmVfb3B0aW9uc2AgcGFyYW1ldGVyLiBgZ2l0IGluaXQgLS10ZW1wbGF0ZT08ZGlyPmAgY29waWVzIGA8ZGlyPi9ob29rcy8qYCBpbnRvIHRoZSBuZXcgcmVwbydzIGAuZ2l0L2hvb2tzYCwgc28gYW4gYXR0YWNrZXItY29udHJvbGxlZCBgdGVtcGxhdGVgIGt3YXJnIHBsYW50cyBhIGhvb2sgdGhhdCBleGVjdXRlcyBvbiB0aGUgbmV4dCBnaXQgb3BlcmF0aW9uIOKGkiBhcmJpdHJhcnkgY29kZSBleGVjdXRpb24uIGAtLXRlbXBsYXRlYCBpcyBhbHJlYWR5IHJlY29nbml6ZWQgYXMgdW5zYWZlIGZvciBjbG9uZSAoaXQgaXMgb24gYHVuc2FmZV9naXRfY2xvbmVfb3B0aW9uc2AsIGFuZCBHSFNBLTZwOGgtM3dneC05N2dmIGNvdmVycyB0aGUgY2xvbmUgcGF0aCksIGJ1dCBgUmVwby5pbml0YCBpcyBhIGRpc3RpbmN0IG1ldGhvZCB0aGF0IG5ldmVyIHJlY2VpdmVkIGEgZ3VhcmQgYW5kIG5lZWRzIGFuIGluZGVwZW5kZW50IGZpeC4KCiMjIyMjIFJvb3QgQ2F1c2UKYFJlcG8uaW5pdChwYXRoLCBta2Rpciwgb2RidCwgZXhwYW5kX3ZhcnMsICoqa3dhcmdzKWAgaXMgYSBiYXJlIGBnaXQuaW5pdCgqKmt3YXJncylgIChnaXQvcmVwby9iYXNlLnB5OjE0MzUpIHdpdGggbm8gYGNoZWNrX3Vuc2FmZV9vcHRpb25zYCBhbmQgbm8gYGFsbG93X3Vuc2FmZV9vcHRpb25zYC4KCiMjIyMjIEltcGFjdApBcmJpdHJhcnkgY29kZSBleGVjdXRpb24gKGhvb2sgZmlyZXMgb24gbmV4dCBnaXQgb3ApIGF0IHRoZSBwcml2aWxlZ2VzIG9mIHRoZSBob3N0IHByb2Nlc3MuIFR3byBwcmVjb25kaXRpb25zIHJhaXNlIGF0dGFjayBjb21wbGV4aXR5IChBQzpIKTogdGhlIGFwcCBtdXN0IGZvcndhcmQgYSBgdGVtcGxhdGU9YCBrd2FyZyAoS0VZIGNvbnRyb2wpIEFORCB0aGUgYXR0YWNrZXIgbXVzdCBzdGFnZSBhbiBleGVjdXRhYmxlIGhvb2sgZGlyZWN0b3J5IGF0IGEga25vd24gcGF0aCDigJQgdGhlIHNhbWUgcHJvZmlsZSBHSFNBLTZwOGgtM3dneC05N2dmIGFjY2VwdGVkIGFzIEhJR0ggZm9yIHRoZSBjbG9uZSBwYXRoLiBEZWZhdWx0IGBhbGxvd191bnNhZmVfb3B0aW9uc2AgaXMgaXJyZWxldmFudCBoZXJlIGJlY2F1c2UgYFJlcG8uaW5pdGAgaGFzIG5vIGd1YXJkIGF0IGFsbC4KCiMjIyMjIFByb29mIG9mIENvbmNlcHQKYGBgcHl0aG9uCgojIyMjIyBhdHRhY2tlciBzdGFnZXMgL2V2aWwvaG9va3MvcG9zdC1jb21taXQgKGV4ZWN1dGFibGUpCmZyb20gZ2l0IGltcG9ydCBSZXBvClJlcG8uaW5pdChwYXRoLCB0ZW1wbGF0ZT0iL2V2aWwiKQoKIyMjIyMgbmV4dCBjb21taXQgcnVucyAvZXZpbC9ob29rcy9wb3N0LWNvbW1pdCAtPiBBQ0UKYGBgCgojIyMjIyBBdHRhY2sgQ2hhaW4KMS4gRW50cnk6IGF0dGFja2VyIHN0YWdlcyBgL2V2aWwvaG9va3MvcG9zdC1jb21taXRgIChleGVjdXRhYmxlKSBhbmQgZ2V0cyB0aGUgYXBwIHRvIGNhbGwgYFJlcG8uaW5pdChwYXRoLCB0ZW1wbGF0ZT0nL2V2aWwnKWAuCjIuIENoZWNrOiBOT05FIG9uIGBSZXBvLmluaXRgLiBCeXBhc3MgcHJvb2Y6IGJhc2UucHk6MTQzNSBpcyBhIGJhcmUgYGdpdC5pbml0KCoqa3dhcmdzKWAuIGFyZ3YgKG9ic2VydmVkKTogYFsnZ2l0JywnaW5pdCcsJy0tdGVtcGxhdGU9L2V2aWwnXWAuCjMuIFNpbms6IGdpdCBjb3BpZXMgYC9ldmlsL2hvb2tzL3Bvc3QtY29tbWl0YCDihpIgYDxyZXBvPi8uZ2l0L2hvb2tzL3Bvc3QtY29tbWl0YC4KNC4gSW1wYWN0OiBuZXh0IGNvbW1pdCBydW5zIHRoZSBob29rIOKGkiBhcmJpdHJhcnkgY29kZSBleGVjdXRpb24uCgojIyMjIyBCeXBhc3MgRXZpZGVuY2UKSW5kZXBlbmRlbnRseSByZXByb2R1Y2VkIChnYXRlIGhhcm5lc3MpOiBgUmVwby5pbml0KGRzdCwgdGVtcGxhdGU9JzxldmlsPicpYCDihpIgYXJndiBgWydnaXQnLCdpbml0JywnLS10ZW1wbGF0ZT08ZXZpbD4nXWAgdW5ndWFyZGVkOyBob29rIGNvcGllZCBpbnRvIGAuZ2l0L2hvb2tzL3Bvc3QtY29tbWl0YDsgYWZ0ZXIgYGdpdCBjb21taXRgIHRoZSBgSU5JVF9BQ0VgIG1hcmtlciB3YXMgY3JlYXRlZC4gYC0tc2VwYXJhdGUtZ2l0LWRpcj08cGF0aD5gIGlzIGEgcGFyYWxsZWwgYXJiaXRyYXJ5LXJlZGlyZWN0IHZlY3RvciB0aHJvdWdoIHRoZSBzYW1lIHVuZ3VhcmRlZCBzaW5rICh2YWx1ZSBjb250cm9sIG9ubHkpLgoKIyMjIyMgQWZmZWN0ZWQgVmVyc2lvbnMKYEdpdFB5dGhvbiA8PSAzLjEuNTdgICh1bmd1YXJkZWQgYGdpdC5pbml0KCoqa3dhcmdzKWAgcHJlc2VudCB2ZXJiYXRpbSBvbiB0aGUgbGF0ZXN0IHJlbGVhc2UgdGFnKS4KCiMjIyMjIFN1Z2dlc3RlZCBGaXgKQWRkIGEgYGNoZWNrX3Vuc2FmZV9vcHRpb25zYCBndWFyZCAod2l0aCBhbiBgYWxsb3dfdW5zYWZlX29wdGlvbnNgIHBhcmFtZXRlcikgdG8gYFJlcG8uaW5pdGAsIGNvbnN1bHRpbmcgYSBkZW55bGlzdCB0aGF0IGluY2x1ZGVzIGAtLXRlbXBsYXRlYCBhbmQgYC0tc2VwYXJhdGUtZ2l0LWRpcmAgKHBhdGgtdGFraW5nIC8gaG9vay1pbnN0YWxsaW5nIG9wdGlvbnMpLgoKLS0tClJlcG9ydGVkIGJ5ICoqenggKEphY2UpKiog4oCUIEdpdEh1YjogQCYjODIwMzttYW51cy11c2UKCiMjIyMgU2V2ZXJpdHkKLSBDVlNTIFNjb3JlOiA3LjUgLyAxMCAoSGlnaCkKLSBWZWN0b3IgU3RyaW5nOiBgQ1ZTUzozLjEvQVY6Ti9BQzpIL1BSOkwvVUk6Ti9TOlUvQzpIL0k6SC9BOkhgCgojIyMjIFJlZmVyZW5jZXMKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9zZWN1cml0eS9hZHZpc29yaWVzL0dIU0EtOXJqNy1yZjJwLXc3N3JdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vc2VjdXJpdHkvYWR2aXNvcmllcy9HSFNBLTlyajctcmYycC13NzdyKQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3B1bGwvMjIwNF0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9wdWxsLzIyMDQpCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vY29tbWl0L2Q5ZGRiNTViZGM2Nl0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9jb21taXQvZDlkZGI1NWJkYzY2KQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uKQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3JlbGVhc2VzL3RhZy8zLjEuNThdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcmVsZWFzZXMvdGFnLzMuMS41OCkKClRoaXMgZGF0YSBpcyBwcm92aWRlZCBieSBbT1NWXShodHRwczovL29zdi5kZXYvdnVsbmVyYWJpbGl0eS9HSFNBLTlyajctcmYycC13NzdyKSBhbmQgdGhlIFtHaXRIdWIgQWR2aXNvcnkgRGF0YWJhc2VdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRodWIvYWR2aXNvcnktZGF0YWJhc2UpIChbQ0MtQlkgNC4wXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0aHViL2Fkdmlzb3J5LWRhdGFiYXNlL2Jsb2IvbWFpbi9MSUNFTlNFLm1kKSkuCjwvZGV0YWlscz4KCi0tLQoKIyMjIEdpdFB5dGhvbjogQXJiaXRyYXJ5IGZpbGUgcmVhZCB2aWEgLS1wYXRoc3BlYy1mcm9tLWZpbGUgaW4gSW5kZXhGaWxlLnJlbW92ZSgpIGFuZCBIZWFkLmNoZWNrb3V0KCkKW0dIU0EtaGg5cC02d2gyLTRtZmNdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9hZHZpc29yaWVzL0dIU0EtaGg5cC02d2gyLTRtZmMpCgo8ZGV0YWlscz4KPHN1bW1hcnk+TW9yZSBpbmZvcm1hdGlvbjwvc3VtbWFyeT4KCiMjIyMgRGV0YWlscwojIyMjIyBTdW1tYXJ5CgpgSW5kZXhGaWxlLnJlbW92ZSgpYCBhbmQgYEhlYWQuY2hlY2tvdXQoKWAgZm9yd2FyZCBgKiprd2FyZ3NgIGludG8gYGdpdCBybWAgYW5kIGBnaXQgY2hlY2tvdXRgCndpdGggbm8gZ3VhcmQuIFBhc3NpbmcgYC0tcGF0aHNwZWMtZnJvbS1maWxlPTxmaWxlPmAgKip0b2dldGhlciB3aXRoIGAtLXBhdGhzcGVjLWZpbGUtbnVsYCoqCm1ha2VzIEdpdCB0cmVhdCB0aGUgd2hvbGUgZmlsZSBhcyBhIHNpbmdsZSBOVUwtZGVsaW1pdGVkIHBhdGhzcGVjLCBhbmQgdGhlIHVubWF0Y2hlZC1wYXRoc3BlYwplcnJvciBxdW90ZXMgaXQgdmVyYmF0aW0uIEdpdFB5dGhvbiBzdXJmYWNlcyB0aGF0IHRocm91Z2ggYEdpdENvbW1hbmRFcnJvci5zdGRlcnJgLCBzbyB0aGUKZW50aXJlIGNvbnRlbnRzIG9mIGEgY2FsbGVyLWNob3NlbiBmaWxlIGFyZSByZXR1cm5lZCB0byB0aGUgY2FsbGVyIGluIGJhbmQuCgpUaGlzIGlzIHRoZSBzYW1lIHByaW1pdGl2ZSBhcyBJbnN0YW5jZSAyIG9mCltHSFNBLTNmN3ctOHJyOC1mMzdmXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vYWR2aXNvcmllcy9HSFNBLTNmN3ctOHJyOC1mMzdmKSAtIGBUYWdSZWZlcmVuY2UuY3JlYXRlKClgCndpdGggYC1GYCwgYXJiaXRyYXJ5IGZpbGUgcmVhZCByZXR1cm5lZCBpbiBiYW5kIC0gYXQgdHdvIHNpdGVzIHRoYXQgYWR2aXNvcnkgYXNzZXNzZWQgYW5kCmNsZWFyZWQuCgojIyMjIyBQcmlvciBhcnQsIGFuZCB3aHkgSSBhbSBmaWxpbmcgcmF0aGVyIHRoYW4gY29tbWVudGluZwoKR0hTQS0zZjd3LThycjgtZjM3ZidzIHN3ZWVwIHRhYmxlIGxpc3RzIHRoZXNlIGZvdXIgc2l0ZXMgd2l0aCB0aGUgYXNzZXNzbWVudAoqImAtLXBhdGhzcGVjLWZyb20tZmlsZWAgb25seSByZWFkcyBhIHBhdGhzcGVjOyBubyB3cml0ZSBvciBkaXNjbG9zdXJlIHByaW1pdGl2ZSBmb3VuZCIqOgoKfCBDYWxsIHNpdGUgfCBnaXQgY29tbWFuZCB8IHRoYXQgYWR2aXNvcnkncyBhc3Nlc3NtZW50IHwKfC0tLXwtLS18LS0tfAp8IGBJbmRleEZpbGUucmVtb3ZlKClgIHwgYHJtYCB8IGAtLXBhdGhzcGVjLWZyb20tZmlsZWAgb25seSByZWFkcyBhIHBhdGhzcGVjOyBubyB3cml0ZSBvciBkaXNjbG9zdXJlIHByaW1pdGl2ZSBmb3VuZCB8CnwgYEluZGV4RmlsZS5tb3ZlKClgIHwgYG12YCB8IHNhbWUgfAp8IGBIRUFELnJlc2V0KClgIHwgYHJlc2V0YCB8IHNhbWUgfAp8IGBIRUFELmNoZWNrb3V0KClgIHwgYGNoZWNrb3V0YCB8IHNhbWUgfAoKVGhhdCBhc3Nlc3NtZW50IGlzIHZlcnkgbmVhcmx5IHJpZ2h0LCBhbmQgSSB0aGluayB0aGF0IGlzIHdoeSBpdCBoZWxkOiB3aXRoCmAtLXBhdGhzcGVjLWZyb20tZmlsZWAgYWxvbmUsIEdpdCBzcGxpdHMgb24gbmV3bGluZXMgYW5kIHRoZSBlcnJvciBxdW90ZXMgb25seSB0aGUgKipmaXJzdApsaW5lKiosIHdoaWNoIHJlYWRzIGFzIGFuIHVuaW50ZXJlc3RpbmcgcGFydGlhbC4gQWRkaW5nIGAtLXBhdGhzcGVjLWZpbGUtbnVsYCAtIGEgc2libGluZyBmbGFnCm9mIHRoZSBzYW1lIG9wdGlvbiwgYW5kIHRoZSBkb2N1bWVudGVkIHdheSB0byBoYW5kbGUgcGF0aHMgY29udGFpbmluZyBuZXdsaW5lcyAtIG1ha2VzIHRoZQp3aG9sZSBmaWxlIG9uZSBwYXRoc3BlYy4KCiMjIyMjIFJvb3QgY2F1c2UKCmBnaXQvaW5kZXgvYmFzZS5weTo5OTEtMTA0M2A6CgpgYGBweXRob24KZGVmIHJlbW92ZShzZWxmLCBpdGVtcywgd29ya2luZ190cmVlPUZhbHNlLCAqKmt3YXJncyk6CiAgICAuLi4KICAgIHJlbW92ZWRfcGF0aHMgPSBzZWxmLnJlcG8uZ2l0LnJtKGFyZ3MsIHBhdGhzLCAqKmt3YXJncykuc3BsaXRsaW5lcygpICAgIyBsaW5lIDEwNDMKYGBgCgpgZ2l0L3JlZnMvaGVhZC5weToyMzctMjY4YDoKCmBgYHB5dGhvbgpkZWYgY2hlY2tvdXQoc2VsZiwgZm9yY2U6IGJvb2wgPSBGYWxzZSwgKiprd2FyZ3M6IEFueSk6CiAgICAuLi4KICAgIHNlbGYucmVwby5naXQuY2hlY2tvdXQoc2VsZiwgKiprd2FyZ3MpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBsaW5lIDI2OApgYGAKCk5laXRoZXIgaGFzIGFuIGBhbGxvd191bnNhZmVfb3B0aW9uc2AgcGFyYW1ldGVyIG9yIGEgYGNoZWNrX3Vuc2FmZV9vcHRpb25zKClgIGNhbGwuCgojIyMjIyBQcm9vZiBvZiBjb25jZXB0CgpgYGBweXRob24KZnJvbSBnaXQgaW1wb3J0IFJlcG8KZnJvbSBnaXQuZXhjIGltcG9ydCBHaXRDb21tYW5kRXJyb3IKCnJlcG8gPSBSZXBvKCIvcGF0aC90by9yZXBvIikKa3cgPSBkaWN0KHBhdGhzcGVjX2Zyb21fZmlsZT0iL2V0Yy9wYXNzd2QiLCBwYXRoc3BlY19maWxlX251bD1UcnVlKQoKdHJ5OgogICAgcmVwby5pbmRleC5yZW1vdmUoW10sICoqa3cpICAgICAgICAgICMgb3I6IHJlcG8uaGVhZHNbMF0uY2hlY2tvdXQoKiprdykKZXhjZXB0IEdpdENvbW1hbmRFcnJvciBhcyBlOgogICAgcHJpbnQoZS5zdGRlcnIpICAgICAgICAgICAgICAgICAgICAgICMgPC0gZW50aXJlIGZpbGUgY29udGVudHMKYGBgCgpPYnNlcnZlZCBvbiBwdWJsaXNoZWQgMy4xLjU3LCBhZ2FpbnN0IGEgY2FuYXJ5IGZpbGUgaG9sZGluZyB0aHJlZSBtYXJrZWQgbGluZXM6CgpgYGAKW1BBU1NdIEluZGV4RmlsZS5yZW1vdmUoKSAtPiBgZ2l0IHJtYCByZXR1cm5zIEFMTCAzIGNhbmFyeSBsaW5lcyBpbi1iYW5kCiAgICAgICBzdGRlcnI6ICdmYXRhbDogcGF0aHNwZWMgJ0xJTkUxLUNBTkFSWS00MjQyCiAgICAgICBMSU5FMi1TRUNSRVQtNzc3NwogICAgICAgTElORTMtVEFJTC05OTk5CiAgICAgICAnIGRpZCBub3QgbWF0Y2ggYW55IGZpbGVzJwpbUEFTU10gSGVhZC5jaGVja291dCgpIC0+IGBnaXQgY2hlY2tvdXRgIHJldHVybnMgQUxMIDMgY2FuYXJ5IGxpbmVzIGluLWJhbmQKICAgICAgIHN0ZGVycjogJ2Vycm9yOiBwYXRoc3BlYyAnTElORTEtQ0FOQVJZLTQyNDIKICAgICAgIExJTkUyLVNFQ1JFVC03Nzc3CiAgICAgICBMSU5FMy1UQUlMLTk5OTkKICAgICAgICcgZGlkIG5vdCBtYXRjaCBhbnkgZmlsZShzKSBrbm93biB0byBnaXQnCltQQVNTXSBQUkVDSVNJT046IGBnaXQgc3RhdHVzYCBsZWFrcyAwLzMgLS0gbm90IGV2ZXJ5IHVuZ3VhcmRlZCBzaXRlIGRpc2Nsb3NlcwpbUEFTU10gUFJFQ0lTSU9OOiB0aGUgR1VBUkRFRCBjaGVja291dC1pbmRleCBsZWFrcyAwLzMKYGBgCgpUaGUgdHdvIHByZWNpc2lvbiBjb250cm9scyBhcmUgdGhlcmUgc28gdGhlIHJlc3VsdCBpcyBhYm91dCB0aGVzZSBzaW5rcyBhbmQgbm90IGFib3V0IHRoZQpjYW5hcnkgYmVpbmcgdmlzaWJsZSBldmVyeXdoZXJlLgoKIyMjIyMgU2NvcGUgY29ycmVjdGlvbiB0byB0aGUgdGFibGUgYWJvdmUKCk9mIHRoZSBmb3VyIHNpdGVzIGNsZWFyZWQgd2l0aCB0aGF0IHNlbnRlbmNlLCAqKnR3byBkaXNjbG9zZSBhbmQgdHdvIGRvIG5vdCoqOgoKfCBDYWxsIHNpdGUgfCBkaXNjbG9zZWQ/IHwKfC0tLXwtLS18CnwgYEluZGV4RmlsZS5yZW1vdmUoKWAg4oaSIGBnaXQgcm1gIHwgKip5ZXMsIGZ1bGwgZmlsZSoqIHwKfCBgSGVhZC5jaGVja291dCgpYCDihpIgYGdpdCBjaGVja291dGAgfCAqKnllcywgZnVsbCBmaWxlKiogfAp8IGBIRUFELnJlc2V0KClgIOKGkiBgZ2l0IHJlc2V0YCB8IG5vIC0gYGdpdCByZXNldGAgZG9lcyBub3QgZXJyb3Igb24gdW5tYXRjaGVkIHBhdGhzcGVjcyB8CnwgYEluZGV4RmlsZS5tb3ZlKClgIOKGkiBgZ2l0IG12YCB8IG5vIHwKClRoZSB0d28gbmVnYXRpdmVzIGFyZSBtZW50aW9uZWQgYmVjYXVzZSAidGhlIGRpc21pc3NhbCB3YXMgd3JvbmciIHdvdWxkIG92ZXJzdGF0ZSBpdDogdGhlCmRpc21pc3NhbCB3YXMgd3JvbmcgZm9yIGhhbGYgb2Ygd2hhdCBpdCBjb3ZlcmVkLgoKIyMjIyBTZXZlcml0eQotIENWU1MgU2NvcmU6IDYuNSAvIDEwIChNZWRpdW0pCi0gVmVjdG9yIFN0cmluZzogYENWU1M6My4xL0FWOk4vQUM6TC9QUjpML1VJOk4vUzpVL0M6SC9JOk4vQTpOYAoKIyMjIyBSZWZlcmVuY2VzCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vc2VjdXJpdHkvYWR2aXNvcmllcy9HSFNBLWhoOXAtNndoMi00bWZjXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3NlY3VyaXR5L2Fkdmlzb3JpZXMvR0hTQS1oaDlwLTZ3aDItNG1mYykKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9wdWxsLzIyMDRdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcHVsbC8yMjA0KQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL2NvbW1pdC9mMjU1MGI2NWJmNjBjYTA4NzE5MDk4MWUyYzdiNjg2NWUyMDFmNDBjXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL2NvbW1pdC9mMjU1MGI2NWJmNjBjYTA4NzE5MDk4MWUyYzdiNjg2NWUyMDFmNDBjKQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uKQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3JlbGVhc2VzL3RhZy8zLjEuNThdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcmVsZWFzZXMvdGFnLzMuMS41OCkKClRoaXMgZGF0YSBpcyBwcm92aWRlZCBieSBbT1NWXShodHRwczovL29zdi5kZXYvdnVsbmVyYWJpbGl0eS9HSFNBLWhoOXAtNndoMi00bWZjKSBhbmQgdGhlIFtHaXRIdWIgQWR2aXNvcnkgRGF0YWJhc2VdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRodWIvYWR2aXNvcnktZGF0YWJhc2UpIChbQ0MtQlkgNC4wXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0aHViL2Fkdmlzb3J5LWRhdGFiYXNlL2Jsb2IvbWFpbi9MSUNFTlNFLm1kKSkuCjwvZGV0YWlscz4KCi0tLQoKIyMjIEdpdFB5dGhvbjogQXJiaXRyYXJ5IEdpdCBSZXBvc2l0b3J5IENyZWF0aW9uIE91dHNpZGUgdGhlIFdvcmtpbmcgVHJlZSB2aWEgVW52YWxpZGF0ZWQgLmdpdG1vZHVsZXMgU3VibW9kdWxlIE5hbWUgaW4gR2l0UHl0aG9uCltHSFNBLWhtcTItdzU4Zi0yN2pjXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vYWR2aXNvcmllcy9HSFNBLWhtcTItdzU4Zi0yN2pjKQoKPGRldGFpbHM+CjxzdW1tYXJ5Pk1vcmUgaW5mb3JtYXRpb248L3N1bW1hcnk+CgojIyMjIERldGFpbHMKIyMjIyMgU3VtbWFyeQpHaXRQeXRob24gY29tcHV0ZXMgdGhlIG9uLWRpc2sgbG9jYXRpb24gb2YgYSBzdWJtb2R1bGUncyBzZXBhcmF0ZSBHaXQgZGlyZWN0b3J5IChgLmdpdC9tb2R1bGVzLzxuYW1lPmApIGZyb20gdGhlIHN1Ym1vZHVsZSdzIGAuZ2l0bW9kdWxlc2Agc2VjdGlvbiBuYW1lIHdpdGggbm8gdmFsaWRhdGlvbi4gQmVjYXVzZSB0aGF0IG5hbWUgaXMgZnVsbHkgYXR0YWNrZXItY29udHJvbGxlZCBjb250ZW50IG9mIGEgY2xvbmVkIHJlcG9zaXRvcnksIGEgbWFsaWNpb3VzIHJlcG9zaXRvcnkgY2FuIHNldCBhIHN1Ym1vZHVsZSBuYW1lIHRvIGEgdHJhdmVyc2FsIHN0cmluZyAoZS5nLiBgLi4vLi4vLi4vLi4vaG9tZS92aWN0aW0vLnNvbWV0aGluZ2ApIGFuZCBjYXVzZSBHaXRQeXRob24gdG8gY3JlYXRlIGFuZCBpbml0aWFsaXplIGEgZnVsbCBHaXQgcmVwb3NpdG9yeSBhdCBhbiBhdHRhY2tlci1jaG9zZW4gZmlsZXN5c3RlbSBwYXRoIG91dHNpZGUgdGhlIGludGVuZGVkIGNsb25lIGRpcmVjdG9yeS4gVGhlIG9ubHkgcHJlY29uZGl0aW9uIGlzIHRoYXQgYSB2aWN0aW0gY2xvbmVzIHRoZSBtYWxpY2lvdXMgcmVwb3NpdG9yeSB3aXRoIEdpdFB5dGhvbiBhbmQgcnVucyBzdWJtb2R1bGUgaW5pdGlhbGl6YXRpb24gKGBzdWJtb2R1bGVfdXBkYXRlKGluaXQ9VHJ1ZSlgIC8gYHNtLnVwZGF0ZShpbml0PVRydWUpYCksIGEgdmVyeSBjb21tb24gYW5kIG9mdGVuIGF1dG9tYXRpYyBzdGVwLiBDb3JlIEdpdCBpdHNlbGYgYWxyZWFkeSBibG9ja3MgdGhpcyBleGFjdCBhdHRhY2sgY2xhc3MgKENWRS0yMDE4LTExMjM1KSwgYnV0IEdpdFB5dGhvbidzIGluZGVwZW5kZW50IHJlaW1wbGVtZW50YXRpb24gbmV2ZXIgYWRvcHRlZCBhbiBlcXVpdmFsZW50IGNoZWNrLgoKIyMjIyMgRGV0YWlscwpgc3JjL0dpdFB5dGhvbi9naXQvb2JqZWN0cy9zdWJtb2R1bGUvdXRpbC5weWAgYHNtX25hbWUoKWAgc3RyaXBzIHRoZSBgc3VibW9kdWxlICJgIC8gYCJgIHdyYXBwZXIgZnJvbSBhIGAuZ2l0bW9kdWxlc2AgYFtzdWJtb2R1bGUgIi4uLiJdYCBoZWFkZXIgYW5kIHJldHVybnMgdGhlIHJlc3VsdCB1bmNoZWNrZWQuIGBTdWJtb2R1bGUuaXRlcl9pdGVtcygpYCBpbiBgc3JjL0dpdFB5dGhvbi9naXQvb2JqZWN0cy9zdWJtb2R1bGUvYmFzZS5weWAgcmVhZHMgdGhpcyB2aWEgYHNtX25hbWUoc21zKWAgYW5kIGFzc2lnbnMgaXQgdG8gYHNtLl9uYW1lYDsgdW5saWtlIHRoZSBzdWJtb2R1bGUgYHBhdGhgLCBgbmFtZWAgaXMgbmV2ZXIgdXNlZCBmb3IgYSB0cmVlIGxvb2t1cCwgc28gaXQgaXMgbmV2ZXIgaW1wbGljaXRseSB2YWxpZGF0ZWQuIGBTdWJtb2R1bGUuX21vZHVsZV9hYnNwYXRoKClgIHRoZW4gYnVpbGRzIGBvc3Auam9pbihwYXJlbnRfcmVwby5naXRfZGlyLCAibW9kdWxlcyIsIG5hbWUpYCAtIGBvcy5wYXRoLmpvaW5gIGRvZXMgbm90IG5vcm1hbGl6ZSBgLi4vYCBzZXF1ZW5jZXMuIGBTdWJtb2R1bGUuX2Nsb25lX3JlcG8oKWAgcGFzc2VzIHRoaXMgdmFsdWUgc3RyYWlnaHQgdG8gYG9zLm1ha2VkaXJzKClgIGFuZCB0byBgZ2l0IGNsb25lIC0tc2VwYXJhdGUtZ2l0LWRpcj08bW9kdWxlX2Fic3BhdGg+YCwgY3JlYXRpbmcgYW5kIHBvcHVsYXRpbmcgYSBmdWxsIEdpdCByZXBvc2l0b3J5IChvYmplY3RzLCByZWZzLCBob29rcywgY29uZmlnKSBhdCB0aGUgZXNjYXBlZCBwYXRoLiBBdHRhY2sgcHJlcmVxdWlzaXRlOiBhdHRhY2tlciBjb250cm9scyBhIHJlcG9zaXRvcnkgdGhlIHZpY3RpbSBjbG9uZXMgYW5kIGluaXRpYWxpemVzIHN1Ym1vZHVsZXMgZm9yLgoKIyMjIyMgUG9DCjEuIEVudmlyb25tZW50OiBEb2NrZXIgaW1hZ2UgYnVpbHQgYEZST00gcHl0aG9uOjMuMTEtc2xpbWAsIHdpdGggYGdpdGAgaW5zdGFsbGVkIHZpYSBgYXB0LWdldCBpbnN0YWxsIC15IGdpdGAgKERlYmlhbiBib29rd29ybSBwYWNrYWdlZCB2ZXJzaW9uLCBkZXNjcmliZWQgaW4gdGhlIGFkdmlzb3J5IGFzICJnaXQgMi54IjsgdGhlIGhvc3Qtc2lkZSB2ZXJpZmljYXRpb24gc2VwYXJhdGVseSB1c2VkIHN5c3RlbSBnaXQgYDIuMzQuMWAsIGJ1dCBubyBleGFjdCB2ZXJzaW9uIGlzIHBpbm5lZCBmb3IgdGhlIGdpdCBiaW5hcnkgaW5zaWRlIHRoaXMgRG9ja2VyIGltYWdlKS4gR2l0UHl0aG9uIGlzIGluc3RhbGxlZCBpbnNpZGUgdGhlIGNvbnRhaW5lciB2aWEgYHBpcCBpbnN0YWxsIC9zcmMvR2l0UHl0aG9uYCBmcm9tIHRoaXMgcmVwb3NpdG9yeSdzIG93biBzb3VyY2UsIHdoaWNoIHRoZSBhZHZpc29yeSBzdGF0ZXMgcmVzb2x2ZWQgdG8gdGhlIG9mZmljaWFsbHkgcmVsZWFzZWQgYEdpdFB5dGhvbj09My4xLjU3YCBhbmQgYGdpdGRiPT00LjAuMTJgLgoyLiBDb25maWd1cmF0aW9uIC8gcHJlY29uZGl0aW9uczogTm9uZSBiZXlvbmQgd2hhdCdzIGRlc2NyaWJlZCAtIHRoZSB2aWN0aW0gbXVzdCBjbG9uZSB0aGUgYXR0YWNrZXIncyByZXBvc2l0b3J5IHdpdGggR2l0UHl0aG9uIGFuZCBydW4gc3VibW9kdWxlIGluaXRpYWxpemF0aW9uIChgcmVwby5zdWJtb2R1bGVzYCArIGBzbS51cGRhdGUoaW5pdD1UcnVlKWAsIGVxdWl2YWxlbnQgdG8gYGdpdCBzdWJtb2R1bGUgdXBkYXRlIC0taW5pdGApLgozLiBDb21tYW5kcyBydW4gKHF1b3RlZCB2ZXJiYXRpbSBmcm9tIHRoZSBhZHZpc29yeSdzICJDb25maXJtZWQgdGVzdCBydW4iIHNlY3Rpb24pOgpgYGBiYXNoCiQgZG9ja2VyIGJ1aWxkIC1mIEdIU0EvdGVzdGluZy9Eb2NrZXJmaWxlIC10IGdoc2EtZ2l0cHl0aG9uLXBvYyAuCiQgZG9ja2VyIHJ1biAtLXJtIGdoc2EtZ2l0cHl0aG9uLXBvYwpgYGAKKFBlciB0aGUgRG9ja2VyZmlsZSwgYGRvY2tlciBydW5gIGV4ZWN1dGVzIGAvd29yay9ydW5fYWxsLnNoYCwgd2hpY2ggaW4gdHVybiBydW5zIGBidWlsZF9hdHRhY2tlcl9yZXBvLnNoYCwgdGhlbiBgcG9jX2dpdHB5dGhvbi5weWAsIHRoZW4gYHBvY19jb250cm9sX3JlYWxnaXQuc2hgLikKNC4gRnVsbCBzb3VyY2Ugb2YgdGhlIFBvQyBzY3JpcHQgKGBHSFNBL3Rlc3RpbmcvcG9jX2dpdHB5dGhvbi5weWApLCB2ZXJiYXRpbToKYGBgcHl0aG9uCiIiIkdIU0EtMDAxIFBvQzogR2l0UHl0aG9uIHNpZGUuCgpDbG9uZXMgdGhlIGF0dGFja2VyIHJlcG8gYW5kIHJ1bnMgdGhlIGVxdWl2YWxlbnQgb2YKYGdpdCBzdWJtb2R1bGUgdXBkYXRlIC0taW5pdGAgdmlhIEdpdFB5dGhvbiwgdGhlbiBjaGVja3Mgd2hldGhlciBhIGdpdApyZXBvc2l0b3J5IHdhcyBjcmVhdGVkIG91dHNpZGUgdGhlIGNsb25lIGRpcmVjdG9yeS4KIiIiCmltcG9ydCBvcwppbXBvcnQgc2h1dGlsCgppbXBvcnQgZ2l0CgpDTE9ORV9ESVIgPSAnL3dvcmsvdmljdGltX2Nsb25lL3JlcG8nCkVTQ0FQRV9UQVJHRVQgPSAnL3RtcC9naXRweXRob25fcG9jX2VzY2FwZWRfcm9vdCcKCmRlZiBtYWluKCk6CiAgICBzaHV0aWwucm10cmVlKG9zLnBhdGguZGlybmFtZShDTE9ORV9ESVIpLCBpZ25vcmVfZXJyb3JzPVRydWUpCiAgICBzaHV0aWwucm10cmVlKEVTQ0FQRV9UQVJHRVQsIGlnbm9yZV9lcnJvcnM9VHJ1ZSkKICAgIG9zLm1ha2VkaXJzKG9zLnBhdGguZGlybmFtZShDTE9ORV9ESVIpLCBleGlzdF9vaz1UcnVlKQoKICAgIHByaW50KGYnR2l0UHl0aG9uIHZlcnNpb246IHtnaXQuX192ZXJzaW9uX199JykKICAgIHJlcG8gPSBnaXQuUmVwby5jbG9uZV9mcm9tKCcvd29yay9hdHRhY2tlcl9yZXBvJywgQ0xPTkVfRElSKQogICAgcHJpbnQoJ0Nsb25lZCBpbnRvOicsIHJlcG8ud29ya2luZ190cmVlX2RpcikKCiAgICBzbXMgPSBsaXN0KHJlcG8uc3VibW9kdWxlcykKICAgIGZvciBzbSBpbiBzbXM6CiAgICAgICAgcHJpbnQoJyAgc3VibW9kdWxlIG5hbWU6JywgcmVwcihzbS5uYW1lKSkKICAgICAgICBwcmludCgnICBzdWJtb2R1bGUgcGF0aDonLCByZXByKHNtLnBhdGgpKQoKICAgIHByaW50KCdlc2NhcGVfdGFyZ2V0IGV4aXN0cyBiZWZvcmUgdXBkYXRlOicsIG9zLnBhdGguZXhpc3RzKEVTQ0FQRV9UQVJHRVQpKQoKICAgIGZvciBzbSBpbiBzbXM6CiAgICAgICAgdHJ5OgogICAgICAgICAgICBzbS51cGRhdGUoaW5pdD1UcnVlKQogICAgICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICAgICAgcHJpbnQoJ3NtLnVwZGF0ZSByYWlzZWQ6JywgcmVwcihlKSkKCiAgICBleGlzdHMgPSBvcy5wYXRoLmV4aXN0cyhFU0NBUEVfVEFSR0VUKQogICAgcHJpbnQoJ2VzY2FwZV90YXJnZXQgZXhpc3RzIGFmdGVyIHVwZGF0ZTonLCBleGlzdHMpCiAgICBpZiBleGlzdHM6CiAgICAgICAgcHJpbnQoJ2VzY2FwZV90YXJnZXQgY29udGVudHM6Jywgb3MubGlzdGRpcihFU0NBUEVfVEFSR0VUKSkKCiAgICBwcmludCgnUE9DX1JFU1VMVD1WVUxORVJBQkxFJyBpZiBleGlzdHMgZWxzZSAnUE9DX1JFU1VMVD1TQUZFJykKCmlmIF9fbmFtZV9fID09ICdfX21haW5fXyc6CiAgICBtYWluKCkKYGBgCjUuIEV4YWN0IGNhcHR1cmVkIHRlcm1pbmFsIG91dHB1dCAodmVyYmF0aW0sIGZyb20gdGhlIG9yaWdpbmFsIGFkdmlzb3J5J3MgIkNvbmZpcm1lZCB0ZXN0IHJ1biAoRG9ja2VyLCByZWxlYXNlZCBwYWNrYWdlKSIgc2VjdGlvbik6CmBgYAo9PT0gR2l0UHl0aG9uIFBvQyAodnVsbmVyYWJsZSBwYXRoKSA9PT0KR2l0UHl0aG9uIHZlcnNpb246IDMuMS41NwpDbG9uZWQgaW50bzogL3dvcmsvdmljdGltX2Nsb25lL3JlcG8KICBzdWJtb2R1bGUgbmFtZTogJy4uLy4uLy4uLy4uLy4uLy4uL3RtcC9naXRweXRob25fcG9jX2VzY2FwZWRfcm9vdC9tb2R1bGVzX2RpcicKICBzdWJtb2R1bGUgcGF0aDogJ2xlZ2l0X2RpcicKZXNjYXBlX3RhcmdldCBleGlzdHMgYmVmb3JlIHVwZGF0ZTogRmFsc2UKZXNjYXBlX3RhcmdldCBleGlzdHMgYWZ0ZXIgdXBkYXRlOiBUcnVlCmVzY2FwZV90YXJnZXQgY29udGVudHM6IFsnbW9kdWxlc19kaXInXQpQT0NfUkVTVUxUPVZVTE5FUkFCTEUKCj09PSBDb250cm9sOiByZWFsIGdpdCBDTEkgb24gaWRlbnRpY2FsIHJlcG8gPT09Cndhcm5pbmc6IGlnbm9yaW5nIHN1c3BpY2lvdXMgc3VibW9kdWxlIG5hbWU6IC4uLy4uLy4uLy4uLy4uLy4uL3RtcC9naXRweXRob25fcG9jX2VzY2FwZWRfcm9vdC9tb2R1bGVzX2Rpcgp3YXJuaW5nOiBpZ25vcmluZyBzdXNwaWNpb3VzIHN1Ym1vZHVsZSBuYW1lOiAuLi8uLi8uLi8uLi8uLi8uLi90bXAvZ2l0cHl0aG9uX3BvY19lc2NhcGVkX3Jvb3QvbW9kdWxlc19kaXIKZmF0YWw6IE5vIHVybCBmb3VuZCBmb3Igc3VibW9kdWxlIHBhdGggJ2xlZ2l0X2RpcicgaW4gLmdpdG1vZHVsZXMKQ09OVFJPTF9SRVNVTFQ9U0FGRSAocmVhbCBnaXQgY29ycmVjdGx5IHJlZnVzZWQpCmBgYAo2LiBQYXlsb2FkOiB0aGUgYXR0YWNrZXIgcmV3cml0ZXMgdGhlIGAuZ2l0bW9kdWxlc2Agc2VjdGlvbiBoZWFkZXIgZnJvbSBgW3N1Ym1vZHVsZSAibGVnaXRfZGlyIl1gIHRvIGBbc3VibW9kdWxlICIuLi8uLi8uLi8uLi8uLi8uLi90bXAvZ2l0cHl0aG9uX3BvY19lc2NhcGVkX3Jvb3QvbW9kdWxlc19kaXIiXWAgKGJ1aWx0IGJ5IGBidWlsZF9hdHRhY2tlcl9yZXBvLnNoYCwgcGFydCBvZiB0aGUgaGFybmVzcyBpbiBgR0hTQS90ZXN0aW5nL2ApLiBUaGUgbWFsaWNpb3VzIHBhcnQgaXMgdGhlIGAuLi8uLi8uLi8uLi8uLi8uLi9gIHRyYXZlcnNhbCBzZXF1ZW5jZSBlbWJlZGRlZCBpbiB0aGUgc3VibW9kdWxlICpuYW1lKiAobm90IHRoZSB0cmVlLXZhbGlkYXRlZCBgcGF0aGApLCB3aGljaCBiZWNvbWVzIHRoZSBvbi1kaXNrIHRhcmdldCBmb3IgdGhlIHN1Ym1vZHVsZSdzIHNlcGFyYXRlIGdpdCBkaXJlY3RvcnkuCjcuIEV4cGVjdGVkIHZzLiBvYnNlcnZlZDogQSBzYWZlIGltcGxlbWVudGF0aW9uIChhcyBkZW1vbnN0cmF0ZWQgYnkgdGhlIHJlYWwgYGdpdGAgQ0xJIGNvbnRyb2wgcnVuKSByZWplY3RzIHRoZSBzdWJtb2R1bGUgbmFtZSB3aXRoICJpZ25vcmluZyBzdXNwaWNpb3VzIHN1Ym1vZHVsZSBuYW1lIiBhbmQgcmVmdXNlcyB0byBjcmVhdGUgYW55dGhpbmcgb3V0c2lkZSB0aGUgcmVwb3NpdG9yeS4gR2l0UHl0aG9uIGluc3RlYWQgY3JlYXRlZCB0aGUgZXNjYXBlLXRhcmdldCBkaXJlY3RvcnkgYW5kIGEgZnVsbHktaW5pdGlhbGl6ZWQgR2l0IHJlcG9zaXRvcnkgYXQgYC90bXAvZ2l0cHl0aG9uX3BvY19lc2NhcGVkX3Jvb3QvbW9kdWxlc19kaXJgLCBjb25maXJtZWQgYnkgYGVzY2FwZV90YXJnZXQgZXhpc3RzIGFmdGVyIHVwZGF0ZTogVHJ1ZWAgYW5kIGl0cyBsaXN0ZWQgY29udGVudHMuCjguIFNlY3VyaXR5IGltcGFjdCBkZW1vbnN0cmF0ZWQ6IGFyYml0cmFyeSBmaWxlc3lzdGVtIGRpcmVjdG9yeSBhbmQgR2l0LXJlcG9zaXRvcnkgY3JlYXRpb24gYXQgYW4gYXR0YWNrZXItY2hvc2VuIGFic29sdXRlIHBhdGggb3V0c2lkZSB0aGUgdmljdGltJ3MgaW50ZW5kZWQgY2xvbmUgZGlyZWN0b3J5LCBwb3B1bGF0ZWQgd2l0aCBhdHRhY2tlci1jb250cm9sbGVkIGNvbnRlbnQgc291cmNlZCBmcm9tIHRoZSBzdWJtb2R1bGUncyBvd24gKGFsc28gYXR0YWNrZXItY29udHJvbGxlZCkgYHVybGAuCgojIyMjIyBJbXBhY3QKUGF0aCB0cmF2ZXJzYWwgKENXRS0yMikgLyBleHRlcm5hbCBjb250cm9sIG9mIGZpbGUgcGF0aCAoQ1dFLTczKSBsZWFkaW5nIHRvIGFyYml0cmFyeSBkaXJlY3RvcnkgYW5kIEdpdC1yZXBvc2l0b3J5IGNyZWF0aW9uIG91dHNpZGUgdGhlIGludGVuZGVkIGNsb25lIGRpcmVjdG9yeS4gSW50ZWdyaXR5IGltcGFjdCBpcyBIaWdoIChhdHRhY2tlciBjaG9vc2VzIGRlc3RpbmF0aW9uIHBhdGggYW5kLCB2aWEgdGhlIHN1Ym1vZHVsZSBVUkwsIG11Y2ggb2YgdGhlIHdyaXR0ZW4gY29udGVudCk7IENvbmZpZGVudGlhbGl0eSBpbXBhY3QgaXMgTm9uZSAob25seSBjcmVhdGlvbiB3YXMgZGVtb25zdHJhdGVkKTsgQXZhaWxhYmlsaXR5IGltcGFjdCBpcyBMb3ctTWVkaXVtIChkaXNrLWV4aGF1c3Rpb24gcG90ZW50aWFsKS4gTm8gYXV0aGVudGljYXRpb24gaXMgcmVxdWlyZWQ7IHRoZSBhdHRhY2tlciBvbmx5IG5lZWRzIHRvIGNvbnRyb2wgYSByZXBvc2l0b3J5IHRoZSB2aWN0aW0gY2xvbmVzIGFuZCBpbml0aWFsaXplcyBzdWJtb2R1bGVzIGZvciAtIGEgcm91dGluZSwgb2Z0ZW4gZnVsbHktYXV0b21hdGljIG9wZXJhdGlvbiBpbiBDSSBwaXBlbGluZXMsIElERSBpbnRlZ3JhdGlvbnMsIGFuZCBkZXBlbmRlbmN5LW1hbmFnZW1lbnQgdG9vbGluZy4KCiMjIyMgU2V2ZXJpdHkKLSBDVlNTIFNjb3JlOiA4LjIgLyAxMCAoSGlnaCkKLSBWZWN0b3IgU3RyaW5nOiBgQ1ZTUzozLjEvQVY6Ti9BQzpML1BSOk4vVUk6Ui9TOkMvQzpOL0k6SC9BOkxgCgojIyMjIFJlZmVyZW5jZXMKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9zZWN1cml0eS9hZHZpc29yaWVzL0dIU0EtaG1xMi13NThmLTI3amNdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vc2VjdXJpdHkvYWR2aXNvcmllcy9HSFNBLWhtcTItdzU4Zi0yN2pjKQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3B1bGwvMjIwMl0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9wdWxsLzIyMDIpCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vY29tbWl0LzQyOTljOTkwZTFjYTIxODk2Zjk0ODUyNzdjYWY3YmIwYWU1YjQwNGNdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vY29tbWl0LzQyOTljOTkwZTFjYTIxODk2Zjk0ODUyNzdjYWY3YmIwYWU1YjQwNGMpCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vY29tbWl0L2U0YjhlN2QwMjZjYTZhYmI0Y2Y2MDRmOGU3NzA5MzQzMmNlMjNjMDZdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vY29tbWl0L2U0YjhlN2QwMjZjYTZhYmI0Y2Y2MDRmOGU3NzA5MzQzMmNlMjNjMDYpCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob25dKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24pCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcmVsZWFzZXMvdGFnLzMuMS41OF0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9yZWxlYXNlcy90YWcvMy4xLjU4KQoKVGhpcyBkYXRhIGlzIHByb3ZpZGVkIGJ5IFtPU1ZdKGh0dHBzOi8vb3N2LmRldi92dWxuZXJhYmlsaXR5L0dIU0EtaG1xMi13NThmLTI3amMpIGFuZCB0aGUgW0dpdEh1YiBBZHZpc29yeSBEYXRhYmFzZV0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdGh1Yi9hZHZpc29yeS1kYXRhYmFzZSkgKFtDQy1CWSA0LjBdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRodWIvYWR2aXNvcnktZGF0YWJhc2UvYmxvYi9tYWluL0xJQ0VOU0UubWQpKS4KPC9kZXRhaWxzPgoKLS0tCgojIyMgR2l0UHl0aG9uOiBnaXQtY29uZmlnIE9QVElPTi1uYW1lIGluamVjdGlvbiB2aWEgPS8jL3doaXRlc3BhY2UgYnlwYXNzZXMgbmFtZSB2YWxpZGF0b3IsIGVuYWJsaW5nIGZvcmdlZCBjb3JlLnNzaENvbW1hbmQvaG9va3NQYXRoIChSQ0UpCltHSFNBLWptNzgtOWZ2di1taGdyXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vYWR2aXNvcmllcy9HSFNBLWptNzgtOWZ2di1taGdyKQoKPGRldGFpbHM+CjxzdW1tYXJ5Pk1vcmUgaW5mb3JtYXRpb248L3N1bW1hcnk+CgojIyMjIERldGFpbHMKIyMjIyMgU3VtbWFyeQpHaXRQeXRob24ncyBjb25maWctbmFtZSB2YWxpZGF0b3Igb25seSBuZXV0cmFsaXplcyBDUi9MRi9OVUwgZm9yIHRoZSBgIm9wdGlvbiJgIGxhYmVsOyBpdCBkb2VzIG5vdCByZWplY3QgYD1gLCBgI2AsIGA7YCwgYFtgLCBgXWAsIG9yIHdoaXRlc3BhY2UgaW4gYW4gKipvcHRpb24gbmFtZSoqLiBgd3JpdGVfc2VjdGlvbmAgd3JpdGVzIHRoZSBvcHRpb24gbmFtZSB2ZXJiYXRpbSBpbnRvIHRoZSBjb25maWcgZmlsZSwgc28gYW4gb3B0aW9uIG5hbWUgc3VjaCBhcyBgc3NoQ29tbWFuZCA9IHRvdWNoIDxjbWQ+ICNgIGlzIHdyaXR0ZW4gYXMgYFx0c3NoQ29tbWFuZCA9IHRvdWNoIDxjbWQ+ICMgPSA8dmFsdWU+YCwgd2hpY2ggZ2l0IHBhcnNlcyBhcyBgY29yZS5zc2hDb21tYW5kID0gdG91Y2ggPGNtZD5gICh0aGUgdHJhaWxpbmcgYCNgIGNvbW1lbnRzIG91dCB0aGUgaW50ZW5kZWQgdmFsdWUpLiBUaGlzIGZvcmdlcyBhcmJpdHJhcnkgY29uZmlnIGRpcmVjdGl2ZXMgKGBjb3JlLnNzaENvbW1hbmRgLCBgY29yZS5ob29rc1BhdGhgLCBgYWxpYXMuKmApIOKGkiBSQ0Ugb24gdGhlIG5leHQgZ2l0IG9wZXJhdGlvbi4gVGhpcyBpcyBhIGRpc3RpbmN0IGZpZWxkIChvcHRpb24gbmFtZSwgbm90IHNlY3Rpb24gbmFtZSkgYW5kIGRpc3RpbmN0IGNoYXJhY3RlciBjbGFzcyAoYD1gL2AjYC9zcGFjZSwgbm90IG5ld2xpbmUvYnJhY2tldCkgZnJvbSBHSFNBLTNycDUtamptdy00d3YyIChzZWN0aW9uLW5hbWUgYnJhY2tldCBpbmplY3Rpb24pIGFuZCBHSFNBLW12OTMtdzc5OS1jajJ3IC8gR0hTQS12ODdyLTZxM2YtMmo2NyAobmV3bGluZSBpbmplY3Rpb24pLgoKIyMjIyMgUm9vdCBDYXVzZQpgX2Fzc3VyZV9jb25maWdfbmFtZV9zYWZlKG5hbWUsIGxhYmVsKWAgKGBnaXQvY29uZmlnLnB5Ojg5N2ApIGFwcGxpZXMgdGhlIGJyYWNrZXQvcXVvdGUgc3RhdGUgbWFjaGluZSBPTkxZIHdoZW4gYGxhYmVsID09ICJzZWN0aW9uImA7IGZvciB0aGUgYCJvcHRpb24iYCBsYWJlbCBpdCBmYWxscyB0aHJvdWdoIHdpdGgganVzdCB0aGUgYFVOU0FGRV9DT05GSUdfQ0hBUlNfUkUgPSBbXHJcblx4MDBdYCByZWdleC4gYHdyaXRlX3NlY3Rpb25gIHRoZW4gd3JpdGVzIHRoZSBvcHRpb24gbmFtZSB2ZXJiYXRpbSBpbnRvIGAiXHQlcyA9ICVzXG4iYCAoY29uZmlnLnB5OjcwMikuCgojIyMjIyBJbXBhY3QKQXJiaXRyYXJ5IGdpdC1jb25maWcgZGlyZWN0aXZlIGluamVjdGlvbiDihpIgcmVtb3RlIGNvZGUgZXhlY3V0aW9uIHZpYSBgY29yZS5zc2hDb21tYW5kYCAoZmlyZXMgb24gYW55IHNzaCBnaXQgb3BlcmF0aW9uLCBubyBzdGFnZWQgZmlsZSBuZWVkZWQpIG9yIGBjb3JlLmhvb2tzUGF0aGAgKHdpdGggYSBzdGFnZWQgaG9vaykuIFJlcXVpcmVzIHRoZSBlbWJlZGRpbmcgYXBwbGljYXRpb24gdG8gZm9yd2FyZCBhIGNhbGxlci1pbmZsdWVuY2VkIE9QVElPTiBOQU1FIGludG8gdGhlIGNvbmZpZyB3cml0ZXIgKG5hbWUtY29udHJvbCBtb2RlbCwgdGhlIHNhbWUgbmFtZS1jb250cm9sIG1vZGVsIGFjY2VwdGVkIGJ5IHRoZSByZWxhdGVkIHB1Ymxpc2hlZCBhZHZpc29yaWVzIEdIU0EtM3JwNS1qam13LTR3djIgYW5kIEdIU0EtbXY5My13Nzk5LWNqMncpLiBEZWZhdWx0IGNvbmZpZ3VyYXRpb24uCgojIyMjIyBQcm9vZiBvZiBDb25jZXB0CmBgYHB5dGhvbgp3aXRoIHJlcG8uY29uZmlnX3dyaXRlcigpIGFzIGN3OgogICAgY3cuc2V0X3ZhbHVlKCJjb3JlIiwgInNzaENvbW1hbmQgPSB0b3VjaCAvdG1wL1JDRSAjIiwgIngiKQoKIyMjIyMgZ2l0IGNvbmZpZyAtLWdldCBjb3JlLnNzaENvbW1hbmQgIC0+ICB0b3VjaCAvdG1wL1JDRQpgYGAKCiMjIyMjIEF0dGFjayBDaGFpbgoxLiBFbnRyeTogYXBwIGNhbGxzIGNvbmZpZyB3cml0ZXIgd2l0aCBhdHRhY2tlci1jb250cm9sbGVkIE9QVElPTiBuYW1lOiBgc2V0X3ZhbHVlKCJjb3JlIiwgInNzaENvbW1hbmQgPSB0b3VjaCAvdG1wL1JDRSAjIiwgIngiKWAuCjIuIENoZWNrOiBgX2Fzc3VyZV9jb25maWdfbmFtZV9zYWZlKG9wdGlvbiwgIm9wdGlvbiIpYCBAJiM4MjAzOyBjb25maWcucHkuIEd1YXJkOiByZWdleCBtYXRjaGVzIG9ubHkgYFtcclxuXHgwMF1gOyBicmFja2V0L3F1b3RlIHN0YXRlIG1hY2hpbmUgaXMgZ2F0ZWQgb24gYGxhYmVsPT0ic2VjdGlvbiJgLiBCeXBhc3MgcHJvb2Y6IGA9YCxgI2Asc3BhY2UgcGFzcyDihpIgbm8gYFZhbHVlRXJyb3JgLgozLiBTaW5rOiBgd3JpdGVfc2VjdGlvbmAgd3JpdGVzIGAiXHRzc2hDb21tYW5kID0gdG91Y2ggL3RtcC9SQ0UgIyA9IHhcbiJgIChjb25maWcucHk6NzAyKS4KNC4gSW1wYWN0OiBnaXQgcGFyc2VzIGBjb3JlLnNzaENvbW1hbmQ9dG91Y2ggL3RtcC9SQ0VgIOKGkiBhcmJpdHJhcnkgY29kZSBleGVjdXRpb24gb24gbmV4dCBnaXQgb3AuCgojIyMjIyBCeXBhc3MgRXZpZGVuY2UKSW5kZXBlbmRlbnRseSByZXByb2R1Y2VkIChnYXRlIGhhcm5lc3MpOiBgc2V0X3ZhbHVlKCdjb3JlJywnc3NoQ29tbWFuZCA9IHRvdWNoIDxSQ0U+ICMnLCd4JylgIOKGkiBubyBgVmFsdWVFcnJvcmA7IGZpbGUgbGluZSBgc3NoQ29tbWFuZCA9IHRvdWNoIDxSQ0U+ICMgPSB4YDsgYGdpdCBjb25maWcgLS1nZXQgY29yZS5zc2hDb21tYW5kYCDihpIgYHRvdWNoIDxSQ0U+YCAocmM9MCkuIEFsc28gdmVyaWZpZWQgYGNvcmUuaG9va3NQYXRoYCB2aWEgYm90aCBgR2l0Q29uZmlnUGFyc2VyYCBhbmQgYHJlcG8uY29uZmlnX3dyaXRlcigpYC4gRml4LWNvbW1pdCByZWFkOiBicmFja2V0L3F1b3RlIGNoZWNrcyBhcmUgaW5zaWRlIGBpZiBsYWJlbCA9PSAic2VjdGlvbiJgOyB0aGUgYCJvcHRpb24iYCBsYWJlbCBpcyBub3QgY292ZXJlZC4KCiMjIyMjIEFmZmVjdGVkIFZlcnNpb25zCmBHaXRQeXRob24gPD0gMy4xLjU3YCAodmFsaWRhdG9yIHByZXNlbnQgdmVyYmF0aW0gb24gdGhlIGxhdGVzdCByZWxlYXNlIHRhZykuCgojIyMjIyBTdWdnZXN0ZWQgRml4CkFwcGx5IHRoZSBzZWN0aW9uLW5hbWUgc2FmZXR5IGNoZWNrcyAocmVqZWN0IGA9YCwgYCNgLCBgO2AsIGBbYCwgYF1gLCB3aGl0ZXNwYWNlKSB0byB0aGUgYCJvcHRpb24iYCBsYWJlbCBhcyB3ZWxsLCBvciB2YWxpZGF0ZSB0aGUgZnVsbHktcmVuZGVyZWQgY29uZmlnIGxpbmUgYWZ0ZXIgc3Vic3RpdHV0aW9uLgoKLS0tClJlcG9ydGVkIGJ5ICoqenggKEphY2UpKiog4oCUIEdpdEh1YjogQCYjODIwMzttYW51cy11c2UKCiMjIyMgU2V2ZXJpdHkKLSBDVlNTIFNjb3JlOiA4LjggLyAxMCAoSGlnaCkKLSBWZWN0b3IgU3RyaW5nOiBgQ1ZTUzozLjEvQVY6Ti9BQzpML1BSOkwvVUk6Ti9TOlUvQzpIL0k6SC9BOkhgCgojIyMjIFJlZmVyZW5jZXMKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9zZWN1cml0eS9hZHZpc29yaWVzL0dIU0Etam03OC05ZnZ2LW1oZ3JdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vc2VjdXJpdHkvYWR2aXNvcmllcy9HSFNBLWptNzgtOWZ2di1taGdyKQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3B1bGwvMjIwNF0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9wdWxsLzIyMDQpCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vY29tbWl0L2E0OTVjY2QzYjU0N2NjZDYwYjIxODcyMTU4MjNiNzJhOWMwMTg4YmZdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vY29tbWl0L2E0OTVjY2QzYjU0N2NjZDYwYjIxODcyMTU4MjNiNzJhOWMwMTg4YmYpCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob25dKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24pCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcmVsZWFzZXMvdGFnLzMuMS41OF0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9yZWxlYXNlcy90YWcvMy4xLjU4KQoKVGhpcyBkYXRhIGlzIHByb3ZpZGVkIGJ5IFtPU1ZdKGh0dHBzOi8vb3N2LmRldi92dWxuZXJhYmlsaXR5L0dIU0Etam03OC05ZnZ2LW1oZ3IpIGFuZCB0aGUgW0dpdEh1YiBBZHZpc29yeSBEYXRhYmFzZV0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdGh1Yi9hZHZpc29yeS1kYXRhYmFzZSkgKFtDQy1CWSA0LjBdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRodWIvYWR2aXNvcnktZGF0YWJhc2UvYmxvYi9tYWluL0xJQ0VOU0UubWQpKS4KPC9kZXRhaWxzPgoKLS0tCgojIyMgR2l0UHl0aG9uOiBVbnNhZmUgZ2l0IG9wdGlvbiBndWFyZCBieXBhc3MgdmlhIHNwbGl0X3NpbmdsZV9jaGFyX29wdGlvbnM9RmFsc2Ugc2hvcnQtb3B0aW9uIHRva2VuIHNtdWdnbGluZyBlbmFibGVzIGNvbW1hbmQgZXhlY3V0aW9uCltHSFNBLXd2cHAtOGh4OS1wNjZqXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vYWR2aXNvcmllcy9HSFNBLXd2cHAtOGh4OS1wNjZqKQoKPGRldGFpbHM+CjxzdW1tYXJ5Pk1vcmUgaW5mb3JtYXRpb248L3N1bW1hcnk+CgojIyMjIERldGFpbHMKIyMjIyMgU3VtbWFyeQpUaGUgYGNoZWNrX3Vuc2FmZV9vcHRpb25zYCBndWFyZCBjYW4gYmUgYnlwYXNzZWQgb24gZXZlcnkgZ3VhcmRlZCBtZXRob2QgKGNsb25lL2Nsb25lX2Zyb20sIGZldGNoL3B1bGwvcHVzaCwgbHNfcmVtb3RlLCBpdGVyX2NvbW1pdHMsIGJsYW1lLCBhcmNoaXZlKSBieSBjb21iaW5pbmcgYSBzaW5nbGUtY2hhcmFjdGVyIGt3YXJnIHdpdGggYHNwbGl0X3NpbmdsZV9jaGFyX29wdGlvbnM9RmFsc2VgLiBUaGUgZ3VhcmQncyBjYW5kaWRhdGUgbGlzdCBvbWl0cyB0aGUgc211Z2dsZWQgb3B0aW9uLCBidXQgYHRyYW5zZm9ybV9rd2FyZ2AgZW1pdHMgYSBKT0lORUQgYC1uPHZhbHVlPmAgYXJndiB0b2tlbiB0aGF0IGdpdCBwYXJzZXMgYXMgYC0tdXBsb2FkLXBhY2s9PGNtZD5gLCB5aWVsZGluZyBhcmJpdHJhcnkgY29tbWFuZCBleGVjdXRpb24gYXQgdGhlIGRlZmF1bHQgYGFsbG93X3Vuc2FmZV9vcHRpb25zPUZhbHNlYC4gVGhpcyBpcyBhbiBpbmNvbXBsZXRlLWZpeCBieXBhc3Mgb2YgY29tbWl0IGBlOGQwZmJmN2AgKHRoZSBmaXggZm9yIEdIU0Etcjltci1tMzdjLTVmcjMpLCB3aGljaCBvbmx5IGVtaXRzIHZhbHVlLWRlcml2ZWQgY2FuZGlkYXRlcyB3aGVuIGBzcGxpdF9zaW5nbGVfY2hhcl9vcHRpb25zYCBpcyBUcnVlLgoKIyMjIyMgUm9vdCBDYXVzZQpgX29wdGlvbl9jYW5kaWRhdGVzYCBkZXJpdmVzIHZhbHVlLXRva2VuIGNhbmRpZGF0ZXMgb25seSB1bmRlciBgaWYgbGVuKGtleSk9PTEgYW5kIHNwbGl0X3NpbmdsZV9jaGFyX29wdGlvbnM6YCAoY21kLnB5OjEwNDgsIGFkZGVkIGJ5IGBlOGQwZmJmN2ApLiBXaXRoIGBzcGxpdF9zaW5nbGVfY2hhcl9vcHRpb25zPUZhbHNlYCwgYF9vcHRpb25fY2FuZGlkYXRlcyhbXSwgeyJuIjoidXRvdWNoIDxjbWQ+O2dpdC11cGxvYWQtcGFjayJ9KWAgcmV0dXJucyBvbmx5IGBbJy1uJ11gIChub3Qgb24gdGhlIGRlbnlsaXN0KSwgc28gdGhlIGd1YXJkIHBhc3Nlcy4gQnV0IGB0cmFuc2Zvcm1fa3dhcmcoJ24nLCB2YWx1ZSwgc3BsaXRfc2luZ2xlX2NoYXJfb3B0aW9ucz1GYWxzZSlgIGVtaXRzIHRoZSBKT0lORUQgdG9rZW4gYC1udXRvdWNoIDxjbWQ+O2dpdC11cGxvYWQtcGFja2AgKGNtZC5weToxNjMxKS4gZ2l0IGNsdXN0ZXJzIHZhbHVlLWxlc3Mgc2hvcnQgZmxhZ3MgdGhlbiBwYXJzZXMgYC11PGNtZD5gID0gYC0tdXBsb2FkLXBhY2s9PGNtZD5gIOKGkiBjb21tYW5kIGV4ZWN1dGlvbi4gVGhlIGhhcmRlbmVkIGd1YXJkIFdPVUxEIGJsb2NrIHRoZSBqb2luZWQgdG9rZW4gaWYgaXQgc2F3IGl0IOKAlCB0aGUgZmxhdyBpcyBpdCBuZXZlciByZWNlaXZlcyBpdC4KCiMjIyMjIEltcGFjdApBcmJpdHJhcnkgT1MgY29tbWFuZCBleGVjdXRpb24gYXMgdGhlIGhvc3QgcHJvY2VzcyAodmlhIGAtLXVwbG9hZC1wYWNrYCkgYXQgZGVmYXVsdCBgYWxsb3dfdW5zYWZlX29wdGlvbnM9RmFsc2VgLCBhZmZlY3RpbmcgYWxsIGd1YXJkZWQgbWV0aG9kcyB0aGF0IGZvcndhcmQga3dhcmdzLiBQcmVjb25kaXRpb246IHRoZSBhcHAgZm9yd2FyZHMgYSB1c2VyLWNvbnRyb2xsZWQga3dhcmdzIGRpY3QgY29udGFpbmluZyBgc3BsaXRfc2luZ2xlX2NoYXJfb3B0aW9ucz1GYWxzZWAgcGx1cyBhIHNpbmdsZS1jaGFyIGtleSAoc2FtZSB1c2VyLWRpY3QtZm9yd2FyZGluZyBtb2RlbCBHSFNBLXI5bXItbTM3Yy01ZnIzIGFjY2VwdHMpLgoKIyMjIyMgUHJvb2Ygb2YgQ29uY2VwdApgYGBweXRob24KZnJvbSBnaXQgaW1wb3J0IFJlcG8KUmVwby5jbG9uZV9mcm9tKHNyYywgZHN0LAogICAgbj0idXRvdWNoIC90bXAvQUNFO2dpdC11cGxvYWQtcGFjayIsCiAgICBzcGxpdF9zaW5nbGVfY2hhcl9vcHRpb25zPUZhbHNlKSAgICMgL3RtcC9BQ0UgY3JlYXRlZCAtPiBBQ0UKYGBgCgojIyMjIyBBdHRhY2sgQ2hhaW4KMS4gRW50cnk6IGFwcCBmb3J3YXJkcyB1c2VyIGt3YXJncyB0byBgUmVwby5jbG9uZV9mcm9tKHVybCwgcGF0aCwgKiprd2FyZ3MpYDogYHtzcGxpdF9zaW5nbGVfY2hhcl9vcHRpb25zOiBGYWxzZSwgbjogJ3V0b3VjaCAvdG1wL0FDRTtnaXQtdXBsb2FkLXBhY2snfWAuCjIuIENoZWNrOiBgY2hlY2tfdW5zYWZlX29wdGlvbnMoX29wdGlvbl9jYW5kaWRhdGVzKFtdLCBrd2FyZ3MpLCB1bnNhZmVfZ2l0X2Nsb25lX29wdGlvbnMpYC4gR3VhcmQ6IGRlbnlsaXN0IGluY2x1ZGVzIGAtLXVwbG9hZC1wYWNrYC9gLXVgLiBCeXBhc3MgcHJvb2Y6IGBfb3B0aW9uX2NhbmRpZGF0ZXNgIHlpZWxkcyBvbmx5IGBbJy1uJ11gICh2YWx1ZSB0b2tlbiBza2lwcGVkIGJlY2F1c2UgYHNwbGl0PUZhbHNlYCk7IGd1YXJkIG5ldmVyIHNlZXMgYC11YC4KMy4gU2luazogYHRyYW5zZm9ybV9rd2FyZ2AgZW1pdHMgam9pbmVkIHRva2VuIChjbWQucHk6MTYzMSkuIGFyZ3YgKG9ic2VydmVkKTogYFsnZ2l0JywnY2xvbmUnLCctdicsJy1udXRvdWNoIC90bXAvQUNFO2dpdC11cGxvYWQtcGFjaycsJy0tJywnPHNyYz4nLCc8ZHN0PiddYC4KNC4gSW1wYWN0OiBnaXQgY2x1c3RlcnMgYC1uYCArIGAtdTxjbWQ+YCDihpIgcnVucyB1cGxvYWQtcGFjayBjb21tYW5kIOKGkiBBQ0UuCgojIyMjIyBCeXBhc3MgRXZpZGVuY2UKSW5kZXBlbmRlbnRseSByZXByb2R1Y2VkIChnYXRlIGhhcm5lc3MsIGRlZmF1bHQgYGFsbG93X3Vuc2FmZV9vcHRpb25zPUZhbHNlYCk6IHRoZSBgc3BsaXQ9RmFsc2VgIHBheWxvYWQgY3JlYXRlZCB0aGUgbWFya2VyIGBWSDA1X0dBVEVfQUNFYCAoQUNFKTsgdGhlIGNsb25lIHJldHVybmVkIG5vcm1hbGx5IChndWFyZCBieXBhc3NlZCkuIENvbnRyb2w6IGBuPSctLXVwbG9hZC1wYWNrPeKApidgIChzcGxpdCBkZWZhdWx0IFRydWUpIOKGkiBgVW5zYWZlT3B0aW9uRXJyb3I6IC0tdXBsb2FkLXBhY2sgaXMgbm90IGFsbG93ZWRgLiBGaXgtY29tbWl0IHJlYWQ6IGBlOGQwZmJmN2AgZXh0ZW5kcyBjYW5kaWRhdGVzIG9ubHkgdW5kZXIgYGlmIGxlbihrZXkpPT0xIGFuZCBzcGxpdF9zaW5nbGVfY2hhcl9vcHRpb25zOmAg4oCUIHNwbGl0PUZhbHNlIHNraXBzIHZhbHVlIGVtaXNzaW9uLiBBbHNvIGNvbmZpcm1lZCB0aGUgZWFybGllciBjbHVzdGVyaW5nLXBhcnNlIGZpeCAoY29tbWl0IGA1NjgwNjA4MGApIGRvZXMgbm90IGNvdmVyIHRoaXMgYmVjYXVzZSB0aGUgZ3VhcmQgb25seSBldmVyIHJlY2VpdmVzIGBbJy1uJ11gLgoKIyMjIyMgQWZmZWN0ZWQgVmVyc2lvbnMKYEdpdFB5dGhvbiA8PSAzLjEuNTdgIChjb2RlIHByZXNlbnQgdmVyYmF0aW0gb24gdGhlIGxhdGVzdCByZWxlYXNlIHRhZykuCgojIyMjIyBTdWdnZXN0ZWQgRml4Ck1ha2UgYF9vcHRpb25fY2FuZGlkYXRlc2AgZW1pdCB2YWx1ZS1kZXJpdmVkIGNhbmRpZGF0ZXMgcmVnYXJkbGVzcyBvZiBgc3BsaXRfc2luZ2xlX2NoYXJfb3B0aW9uc2AgKGkuZS4gYWxzbyBmb3IgdGhlIGpvaW5lZCBgLW48dmFsdWU+YCBmb3JtKSwgT1IgcnVuIGBjaGVja191bnNhZmVfb3B0aW9uc2Agb3ZlciB0aGUgZnVsbHktdHJhbnNmb3JtZWQgYXJndiByYXRoZXIgdGhhbiB0aGUgcmVjb25zdHJ1Y3RlZCBuYW1lLW9ubHkgY2FuZGlkYXRlIGxpc3QuCgotLS0KUmVwb3J0ZWQgYnkgKip6eCAoSmFjZSkqKiDigJQgR2l0SHViOiBAJiM4MjAzO21hbnVzLXVzZQoKIyMjIyBTZXZlcml0eQotIENWU1MgU2NvcmU6IDguOCAvIDEwIChIaWdoKQotIFZlY3RvciBTdHJpbmc6IGBDVlNTOjMuMS9BVjpOL0FDOkwvUFI6TC9VSTpOL1M6VS9DOkgvSTpIL0E6SGAKCiMjIyMgUmVmZXJlbmNlcwotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3NlY3VyaXR5L2Fkdmlzb3JpZXMvR0hTQS13dnBwLThoeDktcDY2al0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9zZWN1cml0eS9hZHZpc29yaWVzL0dIU0Etd3ZwcC04aHg5LXA2NmopCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcHVsbC8yMjA0XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3B1bGwvMjIwNCkKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9jb21taXQvOTZhODg4ZjRkNzgyY2IyZjgwNDUyMTQ4ZTQ4ZTYwY2U0YWY2ZDU0MV0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9jb21taXQvOTZhODg4ZjRkNzgyY2IyZjgwNDUyMTQ4ZTQ4ZTYwY2U0YWY2ZDU0MSkKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbl0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbikKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9yZWxlYXNlcy90YWcvMy4xLjU4XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3JlbGVhc2VzL3RhZy8zLjEuNTgpCgpUaGlzIGRhdGEgaXMgcHJvdmlkZWQgYnkgW09TVl0oaHR0cHM6Ly9vc3YuZGV2L3Z1bG5lcmFiaWxpdHkvR0hTQS13dnBwLThoeDktcDY2aikgYW5kIHRoZSBbR2l0SHViIEFkdmlzb3J5IERhdGFiYXNlXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0aHViL2Fkdmlzb3J5LWRhdGFiYXNlKSAoW0NDLUJZIDQuMF0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdGh1Yi9hZHZpc29yeS1kYXRhYmFzZS9ibG9iL21haW4vTElDRU5TRS5tZCkpLgo8L2RldGFpbHM+CgotLS0KCiMjIyBSZWxlYXNlIE5vdGVzCgo8ZGV0YWlscz4KPHN1bW1hcnk+Z2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uIChHaXRQeXRob24pPC9zdW1tYXJ5PgoKIyMjIFtgdjMuMS41OGBdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcmVsZWFzZXMvdGFnLzMuMS41OCk6IFNlY3VyaXR5IGFuZCBGaXhlcwoKW0NvbXBhcmUgU291cmNlXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL2NvbXBhcmUvMy4xLjU3Li4uMy4xLjU4KQoKIyMjIyMgV2hhdCdzIENoYW5nZWQKCi0gdGVzdDogYWxsb3cgUHl0aG9uIHN0YXJ0dXAgYmVmb3JlIHRpbWVvdXQgYnkgW0AmIzgyMDM7Qnlyb25dKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9CeXJvbikgaW4gWyMmIzgyMDM7MjE5NV0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9wdWxsLzIxOTUpCi0gUmVzb2x2ZSBXaW5kb3dzIGhvb2sgQmFzaCB0aHJvdWdoIFBBVEggYnkgW0AmIzgyMDM7Qnlyb25dKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9CeXJvbikgaW4gWyMmIzgyMDM7MjE5OV0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9wdWxsLzIxOTkpCi0gUmV2ZXJ0ICJSZXNvbHZlIFdpbmRvd3MgaG9vayBCYXNoIHRocm91Z2ggUEFUSCIgYnkgW0AmIzgyMDM7Qnlyb25dKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9CeXJvbikgaW4gWyMmIzgyMDM7MjIwMF0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9wdWxsLzIyMDApCi0gdGVzdDogZm9jdXMgcHl0ZXN0IHN1bW1hcnkgb24gdW5leHBlY3RlZCBmYWlsdXJlcyBieSBbQCYjODIwMztyYWlzdWxjaG93ZGh1cnldKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9yYWlzdWxjaG93ZGh1cnkpIGluIFsjJiM4MjAzOzIyMDNdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcHVsbC8yMjAzKQotIFZhbGlkYXRlIHN1Ym1vZHVsZSBuYW1lcyBiZWZvcmUgZmlsZXN5c3RlbSBvcGVyYXRpb25zIGJ5IFtAJiM4MjAzO0J5cm9uXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vQnlyb24pIGluIFsjJiM4MjAzOzIyMDJdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcHVsbC8yMjAyKQotIEhhbmRsZSBpbnZhbGlkIHN1Ym1vZHVsZSBuYW1lcyBkdXJpbmcgcmVjdXJzaXZlIHVwZGF0ZXMgYnkgW0AmIzgyMDM7Qnlyb25dKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9CeXJvbikgaW4gWyMmIzgyMDM7MjIwNV0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9wdWxsLzIyMDUpCi0gRml4IFdpbmRvd3MgcGF0aCBoYW5kbGluZyBvbiBQeXRob24gMy4xMysgYnkgW0AmIzgyMDM7Qnlyb25dKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9CeXJvbikgaW4gWyMmIzgyMDM7MjE5Nl0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9wdWxsLzIxOTYpCi0gZml4dXAgMjIwMiBieSBbQCYjODIwMztCeXJvbl0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL0J5cm9uKSBpbiBbIyYjODIwMzsyMjA2XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3B1bGwvMjIwNikKLSBDb3JyZWN0IFdpbmRvd3MgaG9vayBCYXNoIHByZWNlZGVuY2UgYnkgW0AmIzgyMDM7Qnlyb25dKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9CeXJvbikgaW4gWyMmIzgyMDM7MjIwMV0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9wdWxsLzIyMDEpCi0gSGFyZGVuIGNvbmZpZyBhbmQgR2l0IG9wdGlvbiB2YWxpZGF0aW9uIGJ5IFtAJiM4MjAzO0J5cm9uXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vQnlyb24pIGluIFsjJiM4MjAzOzIyMDRdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcHVsbC8yMjA0KQotIFNraXAgdGVzdHMgdGhhdCBuZWVkIHN5bWxpbmsgcHJpdmlsZWdlcyBpbnN0ZWFkIG9mIGVycm9yaW5nIGJ5IFtAJiM4MjAzO0N5cnVzNTgwNTI5XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vQ3lydXM1ODA1MjkpIGluIFsjJiM4MjAzOzIxOTddKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcHVsbC8yMTk3KQoKIyMjIyMgTmV3IENvbnRyaWJ1dG9ycwoKLSBbQCYjODIwMztyYWlzdWxjaG93ZGh1cnldKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9yYWlzdWxjaG93ZGh1cnkpIG1hZGUgdGhlaXIgZmlyc3QgY29udHJpYnV0aW9uIGluIFsjJiM4MjAzOzIyMDNdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcHVsbC8yMjAzKQotIFtAJiM4MjAzO0N5cnVzNTgwNTI5XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vQ3lydXM1ODA1MjkpIG1hZGUgdGhlaXIgZmlyc3QgY29udHJpYnV0aW9uIGluIFsjJiM4MjAzOzIxOTddKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcHVsbC8yMTk3KQoKKipGdWxsIENoYW5nZWxvZyoqOiA8aHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9jb21wYXJlLzMuMS41Ny4uLjMuMS41OD4KCjwvZGV0YWlscz4KCi0tLQoKIyMjIENvbmZpZ3VyYXRpb24KCvCfk4UgKipTY2hlZHVsZSoqOiAoVVRDKQoKLSBCcmFuY2ggY3JlYXRpb24KICAtIEF0IGFueSB0aW1lIChubyBzY2hlZHVsZSBkZWZpbmVkKQotIEF1dG9tZXJnZQogIC0gQXQgYW55IHRpbWUgKG5vIHNjaGVkdWxlIGRlZmluZWQpCgrwn5qmICoqQXV0b21lcmdlKio6IERpc2FibGVkIGJ5IGNvbmZpZy4gUGxlYXNlIG1lcmdlIHRoaXMgbWFudWFsbHkgb25jZSB5b3UgYXJlIHNhdGlzZmllZC4KCuKZuyAqKlJlYmFzaW5nKio6IFdoZW5ldmVyIFBSIGJlY29tZXMgY29uZmxpY3RlZCwgb3IgeW91IHRpY2sgdGhlIHJlYmFzZS9yZXRyeSBjaGVja2JveC4KCvCflJUgKipJZ25vcmUqKjogQ2xvc2UgdGhpcyBQUiBhbmQgeW91IHdvbid0IGJlIHJlbWluZGVkIGFib3V0IHRoZXNlIHVwZGF0ZXMgYWdhaW4uCgotLS0KCiAtIFsgXSA8IS0tIHJlYmFzZS1jaGVjayAtLT5JZiB5b3Ugd2FudCB0byByZWJhc2UvcmV0cnkgdGhpcyBQUiwgY2hlY2sgdGhpcyBib3gKCi0tLQoKVGhpcyBQUiB3YXMgZ2VuZXJhdGVkIGJ5IFtNZW5kIFJlbm92YXRlXShodHRwczovL21lbmQuaW8vcmVub3ZhdGUvKS4gVmlldyB0aGUgW3JlcG9zaXRvcnkgam9iIGxvZ10oaHR0cHM6Ly9kZXZlbG9wZXIubWVuZC5pby9naXRodWIvb3Npc20vcHl0aG9uLW9zaXNtKS4KPCEtLXJlbm92YXRlLWRlYnVnOmV5SmpjbVZoZEdWa1NXNVdaWElpT2lJME5DNHhNaTR3SWl3aWRYQmtZWFJsWkVsdVZtVnlJam9pTkRRdU1USXVNQ0lzSW5SaGNtZGxkRUp5WVc1amFDSTZJbTFoYVc0aUxDSnNZV0psYkhNaU9sc2ljbVZ1YjNaaGRHVWlYWDA9LS0+Cg==
      patchset: 8f8d2989b17d7199dea1d0770f90e6edaa6b261f
      pipeline: check
      playbook_context:
        playbook_projects:
          trusted/project_0/github.com/osism/zuul-config:
            canonical_name: github.com/osism/zuul-config
            checkout: main
            commit: 71b711c422c10c242a8f785dc6d41ed9d12e9cd3
          trusted/project_1/github.com/osism/openinfra-zuul-jobs:
            canonical_name: github.com/osism/openinfra-zuul-jobs
            checkout: master
            commit: 242732586e2cba04d04867d3e302888c766bc231
          trusted/project_2/github.com/osism/zuul-jobs:
            canonical_name: github.com/osism/zuul-jobs
            checkout: main
            commit: b7c70f39598a39998dbbc6f833779355630f3a39
          untrusted/project_0/github.com/osism/zuul-jobs:
            canonical_name: github.com/osism/zuul-jobs
            checkout: main
            commit: b7c70f39598a39998dbbc6f833779355630f3a39
          untrusted/project_1/github.com/osism/zuul-config:
            canonical_name: github.com/osism/zuul-config
            checkout: main
            commit: 71b711c422c10c242a8f785dc6d41ed9d12e9cd3
          untrusted/project_2/github.com/osism/openinfra-zuul-jobs:
            canonical_name: github.com/osism/openinfra-zuul-jobs
            checkout: master
            commit: 242732586e2cba04d04867d3e302888c766bc231
        playbooks:
        - path: untrusted/project_0/github.com/osism/zuul-jobs/playbooks/mypy/run.yaml
          roles:
          - checkout: main
            checkout_description: zuul branch
            link_name: ansible/playbook_0/role_0/zuul-config
            link_target: untrusted/project_1/github.com/osism/zuul-config
            role_path: ansible/playbook_0/role_0/zuul-config/roles
          - checkout: master
            checkout_description: project default branch
            link_name: ansible/playbook_0/role_1/openinfra-zuul-jobs
            link_target: untrusted/project_2/github.com/osism/openinfra-zuul-jobs
            role_path: ansible/playbook_0/role_1/openinfra-zuul-jobs/roles
          - checkout: main
            checkout_description: playbook branch
            link_name: ansible/playbook_0/role_2/zuul-jobs
            link_target: untrusted/project_0/github.com/osism/zuul-jobs
            role_path: ansible/playbook_0/role_2/zuul-jobs/roles
      post_review: false
      post_timeout: 1800
      pre_timeout: null
      project:
        canonical_hostname: github.com
        canonical_name: github.com/osism/python-osism
        name: osism/python-osism
        short_name: python-osism
        src_dir: src/github.com/osism/python-osism
      projects:
        github.com/osism/python-osism:
          canonical_hostname: github.com
          canonical_name: github.com/osism/python-osism
          checkout: main
          checkout_description: zuul branch
          commit: 13b42a5fba05001ec11ff5fdf649d2a93c620f73
          name: osism/python-osism
          required: false
          short_name: python-osism
          src_dir: src/github.com/osism/python-osism
      ref: refs/pull/2587/head
      resources: {}
      tenant: osism
      timeout: 1800
      topic: null
      voting: true
