all:
  children:
    zuul_unreachable:
      hosts: {}
  hosts:
    debian-bookworm:
      ansible_connection: ssh
      ansible_host: 2a13:1a81:8000:3124:f816:3eff:fedd:665e
      ansible_port: 22
      ansible_python_interpreter: auto
      ansible_user: zuul
      nodepool:
        az: nova
        cloud: regiocloud-a-ci
        external_id: 28e459d8-feb6-4488-a565-cbb9be9a6831
        host_id: 4ba4344415ca7057d9956ea5de826bbc0b830981e82c0e0f191fa07b
        interface_ip: 2a13:1a81:8000:3124:f816:3eff:fedd:665e
        label: debian-bookworm
        node_properties: {}
        private_ipv4: 10.128.7.211
        private_ipv6: null
        provider: regiocloud-a
        public_ipv4: 81.163.193.82
        public_ipv6: 2a13:1a81:8000:3124:f816:3eff:fedd:665e
        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 yamllint explicit: None implied: {MatchAny:{ImpliedBranchMatcher:main}}
        source: osism/zuul-jobs/.zuul.yaml@main#59>'
      - '<Job yamllint explicit: None implied: None source: osism/netbox-manager/.zuul.yaml@main#39>'
      ansible_version: '9'
      attempts: 1
      branch: main
      build: 5326e7f89e834d2a97704f1e4c44d7ca
      build_refs:
      - branch: main
        change: '293'
        change_message: "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> [!WARNING]\n> Some dependencies could not be looked up. Check
          the [Dependency Dashboard](../issues/1) for more information.\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/netbox-manager).\n<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMi4wIiwidXBkYXRlZEluVmVyIjoiNDQuMTIuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsicmVub3ZhdGUiXX0=-->\n"
        change_url: https://github.com/osism/netbox-manager/pull/293
        commit_id: 916c14ee794a8c2453de3bc8d0a3293f7d9ae186
        patchset: 916c14ee794a8c2453de3bc8d0a3293f7d9ae186
        project:
          canonical_hostname: github.com
          canonical_name: github.com/osism/netbox-manager
          name: osism/netbox-manager
          short_name: netbox-manager
        src_dir: src/github.com/osism/netbox-manager
        topic: null
      buildset: f4e34c3552874ac1acc88cff999b53d8
      buildset_refs:
      - branch: main
        change: '293'
        change_message: "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> [!WARNING]\n> Some dependencies could not be looked up. Check
          the [Dependency Dashboard](../issues/1) for more information.\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/netbox-manager).\n<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMi4wIiwidXBkYXRlZEluVmVyIjoiNDQuMTIuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsicmVub3ZhdGUiXX0=-->\n"
        change_url: https://github.com/osism/netbox-manager/pull/293
        commit_id: 916c14ee794a8c2453de3bc8d0a3293f7d9ae186
        patchset: 916c14ee794a8c2453de3bc8d0a3293f7d9ae186
        project:
          canonical_hostname: github.com
          canonical_name: github.com/osism/netbox-manager
          name: osism/netbox-manager
          short_name: netbox-manager
        src_dir: src/github.com/osism/netbox-manager
        topic: null
      change: '293'
      change_message: "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> [!WARNING]\n> Some dependencies could not be looked up. Check
        the [Dependency Dashboard](../issues/1) for more information.\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/netbox-manager).\n<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMi4wIiwidXBkYXRlZEluVmVyIjoiNDQuMTIuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsicmVub3ZhdGUiXX0=-->\n"
      change_url: https://github.com/osism/netbox-manager/pull/293
      child_jobs: []
      commit_id: 916c14ee794a8c2453de3bc8d0a3293f7d9ae186
      event_id: ac3c88b0-9285-11f1-8ac3-f69549f771c1
      executor:
        hostname: 521e9411259a
        inventory_file: /var/lib/zuul/builds/5326e7f89e834d2a97704f1e4c44d7ca/ansible/inventory.yaml
        log_root: /var/lib/zuul/builds/5326e7f89e834d2a97704f1e4c44d7ca/work/logs
        result_data_file: /var/lib/zuul/builds/5326e7f89e834d2a97704f1e4c44d7ca/work/results.json
        src_root: /var/lib/zuul/builds/5326e7f89e834d2a97704f1e4c44d7ca/work/src
        work_root: /var/lib/zuul/builds/5326e7f89e834d2a97704f1e4c44d7ca/work
      include_vars: []
      items:
      - branch: main
        change: '293'
        change_message: "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> [!WARNING]\n> Some dependencies could not be looked up. Check
          the [Dependency Dashboard](../issues/1) for more information.\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/netbox-manager).\n<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMi4wIiwidXBkYXRlZEluVmVyIjoiNDQuMTIuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsicmVub3ZhdGUiXX0=-->\n"
        change_url: https://github.com/osism/netbox-manager/pull/293
        commit_id: 916c14ee794a8c2453de3bc8d0a3293f7d9ae186
        patchset: 916c14ee794a8c2453de3bc8d0a3293f7d9ae186
        project:
          canonical_hostname: github.com
          canonical_name: github.com/osism/netbox-manager
          name: osism/netbox-manager
          short_name: netbox-manager
          src_dir: src/github.com/osism/netbox-manager
        topic: null
      job: yamllint
      jobtags: []
      max_attempts: 3
      message: VXBkYXRlIGRlcGVuZGVuY3kgR2l0UHl0aG9uIHRvIHYzLjEuNTggW1NFQ1VSSVRZXQoKVGhpcyBQUiBjb250YWlucyB0aGUgZm9sbG93aW5nIHVwZGF0ZXM6Cgp8IFBhY2thZ2UgfCBDaGFuZ2UgfCBbQWdlXShodHRwczovL2RvY3MucmVub3ZhdGVib3QuY29tL21lcmdlLWNvbmZpZGVuY2UvKSB8IFtDb25maWRlbmNlXShodHRwczovL2RvY3MucmVub3ZhdGVib3QuY29tL21lcmdlLWNvbmZpZGVuY2UvKSB8CnwtLS18LS0tfC0tLXwtLS18CnwgW0dpdFB5dGhvbl0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbikgfCBgPT0zLjEuNTdgIOKGkiBgPT0zLjEuNThgIHwgIVthZ2VdKGh0dHBzOi8vZGV2ZWxvcGVyLm1lbmQuaW8vYXBpL21jL2JhZGdlcy9hZ2UvcHlwaS9naXRweXRob24vMy4xLjU4P3NsaW09dHJ1ZSkgfCAhW2NvbmZpZGVuY2VdKGh0dHBzOi8vZGV2ZWxvcGVyLm1lbmQuaW8vYXBpL21jL2JhZGdlcy9jb25maWRlbmNlL3B5cGkvZ2l0cHl0aG9uLzMuMS41Ny8zLjEuNTg/c2xpbT10cnVlKSB8CgotLS0KCj4gWyFXQVJOSU5HXQo+IFNvbWUgZGVwZW5kZW5jaWVzIGNvdWxkIG5vdCBiZSBsb29rZWQgdXAuIENoZWNrIHRoZSBbRGVwZW5kZW5jeSBEYXNoYm9hcmRdKC4uL2lzc3Vlcy8xKSBmb3IgbW9yZSBpbmZvcm1hdGlvbi4KCi0tLQoKIyMjIEdpdFB5dGhvbjogVW5ndWFyZGVkIGdpdCByZWFkLXRyZWUgb3B0aW9uIGZvcndhcmRpbmcgaW4gSW5kZXhGaWxlLmZyb21fdHJlZS9yZXNldC9tZXJnZV90cmVlIGVuYWJsZXMgYXJiaXRyYXJ5IGZpbGUgb3ZlcndyaXRlCltHSFNBLTRnbXctZ2cybS13NDZwXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vYWR2aXNvcmllcy9HSFNBLTRnbXctZ2cybS13NDZwKQoKPGRldGFpbHM+CjxzdW1tYXJ5Pk1vcmUgaW5mb3JtYXRpb248L3N1bW1hcnk+CgojIyMjIERldGFpbHMKIyMjIyMgU3VtbWFyeQpgSW5kZXhGaWxlLmZyb21fdHJlZWAsIGBJbmRleEZpbGUucmVzZXRgICjihpIgZnJvbV90cmVlKSBhbmQgYEluZGV4RmlsZS5tZXJnZV90cmVlYCBhcHBlbmQgY2FsbGVyLWluZmx1ZW5jZWQgdHJlZWlzaCBzdHJpbmdzIHBvc2l0aW9uYWxseSB0byBgZ2l0IHJlYWQtdHJlZWAgd2l0aCBubyB1bnNhZmUtb3B0aW9uIGd1YXJkLCBubyBgYWxsb3dfdW5zYWZlX29wdGlvbnNgIHBhcmFtZXRlciwgYW5kIG5vIGAtLWAgc2VwYXJhdG9yLiBgZ2l0IHJlYWQtdHJlZSAtLWluZGV4LW91dHB1dD08ZmlsZT5gIHdyaXRlcyB0aGUgcmVzdWx0aW5nIGluZGV4IHRvIGFuIGFyYml0cmFyeSBwYXRoLCBhbmQgbGFzdC1vY2N1cnJlbmNlLXdpbnMgbGV0cyBhbiBpbmplY3RlZCBgLS1pbmRleC1vdXRwdXRgIG92ZXJyaWRlIHRoZSBtZXRob2QncyBpbnRlcm5hbCB0ZW1wIHBhdGgg4oCUIGNsb2JiZXJpbmcgYW4gYXJiaXRyYXJ5IGZpbGUgd2l0aCBhIHZhbGlkIGdpdC1pbmRleCBibG9iLiBUaGlzIGlzIGEgZGlzdGluY3QsIG5ldmVyLWd1YXJkZWQgc2luazogY29tbWl0IGAzYWYwYzI1MWAgKEdIU0EtM2Y3dy04cnI4LWYzN2YpIGd1YXJkZWQgb25seSBgY2hlY2tvdXRfaW5kZXhgIGFuZCBgdGFnYDsgYHJlYWRfdHJlZWAgd2FzIGxlZnQgdW5wcm90ZWN0ZWQgKGl0IGlzIGFtb25nIHRoZSBhY2tub3dsZWRnZWQgdW5ndWFyZGVkIGNhbGwgc2l0ZXMgaW4gdGhhdCBhZHZpc29yeSdzIHN3ZWVwIGJ1dCB3YXMgbmV2ZXIgcmVwb3J0ZWQgb3IgZml4ZWQpLgoKIyMjIyMgUm9vdCBDYXVzZQpgZnJvbV90cmVlYCAoaW5kZXgvYmFzZS5weTozODgpLCBgcmVzZXRgIChkZWxlZ2F0ZXMgdG8gZnJvbV90cmVlKSwgYW5kIGBtZXJnZV90cmVlYCAoaW5kZXgvYmFzZS5weToyOTEpIGNhbGwgYHJlcG8uZ2l0LnJlYWRfdHJlZSgqYXJnX2xpc3QpYCB3aXRoIG5vIGBjaGVja191bnNhZmVfb3B0aW9uc2AgYW5kIG5vIGAtLWAuIFRoZSB0cmVlaXNoIGlzIGNhbGxlci1pbmZsdWVuY2VkIGFuZCBwb3NpdGlvbmFsLgoKIyMjIyMgSW1wYWN0CkFyYml0cmFyeSBmaWxlIG92ZXJ3cml0ZSAvIGRlc3RydWN0aW9uIGF0IHRoZSBwcml2aWxlZ2VzIG9mIHRoZSBob3N0IHByb2Nlc3MuIENvbnRlbnQgaXMgY29uc3RyYWluZWQgdG8gYSBnaXQtaW5kZXggYmxvYiAobm90IGF0dGFja2VyLWNob3Nlbiwgc28gbm90IFJDRSksIGJ1dCB0aGUgdGFyZ2V0IHBhdGggaXMgZnVsbHkgYXR0YWNrZXItY29udHJvbGxlZCDigJQgY29ycnVwdGluZy90cnVuY2F0aW5nIGNvbmZpZ3Mgb3IgZGVzdHJveWluZyBmaWxlcyBhdCBhdHRhY2tlci1jaG9zZW4gd3JpdGFibGUgbG9jYXRpb25zID0gSTpIICsgQTpIIChwZXIgdGhlIHNraWxsJ3MgIm92ZXJ3cml0ZS1hbnktcGF0aCA9IEk6SCIgcnVsZSkuIFB1cmUgVkFMVUUgY29udHJvbCAocG9zaXRpb25hbCB0cmVlaXNoKS4gRGVmYXVsdCBjb25maWd1cmF0aW9uLgoKIyMjIyMgUHJvb2Ygb2YgQ29uY2VwdApgYGBweXRob24KSW5kZXhGaWxlLmZyb21fdHJlZShyZXBvLCAiLS1pbmRleC1vdXRwdXQ9L2hvbWUvdmljdGltLy5iYXNocmMiKQoKIyMjIyMgdGFyZ2V0IG92ZXJ3cml0dGVuIHdpdGggYSB2YWxpZCBnaXQtaW5kZXggYmxvYiAoRElSQy4uLikKYGBgCgojIyMjIyBBdHRhY2sgQ2hhaW4KMS4gRW50cnk6IGFwcCBjYWxscyBgSW5kZXhGaWxlLmZyb21fdHJlZShyZXBvLCB0cmVlaXNoKWAgLyBgcmVzZXQoY29tbWl0PeKApilgIC8gYG1lcmdlX3RyZWUoYmFzZT3igKYsIHJocz3igKYpYCB3aXRoIGF0dGFja2VyIGB0cmVlaXNoPSItLWluZGV4LW91dHB1dD0vaG9tZS92aWN0aW0vLmJhc2hyYyJgLgoyLiBDaGVjazogTk9ORSDigJQgdGhlIG1ldGhvZHMgaGF2ZSBubyBgYWxsb3dfdW5zYWZlX29wdGlvbnNgIGFuZCBuZXZlciBjYWxsIGBjaGVja191bnNhZmVfb3B0aW9uc2AuCjMuIFNpbms6IGByZXBvLmdpdC5yZWFkX3RyZWUoKmFyZ19saXN0KWAg4oCUIG5vIGAtLWAuIGFyZ3YgKGZyb21fdHJlZSwgb2JzZXJ2ZWQpOiBgWydnaXQnLCdyZWFkLXRyZWUnLCctLWluZGV4LW91dHB1dD08dG1wPicsJy0taW5kZXgtb3V0cHV0PS/igKYvdmljdGltJ11gIChsYXN0LXdpbnMpLgo0LiBJbXBhY3Q6IHRhcmdldCBwYXRoIGNyZWF0ZWQvb3ZlcndyaXR0ZW4gd2l0aCBhIHZhbGlkIGdpdC1pbmRleCBibG9iOyBleGlzdGluZyBjb250ZW50IGRlc3Ryb3llZC4KCiMjIyMjIEJ5cGFzcyBFdmlkZW5jZQpJbmRlcGVuZGVudGx5IHJlcHJvZHVjZWQgKGdhdGUgaGFybmVzcyk6IGBJbmRleEZpbGUuZnJvbV90cmVlKHJlcG8sJy0taW5kZXgtb3V0cHV0PTx2aWN0aW0+JylgIOKGkiB2aWN0aW0gb3ZlcndyaXR0ZW47IGJlZm9yZT1gSU1QT1JUQU5UIE9SSUdJTkFMIENPTlRFTlRgLCBhZnRlciBzdGFydHMgYERJUkNceDAwXHgwMFx4MDBceDAy4oCmYCAoZGVzdHJ1Y3RpdmUgY2xvYmJlciwgdmFsaWQgaW5kZXggYmxvYikuIGByZXNldChjb21taXQ94oCmKWAgYW5kIGJvdGggYG1lcmdlX3RyZWVgIHBvc2l0aW9uYWxzIHZlcmlmaWVkLiBGaXgtY29tbWl0IHJlYWQ6IGAzYWYwYzI1MWAgdG91Y2hlZCBvbmx5IGBjaGVja291dF9pbmRleGArYHRhZ2A7IGByZWFkX3RyZWVgIHVudG91Y2hlZCBvbiBIRUFELgoKIyMjIyMgQWZmZWN0ZWQgVmVyc2lvbnMKYEdpdFB5dGhvbiA8PSAzLjEuNTdgIChzaW5rcyBwcmVzZW50IHZlcmJhdGltIG9uIHRoZSBsYXRlc3QgcmVsZWFzZSB0YWcpLgoKIyMjIyMgU3VnZ2VzdGVkIEZpeApBZGQgYSBgY2hlY2tfdW5zYWZlX29wdGlvbnNgIGd1YXJkICh3aXRoIGFuIGBhbGxvd191bnNhZmVfb3B0aW9uc2AgcGFyYW1ldGVyKSB0byBgZnJvbV90cmVlYC9gcmVzZXRgL2BtZXJnZV90cmVlYCwgYW5kL29yIHBsYWNlIGEgYC0tYCBzZXBhcmF0b3IgYmVmb3JlIHRoZSBwb3NpdGlvbmFsIHRyZWVpc2ggYXJndW1lbnRzOyBibG9jayBgLS1pbmRleC1vdXRwdXRgIChhIHBhdGgtdGFraW5nIG9wdGlvbikgb24gdGhpcyBzaW5rLgoKLS0tClJlcG9ydGVkIGJ5ICoqenggKEphY2UpKiog4oCUIEdpdEh1YjogQCYjODIwMzttYW51cy11c2UKCiMjIyMgU2V2ZXJpdHkKLSBDVlNTIFNjb3JlOiA4LjEgLyAxMCAoSGlnaCkKLSBWZWN0b3IgU3RyaW5nOiBgQ1ZTUzozLjEvQVY6Ti9BQzpML1BSOkwvVUk6Ti9TOlUvQzpOL0k6SC9BOkhgCgojIyMjIFJlZmVyZW5jZXMKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9zZWN1cml0eS9hZHZpc29yaWVzL0dIU0EtNGdtdy1nZzJtLXc0NnBdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vc2VjdXJpdHkvYWR2aXNvcmllcy9HSFNBLTRnbXctZ2cybS13NDZwKQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3B1bGwvMjIwNF0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9wdWxsLzIyMDQpCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vY29tbWl0LzliNWRjYWY4NWRhNTk0NmRiZjY5ZGNkNTNmOWVkYmEwOGY3NjBiMzJdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vY29tbWl0LzliNWRjYWY4NWRhNTk0NmRiZjY5ZGNkNTNmOWVkYmEwOGY3NjBiMzIpCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob25dKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24pCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcmVsZWFzZXMvdGFnLzMuMS41OF0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9yZWxlYXNlcy90YWcvMy4xLjU4KQoKVGhpcyBkYXRhIGlzIHByb3ZpZGVkIGJ5IFtPU1ZdKGh0dHBzOi8vb3N2LmRldi92dWxuZXJhYmlsaXR5L0dIU0EtNGdtdy1nZzJtLXc0NnApIGFuZCB0aGUgW0dpdEh1YiBBZHZpc29yeSBEYXRhYmFzZV0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdGh1Yi9hZHZpc29yeS1kYXRhYmFzZSkgKFtDQy1CWSA0LjBdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRodWIvYWR2aXNvcnktZGF0YWJhc2UvYmxvYi9tYWluL0xJQ0VOU0UubWQpKS4KPC9kZXRhaWxzPgoKLS0tCgojIyMgR2l0UHl0aG9uOiBVbmd1YXJkZWQgZ2l0IG9wdGlvbiBmb3J3YXJkaW5nIGluIFJlcG8uaW5pdCBlbmFibGVzIGFyYml0cmFyeSBjb21tYW5kIGV4ZWN1dGlvbiB2aWEgLS10ZW1wbGF0ZSBjbG9uZSBob29rcwpbR0hTQS05cmo3LXJmMnAtdzc3cl0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2Fkdmlzb3JpZXMvR0hTQS05cmo3LXJmMnAtdzc3cikKCjxkZXRhaWxzPgo8c3VtbWFyeT5Nb3JlIGluZm9ybWF0aW9uPC9zdW1tYXJ5PgoKIyMjIyBEZXRhaWxzCiMjIyMjIFN1bW1hcnkKYFJlcG8uaW5pdCgpYCBmb3J3YXJkcyBgKiprd2FyZ3NgIHZlcmJhdGltIHRvIGBnaXQgaW5pdGAgd2l0aCBubyB1bnNhZmUtb3B0aW9uIGd1YXJkIGFuZCBubyBgYWxsb3dfdW5zYWZlX29wdGlvbnNgIHBhcmFtZXRlci4gYGdpdCBpbml0IC0tdGVtcGxhdGU9PGRpcj5gIGNvcGllcyBgPGRpcj4vaG9va3MvKmAgaW50byB0aGUgbmV3IHJlcG8ncyBgLmdpdC9ob29rc2AsIHNvIGFuIGF0dGFja2VyLWNvbnRyb2xsZWQgYHRlbXBsYXRlYCBrd2FyZyBwbGFudHMgYSBob29rIHRoYXQgZXhlY3V0ZXMgb24gdGhlIG5leHQgZ2l0IG9wZXJhdGlvbiDihpIgYXJiaXRyYXJ5IGNvZGUgZXhlY3V0aW9uLiBgLS10ZW1wbGF0ZWAgaXMgYWxyZWFkeSByZWNvZ25pemVkIGFzIHVuc2FmZSBmb3IgY2xvbmUgKGl0IGlzIG9uIGB1bnNhZmVfZ2l0X2Nsb25lX29wdGlvbnNgLCBhbmQgR0hTQS02cDhoLTN3Z3gtOTdnZiBjb3ZlcnMgdGhlIGNsb25lIHBhdGgpLCBidXQgYFJlcG8uaW5pdGAgaXMgYSBkaXN0aW5jdCBtZXRob2QgdGhhdCBuZXZlciByZWNlaXZlZCBhIGd1YXJkIGFuZCBuZWVkcyBhbiBpbmRlcGVuZGVudCBmaXguCgojIyMjIyBSb290IENhdXNlCmBSZXBvLmluaXQocGF0aCwgbWtkaXIsIG9kYnQsIGV4cGFuZF92YXJzLCAqKmt3YXJncylgIGlzIGEgYmFyZSBgZ2l0LmluaXQoKiprd2FyZ3MpYCAoZ2l0L3JlcG8vYmFzZS5weToxNDM1KSB3aXRoIG5vIGBjaGVja191bnNhZmVfb3B0aW9uc2AgYW5kIG5vIGBhbGxvd191bnNhZmVfb3B0aW9uc2AuCgojIyMjIyBJbXBhY3QKQXJiaXRyYXJ5IGNvZGUgZXhlY3V0aW9uIChob29rIGZpcmVzIG9uIG5leHQgZ2l0IG9wKSBhdCB0aGUgcHJpdmlsZWdlcyBvZiB0aGUgaG9zdCBwcm9jZXNzLiBUd28gcHJlY29uZGl0aW9ucyByYWlzZSBhdHRhY2sgY29tcGxleGl0eSAoQUM6SCk6IHRoZSBhcHAgbXVzdCBmb3J3YXJkIGEgYHRlbXBsYXRlPWAga3dhcmcgKEtFWSBjb250cm9sKSBBTkQgdGhlIGF0dGFja2VyIG11c3Qgc3RhZ2UgYW4gZXhlY3V0YWJsZSBob29rIGRpcmVjdG9yeSBhdCBhIGtub3duIHBhdGgg4oCUIHRoZSBzYW1lIHByb2ZpbGUgR0hTQS02cDhoLTN3Z3gtOTdnZiBhY2NlcHRlZCBhcyBISUdIIGZvciB0aGUgY2xvbmUgcGF0aC4gRGVmYXVsdCBgYWxsb3dfdW5zYWZlX29wdGlvbnNgIGlzIGlycmVsZXZhbnQgaGVyZSBiZWNhdXNlIGBSZXBvLmluaXRgIGhhcyBubyBndWFyZCBhdCBhbGwuCgojIyMjIyBQcm9vZiBvZiBDb25jZXB0CmBgYHB5dGhvbgoKIyMjIyMgYXR0YWNrZXIgc3RhZ2VzIC9ldmlsL2hvb2tzL3Bvc3QtY29tbWl0IChleGVjdXRhYmxlKQpmcm9tIGdpdCBpbXBvcnQgUmVwbwpSZXBvLmluaXQocGF0aCwgdGVtcGxhdGU9Ii9ldmlsIikKCiMjIyMjIG5leHQgY29tbWl0IHJ1bnMgL2V2aWwvaG9va3MvcG9zdC1jb21taXQgLT4gQUNFCmBgYAoKIyMjIyMgQXR0YWNrIENoYWluCjEuIEVudHJ5OiBhdHRhY2tlciBzdGFnZXMgYC9ldmlsL2hvb2tzL3Bvc3QtY29tbWl0YCAoZXhlY3V0YWJsZSkgYW5kIGdldHMgdGhlIGFwcCB0byBjYWxsIGBSZXBvLmluaXQocGF0aCwgdGVtcGxhdGU9Jy9ldmlsJylgLgoyLiBDaGVjazogTk9ORSBvbiBgUmVwby5pbml0YC4gQnlwYXNzIHByb29mOiBiYXNlLnB5OjE0MzUgaXMgYSBiYXJlIGBnaXQuaW5pdCgqKmt3YXJncylgLiBhcmd2IChvYnNlcnZlZCk6IGBbJ2dpdCcsJ2luaXQnLCctLXRlbXBsYXRlPS9ldmlsJ11gLgozLiBTaW5rOiBnaXQgY29waWVzIGAvZXZpbC9ob29rcy9wb3N0LWNvbW1pdGAg4oaSIGA8cmVwbz4vLmdpdC9ob29rcy9wb3N0LWNvbW1pdGAuCjQuIEltcGFjdDogbmV4dCBjb21taXQgcnVucyB0aGUgaG9vayDihpIgYXJiaXRyYXJ5IGNvZGUgZXhlY3V0aW9uLgoKIyMjIyMgQnlwYXNzIEV2aWRlbmNlCkluZGVwZW5kZW50bHkgcmVwcm9kdWNlZCAoZ2F0ZSBoYXJuZXNzKTogYFJlcG8uaW5pdChkc3QsIHRlbXBsYXRlPSc8ZXZpbD4nKWAg4oaSIGFyZ3YgYFsnZ2l0JywnaW5pdCcsJy0tdGVtcGxhdGU9PGV2aWw+J11gIHVuZ3VhcmRlZDsgaG9vayBjb3BpZWQgaW50byBgLmdpdC9ob29rcy9wb3N0LWNvbW1pdGA7IGFmdGVyIGBnaXQgY29tbWl0YCB0aGUgYElOSVRfQUNFYCBtYXJrZXIgd2FzIGNyZWF0ZWQuIGAtLXNlcGFyYXRlLWdpdC1kaXI9PHBhdGg+YCBpcyBhIHBhcmFsbGVsIGFyYml0cmFyeS1yZWRpcmVjdCB2ZWN0b3IgdGhyb3VnaCB0aGUgc2FtZSB1bmd1YXJkZWQgc2luayAodmFsdWUgY29udHJvbCBvbmx5KS4KCiMjIyMjIEFmZmVjdGVkIFZlcnNpb25zCmBHaXRQeXRob24gPD0gMy4xLjU3YCAodW5ndWFyZGVkIGBnaXQuaW5pdCgqKmt3YXJncylgIHByZXNlbnQgdmVyYmF0aW0gb24gdGhlIGxhdGVzdCByZWxlYXNlIHRhZykuCgojIyMjIyBTdWdnZXN0ZWQgRml4CkFkZCBhIGBjaGVja191bnNhZmVfb3B0aW9uc2AgZ3VhcmQgKHdpdGggYW4gYGFsbG93X3Vuc2FmZV9vcHRpb25zYCBwYXJhbWV0ZXIpIHRvIGBSZXBvLmluaXRgLCBjb25zdWx0aW5nIGEgZGVueWxpc3QgdGhhdCBpbmNsdWRlcyBgLS10ZW1wbGF0ZWAgYW5kIGAtLXNlcGFyYXRlLWdpdC1kaXJgIChwYXRoLXRha2luZyAvIGhvb2staW5zdGFsbGluZyBvcHRpb25zKS4KCi0tLQpSZXBvcnRlZCBieSAqKnp4IChKYWNlKSoqIOKAlCBHaXRIdWI6IEAmIzgyMDM7bWFudXMtdXNlCgojIyMjIFNldmVyaXR5Ci0gQ1ZTUyBTY29yZTogNy41IC8gMTAgKEhpZ2gpCi0gVmVjdG9yIFN0cmluZzogYENWU1M6My4xL0FWOk4vQUM6SC9QUjpML1VJOk4vUzpVL0M6SC9JOkgvQTpIYAoKIyMjIyBSZWZlcmVuY2VzCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vc2VjdXJpdHkvYWR2aXNvcmllcy9HSFNBLTlyajctcmYycC13NzdyXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3NlY3VyaXR5L2Fkdmlzb3JpZXMvR0hTQS05cmo3LXJmMnAtdzc3cikKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9wdWxsLzIyMDRdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcHVsbC8yMjA0KQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL2NvbW1pdC9kOWRkYjU1YmRjNjZdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vY29tbWl0L2Q5ZGRiNTViZGM2NikKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbl0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbikKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9yZWxlYXNlcy90YWcvMy4xLjU4XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3JlbGVhc2VzL3RhZy8zLjEuNTgpCgpUaGlzIGRhdGEgaXMgcHJvdmlkZWQgYnkgW09TVl0oaHR0cHM6Ly9vc3YuZGV2L3Z1bG5lcmFiaWxpdHkvR0hTQS05cmo3LXJmMnAtdzc3cikgYW5kIHRoZSBbR2l0SHViIEFkdmlzb3J5IERhdGFiYXNlXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0aHViL2Fkdmlzb3J5LWRhdGFiYXNlKSAoW0NDLUJZIDQuMF0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdGh1Yi9hZHZpc29yeS1kYXRhYmFzZS9ibG9iL21haW4vTElDRU5TRS5tZCkpLgo8L2RldGFpbHM+CgotLS0KCiMjIyBHaXRQeXRob246IEFyYml0cmFyeSBmaWxlIHJlYWQgdmlhIC0tcGF0aHNwZWMtZnJvbS1maWxlIGluIEluZGV4RmlsZS5yZW1vdmUoKSBhbmQgSGVhZC5jaGVja291dCgpCltHSFNBLWhoOXAtNndoMi00bWZjXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vYWR2aXNvcmllcy9HSFNBLWhoOXAtNndoMi00bWZjKQoKPGRldGFpbHM+CjxzdW1tYXJ5Pk1vcmUgaW5mb3JtYXRpb248L3N1bW1hcnk+CgojIyMjIERldGFpbHMKIyMjIyMgU3VtbWFyeQoKYEluZGV4RmlsZS5yZW1vdmUoKWAgYW5kIGBIZWFkLmNoZWNrb3V0KClgIGZvcndhcmQgYCoqa3dhcmdzYCBpbnRvIGBnaXQgcm1gIGFuZCBgZ2l0IGNoZWNrb3V0YAp3aXRoIG5vIGd1YXJkLiBQYXNzaW5nIGAtLXBhdGhzcGVjLWZyb20tZmlsZT08ZmlsZT5gICoqdG9nZXRoZXIgd2l0aCBgLS1wYXRoc3BlYy1maWxlLW51bGAqKgptYWtlcyBHaXQgdHJlYXQgdGhlIHdob2xlIGZpbGUgYXMgYSBzaW5nbGUgTlVMLWRlbGltaXRlZCBwYXRoc3BlYywgYW5kIHRoZSB1bm1hdGNoZWQtcGF0aHNwZWMKZXJyb3IgcXVvdGVzIGl0IHZlcmJhdGltLiBHaXRQeXRob24gc3VyZmFjZXMgdGhhdCB0aHJvdWdoIGBHaXRDb21tYW5kRXJyb3Iuc3RkZXJyYCwgc28gdGhlCmVudGlyZSBjb250ZW50cyBvZiBhIGNhbGxlci1jaG9zZW4gZmlsZSBhcmUgcmV0dXJuZWQgdG8gdGhlIGNhbGxlciBpbiBiYW5kLgoKVGhpcyBpcyB0aGUgc2FtZSBwcmltaXRpdmUgYXMgSW5zdGFuY2UgMiBvZgpbR0hTQS0zZjd3LThycjgtZjM3Zl0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2Fkdmlzb3JpZXMvR0hTQS0zZjd3LThycjgtZjM3ZikgLSBgVGFnUmVmZXJlbmNlLmNyZWF0ZSgpYAp3aXRoIGAtRmAsIGFyYml0cmFyeSBmaWxlIHJlYWQgcmV0dXJuZWQgaW4gYmFuZCAtIGF0IHR3byBzaXRlcyB0aGF0IGFkdmlzb3J5IGFzc2Vzc2VkIGFuZApjbGVhcmVkLgoKIyMjIyMgUHJpb3IgYXJ0LCBhbmQgd2h5IEkgYW0gZmlsaW5nIHJhdGhlciB0aGFuIGNvbW1lbnRpbmcKCkdIU0EtM2Y3dy04cnI4LWYzN2YncyBzd2VlcCB0YWJsZSBsaXN0cyB0aGVzZSBmb3VyIHNpdGVzIHdpdGggdGhlIGFzc2Vzc21lbnQKKiJgLS1wYXRoc3BlYy1mcm9tLWZpbGVgIG9ubHkgcmVhZHMgYSBwYXRoc3BlYzsgbm8gd3JpdGUgb3IgZGlzY2xvc3VyZSBwcmltaXRpdmUgZm91bmQiKjoKCnwgQ2FsbCBzaXRlIHwgZ2l0IGNvbW1hbmQgfCB0aGF0IGFkdmlzb3J5J3MgYXNzZXNzbWVudCB8CnwtLS18LS0tfC0tLXwKfCBgSW5kZXhGaWxlLnJlbW92ZSgpYCB8IGBybWAgfCBgLS1wYXRoc3BlYy1mcm9tLWZpbGVgIG9ubHkgcmVhZHMgYSBwYXRoc3BlYzsgbm8gd3JpdGUgb3IgZGlzY2xvc3VyZSBwcmltaXRpdmUgZm91bmQgfAp8IGBJbmRleEZpbGUubW92ZSgpYCB8IGBtdmAgfCBzYW1lIHwKfCBgSEVBRC5yZXNldCgpYCB8IGByZXNldGAgfCBzYW1lIHwKfCBgSEVBRC5jaGVja291dCgpYCB8IGBjaGVja291dGAgfCBzYW1lIHwKClRoYXQgYXNzZXNzbWVudCBpcyB2ZXJ5IG5lYXJseSByaWdodCwgYW5kIEkgdGhpbmsgdGhhdCBpcyB3aHkgaXQgaGVsZDogd2l0aApgLS1wYXRoc3BlYy1mcm9tLWZpbGVgIGFsb25lLCBHaXQgc3BsaXRzIG9uIG5ld2xpbmVzIGFuZCB0aGUgZXJyb3IgcXVvdGVzIG9ubHkgdGhlICoqZmlyc3QKbGluZSoqLCB3aGljaCByZWFkcyBhcyBhbiB1bmludGVyZXN0aW5nIHBhcnRpYWwuIEFkZGluZyBgLS1wYXRoc3BlYy1maWxlLW51bGAgLSBhIHNpYmxpbmcgZmxhZwpvZiB0aGUgc2FtZSBvcHRpb24sIGFuZCB0aGUgZG9jdW1lbnRlZCB3YXkgdG8gaGFuZGxlIHBhdGhzIGNvbnRhaW5pbmcgbmV3bGluZXMgLSBtYWtlcyB0aGUKd2hvbGUgZmlsZSBvbmUgcGF0aHNwZWMuCgojIyMjIyBSb290IGNhdXNlCgpgZ2l0L2luZGV4L2Jhc2UucHk6OTkxLTEwNDNgOgoKYGBgcHl0aG9uCmRlZiByZW1vdmUoc2VsZiwgaXRlbXMsIHdvcmtpbmdfdHJlZT1GYWxzZSwgKiprd2FyZ3MpOgogICAgLi4uCiAgICByZW1vdmVkX3BhdGhzID0gc2VsZi5yZXBvLmdpdC5ybShhcmdzLCBwYXRocywgKiprd2FyZ3MpLnNwbGl0bGluZXMoKSAgICMgbGluZSAxMDQzCmBgYAoKYGdpdC9yZWZzL2hlYWQucHk6MjM3LTI2OGA6CgpgYGBweXRob24KZGVmIGNoZWNrb3V0KHNlbGYsIGZvcmNlOiBib29sID0gRmFsc2UsICoqa3dhcmdzOiBBbnkpOgogICAgLi4uCiAgICBzZWxmLnJlcG8uZ2l0LmNoZWNrb3V0KHNlbGYsICoqa3dhcmdzKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgbGluZSAyNjgKYGBgCgpOZWl0aGVyIGhhcyBhbiBgYWxsb3dfdW5zYWZlX29wdGlvbnNgIHBhcmFtZXRlciBvciBhIGBjaGVja191bnNhZmVfb3B0aW9ucygpYCBjYWxsLgoKIyMjIyMgUHJvb2Ygb2YgY29uY2VwdAoKYGBgcHl0aG9uCmZyb20gZ2l0IGltcG9ydCBSZXBvCmZyb20gZ2l0LmV4YyBpbXBvcnQgR2l0Q29tbWFuZEVycm9yCgpyZXBvID0gUmVwbygiL3BhdGgvdG8vcmVwbyIpCmt3ID0gZGljdChwYXRoc3BlY19mcm9tX2ZpbGU9Ii9ldGMvcGFzc3dkIiwgcGF0aHNwZWNfZmlsZV9udWw9VHJ1ZSkKCnRyeToKICAgIHJlcG8uaW5kZXgucmVtb3ZlKFtdLCAqKmt3KSAgICAgICAgICAjIG9yOiByZXBvLmhlYWRzWzBdLmNoZWNrb3V0KCoqa3cpCmV4Y2VwdCBHaXRDb21tYW5kRXJyb3IgYXMgZToKICAgIHByaW50KGUuc3RkZXJyKSAgICAgICAgICAgICAgICAgICAgICAjIDwtIGVudGlyZSBmaWxlIGNvbnRlbnRzCmBgYAoKT2JzZXJ2ZWQgb24gcHVibGlzaGVkIDMuMS41NywgYWdhaW5zdCBhIGNhbmFyeSBmaWxlIGhvbGRpbmcgdGhyZWUgbWFya2VkIGxpbmVzOgoKYGBgCltQQVNTXSBJbmRleEZpbGUucmVtb3ZlKCkgLT4gYGdpdCBybWAgcmV0dXJucyBBTEwgMyBjYW5hcnkgbGluZXMgaW4tYmFuZAogICAgICAgc3RkZXJyOiAnZmF0YWw6IHBhdGhzcGVjICdMSU5FMS1DQU5BUlktNDI0MgogICAgICAgTElORTItU0VDUkVULTc3NzcKICAgICAgIExJTkUzLVRBSUwtOTk5OQogICAgICAgJyBkaWQgbm90IG1hdGNoIGFueSBmaWxlcycKW1BBU1NdIEhlYWQuY2hlY2tvdXQoKSAtPiBgZ2l0IGNoZWNrb3V0YCByZXR1cm5zIEFMTCAzIGNhbmFyeSBsaW5lcyBpbi1iYW5kCiAgICAgICBzdGRlcnI6ICdlcnJvcjogcGF0aHNwZWMgJ0xJTkUxLUNBTkFSWS00MjQyCiAgICAgICBMSU5FMi1TRUNSRVQtNzc3NwogICAgICAgTElORTMtVEFJTC05OTk5CiAgICAgICAnIGRpZCBub3QgbWF0Y2ggYW55IGZpbGUocykga25vd24gdG8gZ2l0JwpbUEFTU10gUFJFQ0lTSU9OOiBgZ2l0IHN0YXR1c2AgbGVha3MgMC8zIC0tIG5vdCBldmVyeSB1bmd1YXJkZWQgc2l0ZSBkaXNjbG9zZXMKW1BBU1NdIFBSRUNJU0lPTjogdGhlIEdVQVJERUQgY2hlY2tvdXQtaW5kZXggbGVha3MgMC8zCmBgYAoKVGhlIHR3byBwcmVjaXNpb24gY29udHJvbHMgYXJlIHRoZXJlIHNvIHRoZSByZXN1bHQgaXMgYWJvdXQgdGhlc2Ugc2lua3MgYW5kIG5vdCBhYm91dCB0aGUKY2FuYXJ5IGJlaW5nIHZpc2libGUgZXZlcnl3aGVyZS4KCiMjIyMjIFNjb3BlIGNvcnJlY3Rpb24gdG8gdGhlIHRhYmxlIGFib3ZlCgpPZiB0aGUgZm91ciBzaXRlcyBjbGVhcmVkIHdpdGggdGhhdCBzZW50ZW5jZSwgKip0d28gZGlzY2xvc2UgYW5kIHR3byBkbyBub3QqKjoKCnwgQ2FsbCBzaXRlIHwgZGlzY2xvc2VkPyB8CnwtLS18LS0tfAp8IGBJbmRleEZpbGUucmVtb3ZlKClgIOKGkiBgZ2l0IHJtYCB8ICoqeWVzLCBmdWxsIGZpbGUqKiB8CnwgYEhlYWQuY2hlY2tvdXQoKWAg4oaSIGBnaXQgY2hlY2tvdXRgIHwgKip5ZXMsIGZ1bGwgZmlsZSoqIHwKfCBgSEVBRC5yZXNldCgpYCDihpIgYGdpdCByZXNldGAgfCBubyAtIGBnaXQgcmVzZXRgIGRvZXMgbm90IGVycm9yIG9uIHVubWF0Y2hlZCBwYXRoc3BlY3MgfAp8IGBJbmRleEZpbGUubW92ZSgpYCDihpIgYGdpdCBtdmAgfCBubyB8CgpUaGUgdHdvIG5lZ2F0aXZlcyBhcmUgbWVudGlvbmVkIGJlY2F1c2UgInRoZSBkaXNtaXNzYWwgd2FzIHdyb25nIiB3b3VsZCBvdmVyc3RhdGUgaXQ6IHRoZQpkaXNtaXNzYWwgd2FzIHdyb25nIGZvciBoYWxmIG9mIHdoYXQgaXQgY292ZXJlZC4KCiMjIyMgU2V2ZXJpdHkKLSBDVlNTIFNjb3JlOiA2LjUgLyAxMCAoTWVkaXVtKQotIFZlY3RvciBTdHJpbmc6IGBDVlNTOjMuMS9BVjpOL0FDOkwvUFI6TC9VSTpOL1M6VS9DOkgvSTpOL0E6TmAKCiMjIyMgUmVmZXJlbmNlcwotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3NlY3VyaXR5L2Fkdmlzb3JpZXMvR0hTQS1oaDlwLTZ3aDItNG1mY10oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9zZWN1cml0eS9hZHZpc29yaWVzL0dIU0EtaGg5cC02d2gyLTRtZmMpCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcHVsbC8yMjA0XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3B1bGwvMjIwNCkKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9jb21taXQvZjI1NTBiNjViZjYwY2EwODcxOTA5ODFlMmM3YjY4NjVlMjAxZjQwY10oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9jb21taXQvZjI1NTBiNjViZjYwY2EwODcxOTA5ODFlMmM3YjY4NjVlMjAxZjQwYykKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbl0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbikKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9yZWxlYXNlcy90YWcvMy4xLjU4XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3JlbGVhc2VzL3RhZy8zLjEuNTgpCgpUaGlzIGRhdGEgaXMgcHJvdmlkZWQgYnkgW09TVl0oaHR0cHM6Ly9vc3YuZGV2L3Z1bG5lcmFiaWxpdHkvR0hTQS1oaDlwLTZ3aDItNG1mYykgYW5kIHRoZSBbR2l0SHViIEFkdmlzb3J5IERhdGFiYXNlXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0aHViL2Fkdmlzb3J5LWRhdGFiYXNlKSAoW0NDLUJZIDQuMF0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdGh1Yi9hZHZpc29yeS1kYXRhYmFzZS9ibG9iL21haW4vTElDRU5TRS5tZCkpLgo8L2RldGFpbHM+CgotLS0KCiMjIyBHaXRQeXRob246IEFyYml0cmFyeSBHaXQgUmVwb3NpdG9yeSBDcmVhdGlvbiBPdXRzaWRlIHRoZSBXb3JraW5nIFRyZWUgdmlhIFVudmFsaWRhdGVkIC5naXRtb2R1bGVzIFN1Ym1vZHVsZSBOYW1lIGluIEdpdFB5dGhvbgpbR0hTQS1obXEyLXc1OGYtMjdqY10oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2Fkdmlzb3JpZXMvR0hTQS1obXEyLXc1OGYtMjdqYykKCjxkZXRhaWxzPgo8c3VtbWFyeT5Nb3JlIGluZm9ybWF0aW9uPC9zdW1tYXJ5PgoKIyMjIyBEZXRhaWxzCiMjIyMjIFN1bW1hcnkKR2l0UHl0aG9uIGNvbXB1dGVzIHRoZSBvbi1kaXNrIGxvY2F0aW9uIG9mIGEgc3VibW9kdWxlJ3Mgc2VwYXJhdGUgR2l0IGRpcmVjdG9yeSAoYC5naXQvbW9kdWxlcy88bmFtZT5gKSBmcm9tIHRoZSBzdWJtb2R1bGUncyBgLmdpdG1vZHVsZXNgIHNlY3Rpb24gbmFtZSB3aXRoIG5vIHZhbGlkYXRpb24uIEJlY2F1c2UgdGhhdCBuYW1lIGlzIGZ1bGx5IGF0dGFja2VyLWNvbnRyb2xsZWQgY29udGVudCBvZiBhIGNsb25lZCByZXBvc2l0b3J5LCBhIG1hbGljaW91cyByZXBvc2l0b3J5IGNhbiBzZXQgYSBzdWJtb2R1bGUgbmFtZSB0byBhIHRyYXZlcnNhbCBzdHJpbmcgKGUuZy4gYC4uLy4uLy4uLy4uL2hvbWUvdmljdGltLy5zb21ldGhpbmdgKSBhbmQgY2F1c2UgR2l0UHl0aG9uIHRvIGNyZWF0ZSBhbmQgaW5pdGlhbGl6ZSBhIGZ1bGwgR2l0IHJlcG9zaXRvcnkgYXQgYW4gYXR0YWNrZXItY2hvc2VuIGZpbGVzeXN0ZW0gcGF0aCBvdXRzaWRlIHRoZSBpbnRlbmRlZCBjbG9uZSBkaXJlY3RvcnkuIFRoZSBvbmx5IHByZWNvbmRpdGlvbiBpcyB0aGF0IGEgdmljdGltIGNsb25lcyB0aGUgbWFsaWNpb3VzIHJlcG9zaXRvcnkgd2l0aCBHaXRQeXRob24gYW5kIHJ1bnMgc3VibW9kdWxlIGluaXRpYWxpemF0aW9uIChgc3VibW9kdWxlX3VwZGF0ZShpbml0PVRydWUpYCAvIGBzbS51cGRhdGUoaW5pdD1UcnVlKWApLCBhIHZlcnkgY29tbW9uIGFuZCBvZnRlbiBhdXRvbWF0aWMgc3RlcC4gQ29yZSBHaXQgaXRzZWxmIGFscmVhZHkgYmxvY2tzIHRoaXMgZXhhY3QgYXR0YWNrIGNsYXNzIChDVkUtMjAxOC0xMTIzNSksIGJ1dCBHaXRQeXRob24ncyBpbmRlcGVuZGVudCByZWltcGxlbWVudGF0aW9uIG5ldmVyIGFkb3B0ZWQgYW4gZXF1aXZhbGVudCBjaGVjay4KCiMjIyMjIERldGFpbHMKYHNyYy9HaXRQeXRob24vZ2l0L29iamVjdHMvc3VibW9kdWxlL3V0aWwucHlgIGBzbV9uYW1lKClgIHN0cmlwcyB0aGUgYHN1Ym1vZHVsZSAiYCAvIGAiYCB3cmFwcGVyIGZyb20gYSBgLmdpdG1vZHVsZXNgIGBbc3VibW9kdWxlICIuLi4iXWAgaGVhZGVyIGFuZCByZXR1cm5zIHRoZSByZXN1bHQgdW5jaGVja2VkLiBgU3VibW9kdWxlLml0ZXJfaXRlbXMoKWAgaW4gYHNyYy9HaXRQeXRob24vZ2l0L29iamVjdHMvc3VibW9kdWxlL2Jhc2UucHlgIHJlYWRzIHRoaXMgdmlhIGBzbV9uYW1lKHNtcylgIGFuZCBhc3NpZ25zIGl0IHRvIGBzbS5fbmFtZWA7IHVubGlrZSB0aGUgc3VibW9kdWxlIGBwYXRoYCwgYG5hbWVgIGlzIG5ldmVyIHVzZWQgZm9yIGEgdHJlZSBsb29rdXAsIHNvIGl0IGlzIG5ldmVyIGltcGxpY2l0bHkgdmFsaWRhdGVkLiBgU3VibW9kdWxlLl9tb2R1bGVfYWJzcGF0aCgpYCB0aGVuIGJ1aWxkcyBgb3NwLmpvaW4ocGFyZW50X3JlcG8uZ2l0X2RpciwgIm1vZHVsZXMiLCBuYW1lKWAgLSBgb3MucGF0aC5qb2luYCBkb2VzIG5vdCBub3JtYWxpemUgYC4uL2Agc2VxdWVuY2VzLiBgU3VibW9kdWxlLl9jbG9uZV9yZXBvKClgIHBhc3NlcyB0aGlzIHZhbHVlIHN0cmFpZ2h0IHRvIGBvcy5tYWtlZGlycygpYCBhbmQgdG8gYGdpdCBjbG9uZSAtLXNlcGFyYXRlLWdpdC1kaXI9PG1vZHVsZV9hYnNwYXRoPmAsIGNyZWF0aW5nIGFuZCBwb3B1bGF0aW5nIGEgZnVsbCBHaXQgcmVwb3NpdG9yeSAob2JqZWN0cywgcmVmcywgaG9va3MsIGNvbmZpZykgYXQgdGhlIGVzY2FwZWQgcGF0aC4gQXR0YWNrIHByZXJlcXVpc2l0ZTogYXR0YWNrZXIgY29udHJvbHMgYSByZXBvc2l0b3J5IHRoZSB2aWN0aW0gY2xvbmVzIGFuZCBpbml0aWFsaXplcyBzdWJtb2R1bGVzIGZvci4KCiMjIyMjIFBvQwoxLiBFbnZpcm9ubWVudDogRG9ja2VyIGltYWdlIGJ1aWx0IGBGUk9NIHB5dGhvbjozLjExLXNsaW1gLCB3aXRoIGBnaXRgIGluc3RhbGxlZCB2aWEgYGFwdC1nZXQgaW5zdGFsbCAteSBnaXRgIChEZWJpYW4gYm9va3dvcm0gcGFja2FnZWQgdmVyc2lvbiwgZGVzY3JpYmVkIGluIHRoZSBhZHZpc29yeSBhcyAiZ2l0IDIueCI7IHRoZSBob3N0LXNpZGUgdmVyaWZpY2F0aW9uIHNlcGFyYXRlbHkgdXNlZCBzeXN0ZW0gZ2l0IGAyLjM0LjFgLCBidXQgbm8gZXhhY3QgdmVyc2lvbiBpcyBwaW5uZWQgZm9yIHRoZSBnaXQgYmluYXJ5IGluc2lkZSB0aGlzIERvY2tlciBpbWFnZSkuIEdpdFB5dGhvbiBpcyBpbnN0YWxsZWQgaW5zaWRlIHRoZSBjb250YWluZXIgdmlhIGBwaXAgaW5zdGFsbCAvc3JjL0dpdFB5dGhvbmAgZnJvbSB0aGlzIHJlcG9zaXRvcnkncyBvd24gc291cmNlLCB3aGljaCB0aGUgYWR2aXNvcnkgc3RhdGVzIHJlc29sdmVkIHRvIHRoZSBvZmZpY2lhbGx5IHJlbGVhc2VkIGBHaXRQeXRob249PTMuMS41N2AgYW5kIGBnaXRkYj09NC4wLjEyYC4KMi4gQ29uZmlndXJhdGlvbiAvIHByZWNvbmRpdGlvbnM6IE5vbmUgYmV5b25kIHdoYXQncyBkZXNjcmliZWQgLSB0aGUgdmljdGltIG11c3QgY2xvbmUgdGhlIGF0dGFja2VyJ3MgcmVwb3NpdG9yeSB3aXRoIEdpdFB5dGhvbiBhbmQgcnVuIHN1Ym1vZHVsZSBpbml0aWFsaXphdGlvbiAoYHJlcG8uc3VibW9kdWxlc2AgKyBgc20udXBkYXRlKGluaXQ9VHJ1ZSlgLCBlcXVpdmFsZW50IHRvIGBnaXQgc3VibW9kdWxlIHVwZGF0ZSAtLWluaXRgKS4KMy4gQ29tbWFuZHMgcnVuIChxdW90ZWQgdmVyYmF0aW0gZnJvbSB0aGUgYWR2aXNvcnkncyAiQ29uZmlybWVkIHRlc3QgcnVuIiBzZWN0aW9uKToKYGBgYmFzaAokIGRvY2tlciBidWlsZCAtZiBHSFNBL3Rlc3RpbmcvRG9ja2VyZmlsZSAtdCBnaHNhLWdpdHB5dGhvbi1wb2MgLgokIGRvY2tlciBydW4gLS1ybSBnaHNhLWdpdHB5dGhvbi1wb2MKYGBgCihQZXIgdGhlIERvY2tlcmZpbGUsIGBkb2NrZXIgcnVuYCBleGVjdXRlcyBgL3dvcmsvcnVuX2FsbC5zaGAsIHdoaWNoIGluIHR1cm4gcnVucyBgYnVpbGRfYXR0YWNrZXJfcmVwby5zaGAsIHRoZW4gYHBvY19naXRweXRob24ucHlgLCB0aGVuIGBwb2NfY29udHJvbF9yZWFsZ2l0LnNoYC4pCjQuIEZ1bGwgc291cmNlIG9mIHRoZSBQb0Mgc2NyaXB0IChgR0hTQS90ZXN0aW5nL3BvY19naXRweXRob24ucHlgKSwgdmVyYmF0aW06CmBgYHB5dGhvbgoiIiJHSFNBLTAwMSBQb0M6IEdpdFB5dGhvbiBzaWRlLgoKQ2xvbmVzIHRoZSBhdHRhY2tlciByZXBvIGFuZCBydW5zIHRoZSBlcXVpdmFsZW50IG9mCmBnaXQgc3VibW9kdWxlIHVwZGF0ZSAtLWluaXRgIHZpYSBHaXRQeXRob24sIHRoZW4gY2hlY2tzIHdoZXRoZXIgYSBnaXQKcmVwb3NpdG9yeSB3YXMgY3JlYXRlZCBvdXRzaWRlIHRoZSBjbG9uZSBkaXJlY3RvcnkuCiIiIgppbXBvcnQgb3MKaW1wb3J0IHNodXRpbAoKaW1wb3J0IGdpdAoKQ0xPTkVfRElSID0gJy93b3JrL3ZpY3RpbV9jbG9uZS9yZXBvJwpFU0NBUEVfVEFSR0VUID0gJy90bXAvZ2l0cHl0aG9uX3BvY19lc2NhcGVkX3Jvb3QnCgpkZWYgbWFpbigpOgogICAgc2h1dGlsLnJtdHJlZShvcy5wYXRoLmRpcm5hbWUoQ0xPTkVfRElSKSwgaWdub3JlX2Vycm9ycz1UcnVlKQogICAgc2h1dGlsLnJtdHJlZShFU0NBUEVfVEFSR0VULCBpZ25vcmVfZXJyb3JzPVRydWUpCiAgICBvcy5tYWtlZGlycyhvcy5wYXRoLmRpcm5hbWUoQ0xPTkVfRElSKSwgZXhpc3Rfb2s9VHJ1ZSkKCiAgICBwcmludChmJ0dpdFB5dGhvbiB2ZXJzaW9uOiB7Z2l0Ll9fdmVyc2lvbl9ffScpCiAgICByZXBvID0gZ2l0LlJlcG8uY2xvbmVfZnJvbSgnL3dvcmsvYXR0YWNrZXJfcmVwbycsIENMT05FX0RJUikKICAgIHByaW50KCdDbG9uZWQgaW50bzonLCByZXBvLndvcmtpbmdfdHJlZV9kaXIpCgogICAgc21zID0gbGlzdChyZXBvLnN1Ym1vZHVsZXMpCiAgICBmb3Igc20gaW4gc21zOgogICAgICAgIHByaW50KCcgIHN1Ym1vZHVsZSBuYW1lOicsIHJlcHIoc20ubmFtZSkpCiAgICAgICAgcHJpbnQoJyAgc3VibW9kdWxlIHBhdGg6JywgcmVwcihzbS5wYXRoKSkKCiAgICBwcmludCgnZXNjYXBlX3RhcmdldCBleGlzdHMgYmVmb3JlIHVwZGF0ZTonLCBvcy5wYXRoLmV4aXN0cyhFU0NBUEVfVEFSR0VUKSkKCiAgICBmb3Igc20gaW4gc21zOgogICAgICAgIHRyeToKICAgICAgICAgICAgc20udXBkYXRlKGluaXQ9VHJ1ZSkKICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgICAgIHByaW50KCdzbS51cGRhdGUgcmFpc2VkOicsIHJlcHIoZSkpCgogICAgZXhpc3RzID0gb3MucGF0aC5leGlzdHMoRVNDQVBFX1RBUkdFVCkKICAgIHByaW50KCdlc2NhcGVfdGFyZ2V0IGV4aXN0cyBhZnRlciB1cGRhdGU6JywgZXhpc3RzKQogICAgaWYgZXhpc3RzOgogICAgICAgIHByaW50KCdlc2NhcGVfdGFyZ2V0IGNvbnRlbnRzOicsIG9zLmxpc3RkaXIoRVNDQVBFX1RBUkdFVCkpCgogICAgcHJpbnQoJ1BPQ19SRVNVTFQ9VlVMTkVSQUJMRScgaWYgZXhpc3RzIGVsc2UgJ1BPQ19SRVNVTFQ9U0FGRScpCgppZiBfX25hbWVfXyA9PSAnX19tYWluX18nOgogICAgbWFpbigpCmBgYAo1LiBFeGFjdCBjYXB0dXJlZCB0ZXJtaW5hbCBvdXRwdXQgKHZlcmJhdGltLCBmcm9tIHRoZSBvcmlnaW5hbCBhZHZpc29yeSdzICJDb25maXJtZWQgdGVzdCBydW4gKERvY2tlciwgcmVsZWFzZWQgcGFja2FnZSkiIHNlY3Rpb24pOgpgYGAKPT09IEdpdFB5dGhvbiBQb0MgKHZ1bG5lcmFibGUgcGF0aCkgPT09CkdpdFB5dGhvbiB2ZXJzaW9uOiAzLjEuNTcKQ2xvbmVkIGludG86IC93b3JrL3ZpY3RpbV9jbG9uZS9yZXBvCiAgc3VibW9kdWxlIG5hbWU6ICcuLi8uLi8uLi8uLi8uLi8uLi90bXAvZ2l0cHl0aG9uX3BvY19lc2NhcGVkX3Jvb3QvbW9kdWxlc19kaXInCiAgc3VibW9kdWxlIHBhdGg6ICdsZWdpdF9kaXInCmVzY2FwZV90YXJnZXQgZXhpc3RzIGJlZm9yZSB1cGRhdGU6IEZhbHNlCmVzY2FwZV90YXJnZXQgZXhpc3RzIGFmdGVyIHVwZGF0ZTogVHJ1ZQplc2NhcGVfdGFyZ2V0IGNvbnRlbnRzOiBbJ21vZHVsZXNfZGlyJ10KUE9DX1JFU1VMVD1WVUxORVJBQkxFCgo9PT0gQ29udHJvbDogcmVhbCBnaXQgQ0xJIG9uIGlkZW50aWNhbCByZXBvID09PQp3YXJuaW5nOiBpZ25vcmluZyBzdXNwaWNpb3VzIHN1Ym1vZHVsZSBuYW1lOiAuLi8uLi8uLi8uLi8uLi8uLi90bXAvZ2l0cHl0aG9uX3BvY19lc2NhcGVkX3Jvb3QvbW9kdWxlc19kaXIKd2FybmluZzogaWdub3Jpbmcgc3VzcGljaW91cyBzdWJtb2R1bGUgbmFtZTogLi4vLi4vLi4vLi4vLi4vLi4vdG1wL2dpdHB5dGhvbl9wb2NfZXNjYXBlZF9yb290L21vZHVsZXNfZGlyCmZhdGFsOiBObyB1cmwgZm91bmQgZm9yIHN1Ym1vZHVsZSBwYXRoICdsZWdpdF9kaXInIGluIC5naXRtb2R1bGVzCkNPTlRST0xfUkVTVUxUPVNBRkUgKHJlYWwgZ2l0IGNvcnJlY3RseSByZWZ1c2VkKQpgYGAKNi4gUGF5bG9hZDogdGhlIGF0dGFja2VyIHJld3JpdGVzIHRoZSBgLmdpdG1vZHVsZXNgIHNlY3Rpb24gaGVhZGVyIGZyb20gYFtzdWJtb2R1bGUgImxlZ2l0X2RpciJdYCB0byBgW3N1Ym1vZHVsZSAiLi4vLi4vLi4vLi4vLi4vLi4vdG1wL2dpdHB5dGhvbl9wb2NfZXNjYXBlZF9yb290L21vZHVsZXNfZGlyIl1gIChidWlsdCBieSBgYnVpbGRfYXR0YWNrZXJfcmVwby5zaGAsIHBhcnQgb2YgdGhlIGhhcm5lc3MgaW4gYEdIU0EvdGVzdGluZy9gKS4gVGhlIG1hbGljaW91cyBwYXJ0IGlzIHRoZSBgLi4vLi4vLi4vLi4vLi4vLi4vYCB0cmF2ZXJzYWwgc2VxdWVuY2UgZW1iZWRkZWQgaW4gdGhlIHN1Ym1vZHVsZSAqbmFtZSogKG5vdCB0aGUgdHJlZS12YWxpZGF0ZWQgYHBhdGhgKSwgd2hpY2ggYmVjb21lcyB0aGUgb24tZGlzayB0YXJnZXQgZm9yIHRoZSBzdWJtb2R1bGUncyBzZXBhcmF0ZSBnaXQgZGlyZWN0b3J5Lgo3LiBFeHBlY3RlZCB2cy4gb2JzZXJ2ZWQ6IEEgc2FmZSBpbXBsZW1lbnRhdGlvbiAoYXMgZGVtb25zdHJhdGVkIGJ5IHRoZSByZWFsIGBnaXRgIENMSSBjb250cm9sIHJ1bikgcmVqZWN0cyB0aGUgc3VibW9kdWxlIG5hbWUgd2l0aCAiaWdub3Jpbmcgc3VzcGljaW91cyBzdWJtb2R1bGUgbmFtZSIgYW5kIHJlZnVzZXMgdG8gY3JlYXRlIGFueXRoaW5nIG91dHNpZGUgdGhlIHJlcG9zaXRvcnkuIEdpdFB5dGhvbiBpbnN0ZWFkIGNyZWF0ZWQgdGhlIGVzY2FwZS10YXJnZXQgZGlyZWN0b3J5IGFuZCBhIGZ1bGx5LWluaXRpYWxpemVkIEdpdCByZXBvc2l0b3J5IGF0IGAvdG1wL2dpdHB5dGhvbl9wb2NfZXNjYXBlZF9yb290L21vZHVsZXNfZGlyYCwgY29uZmlybWVkIGJ5IGBlc2NhcGVfdGFyZ2V0IGV4aXN0cyBhZnRlciB1cGRhdGU6IFRydWVgIGFuZCBpdHMgbGlzdGVkIGNvbnRlbnRzLgo4LiBTZWN1cml0eSBpbXBhY3QgZGVtb25zdHJhdGVkOiBhcmJpdHJhcnkgZmlsZXN5c3RlbSBkaXJlY3RvcnkgYW5kIEdpdC1yZXBvc2l0b3J5IGNyZWF0aW9uIGF0IGFuIGF0dGFja2VyLWNob3NlbiBhYnNvbHV0ZSBwYXRoIG91dHNpZGUgdGhlIHZpY3RpbSdzIGludGVuZGVkIGNsb25lIGRpcmVjdG9yeSwgcG9wdWxhdGVkIHdpdGggYXR0YWNrZXItY29udHJvbGxlZCBjb250ZW50IHNvdXJjZWQgZnJvbSB0aGUgc3VibW9kdWxlJ3Mgb3duIChhbHNvIGF0dGFja2VyLWNvbnRyb2xsZWQpIGB1cmxgLgoKIyMjIyMgSW1wYWN0ClBhdGggdHJhdmVyc2FsIChDV0UtMjIpIC8gZXh0ZXJuYWwgY29udHJvbCBvZiBmaWxlIHBhdGggKENXRS03MykgbGVhZGluZyB0byBhcmJpdHJhcnkgZGlyZWN0b3J5IGFuZCBHaXQtcmVwb3NpdG9yeSBjcmVhdGlvbiBvdXRzaWRlIHRoZSBpbnRlbmRlZCBjbG9uZSBkaXJlY3RvcnkuIEludGVncml0eSBpbXBhY3QgaXMgSGlnaCAoYXR0YWNrZXIgY2hvb3NlcyBkZXN0aW5hdGlvbiBwYXRoIGFuZCwgdmlhIHRoZSBzdWJtb2R1bGUgVVJMLCBtdWNoIG9mIHRoZSB3cml0dGVuIGNvbnRlbnQpOyBDb25maWRlbnRpYWxpdHkgaW1wYWN0IGlzIE5vbmUgKG9ubHkgY3JlYXRpb24gd2FzIGRlbW9uc3RyYXRlZCk7IEF2YWlsYWJpbGl0eSBpbXBhY3QgaXMgTG93LU1lZGl1bSAoZGlzay1leGhhdXN0aW9uIHBvdGVudGlhbCkuIE5vIGF1dGhlbnRpY2F0aW9uIGlzIHJlcXVpcmVkOyB0aGUgYXR0YWNrZXIgb25seSBuZWVkcyB0byBjb250cm9sIGEgcmVwb3NpdG9yeSB0aGUgdmljdGltIGNsb25lcyBhbmQgaW5pdGlhbGl6ZXMgc3VibW9kdWxlcyBmb3IgLSBhIHJvdXRpbmUsIG9mdGVuIGZ1bGx5LWF1dG9tYXRpYyBvcGVyYXRpb24gaW4gQ0kgcGlwZWxpbmVzLCBJREUgaW50ZWdyYXRpb25zLCBhbmQgZGVwZW5kZW5jeS1tYW5hZ2VtZW50IHRvb2xpbmcuCgojIyMjIFNldmVyaXR5Ci0gQ1ZTUyBTY29yZTogOC4yIC8gMTAgKEhpZ2gpCi0gVmVjdG9yIFN0cmluZzogYENWU1M6My4xL0FWOk4vQUM6TC9QUjpOL1VJOlIvUzpDL0M6Ti9JOkgvQTpMYAoKIyMjIyBSZWZlcmVuY2VzCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vc2VjdXJpdHkvYWR2aXNvcmllcy9HSFNBLWhtcTItdzU4Zi0yN2pjXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3NlY3VyaXR5L2Fkdmlzb3JpZXMvR0hTQS1obXEyLXc1OGYtMjdqYykKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9wdWxsLzIyMDJdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcHVsbC8yMjAyKQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL2NvbW1pdC80Mjk5Yzk5MGUxY2EyMTg5NmY5NDg1Mjc3Y2FmN2JiMGFlNWI0MDRjXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL2NvbW1pdC80Mjk5Yzk5MGUxY2EyMTg5NmY5NDg1Mjc3Y2FmN2JiMGFlNWI0MDRjKQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL2NvbW1pdC9lNGI4ZTdkMDI2Y2E2YWJiNGNmNjA0ZjhlNzcwOTM0MzJjZTIzYzA2XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL2NvbW1pdC9lNGI4ZTdkMDI2Y2E2YWJiNGNmNjA0ZjhlNzcwOTM0MzJjZTIzYzA2KQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uKQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3JlbGVhc2VzL3RhZy8zLjEuNThdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcmVsZWFzZXMvdGFnLzMuMS41OCkKClRoaXMgZGF0YSBpcyBwcm92aWRlZCBieSBbT1NWXShodHRwczovL29zdi5kZXYvdnVsbmVyYWJpbGl0eS9HSFNBLWhtcTItdzU4Zi0yN2pjKSBhbmQgdGhlIFtHaXRIdWIgQWR2aXNvcnkgRGF0YWJhc2VdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRodWIvYWR2aXNvcnktZGF0YWJhc2UpIChbQ0MtQlkgNC4wXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0aHViL2Fkdmlzb3J5LWRhdGFiYXNlL2Jsb2IvbWFpbi9MSUNFTlNFLm1kKSkuCjwvZGV0YWlscz4KCi0tLQoKIyMjIEdpdFB5dGhvbjogZ2l0LWNvbmZpZyBPUFRJT04tbmFtZSBpbmplY3Rpb24gdmlhID0vIy93aGl0ZXNwYWNlIGJ5cGFzc2VzIG5hbWUgdmFsaWRhdG9yLCBlbmFibGluZyBmb3JnZWQgY29yZS5zc2hDb21tYW5kL2hvb2tzUGF0aCAoUkNFKQpbR0hTQS1qbTc4LTlmdnYtbWhncl0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2Fkdmlzb3JpZXMvR0hTQS1qbTc4LTlmdnYtbWhncikKCjxkZXRhaWxzPgo8c3VtbWFyeT5Nb3JlIGluZm9ybWF0aW9uPC9zdW1tYXJ5PgoKIyMjIyBEZXRhaWxzCiMjIyMjIFN1bW1hcnkKR2l0UHl0aG9uJ3MgY29uZmlnLW5hbWUgdmFsaWRhdG9yIG9ubHkgbmV1dHJhbGl6ZXMgQ1IvTEYvTlVMIGZvciB0aGUgYCJvcHRpb24iYCBsYWJlbDsgaXQgZG9lcyBub3QgcmVqZWN0IGA9YCwgYCNgLCBgO2AsIGBbYCwgYF1gLCBvciB3aGl0ZXNwYWNlIGluIGFuICoqb3B0aW9uIG5hbWUqKi4gYHdyaXRlX3NlY3Rpb25gIHdyaXRlcyB0aGUgb3B0aW9uIG5hbWUgdmVyYmF0aW0gaW50byB0aGUgY29uZmlnIGZpbGUsIHNvIGFuIG9wdGlvbiBuYW1lIHN1Y2ggYXMgYHNzaENvbW1hbmQgPSB0b3VjaCA8Y21kPiAjYCBpcyB3cml0dGVuIGFzIGBcdHNzaENvbW1hbmQgPSB0b3VjaCA8Y21kPiAjID0gPHZhbHVlPmAsIHdoaWNoIGdpdCBwYXJzZXMgYXMgYGNvcmUuc3NoQ29tbWFuZCA9IHRvdWNoIDxjbWQ+YCAodGhlIHRyYWlsaW5nIGAjYCBjb21tZW50cyBvdXQgdGhlIGludGVuZGVkIHZhbHVlKS4gVGhpcyBmb3JnZXMgYXJiaXRyYXJ5IGNvbmZpZyBkaXJlY3RpdmVzIChgY29yZS5zc2hDb21tYW5kYCwgYGNvcmUuaG9va3NQYXRoYCwgYGFsaWFzLipgKSDihpIgUkNFIG9uIHRoZSBuZXh0IGdpdCBvcGVyYXRpb24uIFRoaXMgaXMgYSBkaXN0aW5jdCBmaWVsZCAob3B0aW9uIG5hbWUsIG5vdCBzZWN0aW9uIG5hbWUpIGFuZCBkaXN0aW5jdCBjaGFyYWN0ZXIgY2xhc3MgKGA9YC9gI2Avc3BhY2UsIG5vdCBuZXdsaW5lL2JyYWNrZXQpIGZyb20gR0hTQS0zcnA1LWpqbXctNHd2MiAoc2VjdGlvbi1uYW1lIGJyYWNrZXQgaW5qZWN0aW9uKSBhbmQgR0hTQS1tdjkzLXc3OTktY2oydyAvIEdIU0Etdjg3ci02cTNmLTJqNjcgKG5ld2xpbmUgaW5qZWN0aW9uKS4KCiMjIyMjIFJvb3QgQ2F1c2UKYF9hc3N1cmVfY29uZmlnX25hbWVfc2FmZShuYW1lLCBsYWJlbClgIChgZ2l0L2NvbmZpZy5weTo4OTdgKSBhcHBsaWVzIHRoZSBicmFja2V0L3F1b3RlIHN0YXRlIG1hY2hpbmUgT05MWSB3aGVuIGBsYWJlbCA9PSAic2VjdGlvbiJgOyBmb3IgdGhlIGAib3B0aW9uImAgbGFiZWwgaXQgZmFsbHMgdGhyb3VnaCB3aXRoIGp1c3QgdGhlIGBVTlNBRkVfQ09ORklHX0NIQVJTX1JFID0gW1xyXG5ceDAwXWAgcmVnZXguIGB3cml0ZV9zZWN0aW9uYCB0aGVuIHdyaXRlcyB0aGUgb3B0aW9uIG5hbWUgdmVyYmF0aW0gaW50byBgIlx0JXMgPSAlc1xuImAgKGNvbmZpZy5weTo3MDIpLgoKIyMjIyMgSW1wYWN0CkFyYml0cmFyeSBnaXQtY29uZmlnIGRpcmVjdGl2ZSBpbmplY3Rpb24g4oaSIHJlbW90ZSBjb2RlIGV4ZWN1dGlvbiB2aWEgYGNvcmUuc3NoQ29tbWFuZGAgKGZpcmVzIG9uIGFueSBzc2ggZ2l0IG9wZXJhdGlvbiwgbm8gc3RhZ2VkIGZpbGUgbmVlZGVkKSBvciBgY29yZS5ob29rc1BhdGhgICh3aXRoIGEgc3RhZ2VkIGhvb2spLiBSZXF1aXJlcyB0aGUgZW1iZWRkaW5nIGFwcGxpY2F0aW9uIHRvIGZvcndhcmQgYSBjYWxsZXItaW5mbHVlbmNlZCBPUFRJT04gTkFNRSBpbnRvIHRoZSBjb25maWcgd3JpdGVyIChuYW1lLWNvbnRyb2wgbW9kZWwsIHRoZSBzYW1lIG5hbWUtY29udHJvbCBtb2RlbCBhY2NlcHRlZCBieSB0aGUgcmVsYXRlZCBwdWJsaXNoZWQgYWR2aXNvcmllcyBHSFNBLTNycDUtamptdy00d3YyIGFuZCBHSFNBLW12OTMtdzc5OS1jajJ3KS4gRGVmYXVsdCBjb25maWd1cmF0aW9uLgoKIyMjIyMgUHJvb2Ygb2YgQ29uY2VwdApgYGBweXRob24Kd2l0aCByZXBvLmNvbmZpZ193cml0ZXIoKSBhcyBjdzoKICAgIGN3LnNldF92YWx1ZSgiY29yZSIsICJzc2hDb21tYW5kID0gdG91Y2ggL3RtcC9SQ0UgIyIsICJ4IikKCiMjIyMjIGdpdCBjb25maWcgLS1nZXQgY29yZS5zc2hDb21tYW5kICAtPiAgdG91Y2ggL3RtcC9SQ0UKYGBgCgojIyMjIyBBdHRhY2sgQ2hhaW4KMS4gRW50cnk6IGFwcCBjYWxscyBjb25maWcgd3JpdGVyIHdpdGggYXR0YWNrZXItY29udHJvbGxlZCBPUFRJT04gbmFtZTogYHNldF92YWx1ZSgiY29yZSIsICJzc2hDb21tYW5kID0gdG91Y2ggL3RtcC9SQ0UgIyIsICJ4IilgLgoyLiBDaGVjazogYF9hc3N1cmVfY29uZmlnX25hbWVfc2FmZShvcHRpb24sICJvcHRpb24iKWAgQCYjODIwMzsgY29uZmlnLnB5LiBHdWFyZDogcmVnZXggbWF0Y2hlcyBvbmx5IGBbXHJcblx4MDBdYDsgYnJhY2tldC9xdW90ZSBzdGF0ZSBtYWNoaW5lIGlzIGdhdGVkIG9uIGBsYWJlbD09InNlY3Rpb24iYC4gQnlwYXNzIHByb29mOiBgPWAsYCNgLHNwYWNlIHBhc3Mg4oaSIG5vIGBWYWx1ZUVycm9yYC4KMy4gU2luazogYHdyaXRlX3NlY3Rpb25gIHdyaXRlcyBgIlx0c3NoQ29tbWFuZCA9IHRvdWNoIC90bXAvUkNFICMgPSB4XG4iYCAoY29uZmlnLnB5OjcwMikuCjQuIEltcGFjdDogZ2l0IHBhcnNlcyBgY29yZS5zc2hDb21tYW5kPXRvdWNoIC90bXAvUkNFYCDihpIgYXJiaXRyYXJ5IGNvZGUgZXhlY3V0aW9uIG9uIG5leHQgZ2l0IG9wLgoKIyMjIyMgQnlwYXNzIEV2aWRlbmNlCkluZGVwZW5kZW50bHkgcmVwcm9kdWNlZCAoZ2F0ZSBoYXJuZXNzKTogYHNldF92YWx1ZSgnY29yZScsJ3NzaENvbW1hbmQgPSB0b3VjaCA8UkNFPiAjJywneCcpYCDihpIgbm8gYFZhbHVlRXJyb3JgOyBmaWxlIGxpbmUgYHNzaENvbW1hbmQgPSB0b3VjaCA8UkNFPiAjID0geGA7IGBnaXQgY29uZmlnIC0tZ2V0IGNvcmUuc3NoQ29tbWFuZGAg4oaSIGB0b3VjaCA8UkNFPmAgKHJjPTApLiBBbHNvIHZlcmlmaWVkIGBjb3JlLmhvb2tzUGF0aGAgdmlhIGJvdGggYEdpdENvbmZpZ1BhcnNlcmAgYW5kIGByZXBvLmNvbmZpZ193cml0ZXIoKWAuIEZpeC1jb21taXQgcmVhZDogYnJhY2tldC9xdW90ZSBjaGVja3MgYXJlIGluc2lkZSBgaWYgbGFiZWwgPT0gInNlY3Rpb24iYDsgdGhlIGAib3B0aW9uImAgbGFiZWwgaXMgbm90IGNvdmVyZWQuCgojIyMjIyBBZmZlY3RlZCBWZXJzaW9ucwpgR2l0UHl0aG9uIDw9IDMuMS41N2AgKHZhbGlkYXRvciBwcmVzZW50IHZlcmJhdGltIG9uIHRoZSBsYXRlc3QgcmVsZWFzZSB0YWcpLgoKIyMjIyMgU3VnZ2VzdGVkIEZpeApBcHBseSB0aGUgc2VjdGlvbi1uYW1lIHNhZmV0eSBjaGVja3MgKHJlamVjdCBgPWAsIGAjYCwgYDtgLCBgW2AsIGBdYCwgd2hpdGVzcGFjZSkgdG8gdGhlIGAib3B0aW9uImAgbGFiZWwgYXMgd2VsbCwgb3IgdmFsaWRhdGUgdGhlIGZ1bGx5LXJlbmRlcmVkIGNvbmZpZyBsaW5lIGFmdGVyIHN1YnN0aXR1dGlvbi4KCi0tLQpSZXBvcnRlZCBieSAqKnp4IChKYWNlKSoqIOKAlCBHaXRIdWI6IEAmIzgyMDM7bWFudXMtdXNlCgojIyMjIFNldmVyaXR5Ci0gQ1ZTUyBTY29yZTogOC44IC8gMTAgKEhpZ2gpCi0gVmVjdG9yIFN0cmluZzogYENWU1M6My4xL0FWOk4vQUM6TC9QUjpML1VJOk4vUzpVL0M6SC9JOkgvQTpIYAoKIyMjIyBSZWZlcmVuY2VzCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vc2VjdXJpdHkvYWR2aXNvcmllcy9HSFNBLWptNzgtOWZ2di1taGdyXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3NlY3VyaXR5L2Fkdmlzb3JpZXMvR0hTQS1qbTc4LTlmdnYtbWhncikKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9wdWxsLzIyMDRdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcHVsbC8yMjA0KQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL2NvbW1pdC9hNDk1Y2NkM2I1NDdjY2Q2MGIyMTg3MjE1ODIzYjcyYTljMDE4OGJmXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL2NvbW1pdC9hNDk1Y2NkM2I1NDdjY2Q2MGIyMTg3MjE1ODIzYjcyYTljMDE4OGJmKQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uKQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3JlbGVhc2VzL3RhZy8zLjEuNThdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcmVsZWFzZXMvdGFnLzMuMS41OCkKClRoaXMgZGF0YSBpcyBwcm92aWRlZCBieSBbT1NWXShodHRwczovL29zdi5kZXYvdnVsbmVyYWJpbGl0eS9HSFNBLWptNzgtOWZ2di1taGdyKSBhbmQgdGhlIFtHaXRIdWIgQWR2aXNvcnkgRGF0YWJhc2VdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRodWIvYWR2aXNvcnktZGF0YWJhc2UpIChbQ0MtQlkgNC4wXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0aHViL2Fkdmlzb3J5LWRhdGFiYXNlL2Jsb2IvbWFpbi9MSUNFTlNFLm1kKSkuCjwvZGV0YWlscz4KCi0tLQoKIyMjIEdpdFB5dGhvbjogVW5zYWZlIGdpdCBvcHRpb24gZ3VhcmQgYnlwYXNzIHZpYSBzcGxpdF9zaW5nbGVfY2hhcl9vcHRpb25zPUZhbHNlIHNob3J0LW9wdGlvbiB0b2tlbiBzbXVnZ2xpbmcgZW5hYmxlcyBjb21tYW5kIGV4ZWN1dGlvbgpbR0hTQS13dnBwLThoeDktcDY2al0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2Fkdmlzb3JpZXMvR0hTQS13dnBwLThoeDktcDY2aikKCjxkZXRhaWxzPgo8c3VtbWFyeT5Nb3JlIGluZm9ybWF0aW9uPC9zdW1tYXJ5PgoKIyMjIyBEZXRhaWxzCiMjIyMjIFN1bW1hcnkKVGhlIGBjaGVja191bnNhZmVfb3B0aW9uc2AgZ3VhcmQgY2FuIGJlIGJ5cGFzc2VkIG9uIGV2ZXJ5IGd1YXJkZWQgbWV0aG9kIChjbG9uZS9jbG9uZV9mcm9tLCBmZXRjaC9wdWxsL3B1c2gsIGxzX3JlbW90ZSwgaXRlcl9jb21taXRzLCBibGFtZSwgYXJjaGl2ZSkgYnkgY29tYmluaW5nIGEgc2luZ2xlLWNoYXJhY3RlciBrd2FyZyB3aXRoIGBzcGxpdF9zaW5nbGVfY2hhcl9vcHRpb25zPUZhbHNlYC4gVGhlIGd1YXJkJ3MgY2FuZGlkYXRlIGxpc3Qgb21pdHMgdGhlIHNtdWdnbGVkIG9wdGlvbiwgYnV0IGB0cmFuc2Zvcm1fa3dhcmdgIGVtaXRzIGEgSk9JTkVEIGAtbjx2YWx1ZT5gIGFyZ3YgdG9rZW4gdGhhdCBnaXQgcGFyc2VzIGFzIGAtLXVwbG9hZC1wYWNrPTxjbWQ+YCwgeWllbGRpbmcgYXJiaXRyYXJ5IGNvbW1hbmQgZXhlY3V0aW9uIGF0IHRoZSBkZWZhdWx0IGBhbGxvd191bnNhZmVfb3B0aW9ucz1GYWxzZWAuIFRoaXMgaXMgYW4gaW5jb21wbGV0ZS1maXggYnlwYXNzIG9mIGNvbW1pdCBgZThkMGZiZjdgICh0aGUgZml4IGZvciBHSFNBLXI5bXItbTM3Yy01ZnIzKSwgd2hpY2ggb25seSBlbWl0cyB2YWx1ZS1kZXJpdmVkIGNhbmRpZGF0ZXMgd2hlbiBgc3BsaXRfc2luZ2xlX2NoYXJfb3B0aW9uc2AgaXMgVHJ1ZS4KCiMjIyMjIFJvb3QgQ2F1c2UKYF9vcHRpb25fY2FuZGlkYXRlc2AgZGVyaXZlcyB2YWx1ZS10b2tlbiBjYW5kaWRhdGVzIG9ubHkgdW5kZXIgYGlmIGxlbihrZXkpPT0xIGFuZCBzcGxpdF9zaW5nbGVfY2hhcl9vcHRpb25zOmAgKGNtZC5weToxMDQ4LCBhZGRlZCBieSBgZThkMGZiZjdgKS4gV2l0aCBgc3BsaXRfc2luZ2xlX2NoYXJfb3B0aW9ucz1GYWxzZWAsIGBfb3B0aW9uX2NhbmRpZGF0ZXMoW10sIHsibiI6InV0b3VjaCA8Y21kPjtnaXQtdXBsb2FkLXBhY2sifSlgIHJldHVybnMgb25seSBgWyctbiddYCAobm90IG9uIHRoZSBkZW55bGlzdCksIHNvIHRoZSBndWFyZCBwYXNzZXMuIEJ1dCBgdHJhbnNmb3JtX2t3YXJnKCduJywgdmFsdWUsIHNwbGl0X3NpbmdsZV9jaGFyX29wdGlvbnM9RmFsc2UpYCBlbWl0cyB0aGUgSk9JTkVEIHRva2VuIGAtbnV0b3VjaCA8Y21kPjtnaXQtdXBsb2FkLXBhY2tgIChjbWQucHk6MTYzMSkuIGdpdCBjbHVzdGVycyB2YWx1ZS1sZXNzIHNob3J0IGZsYWdzIHRoZW4gcGFyc2VzIGAtdTxjbWQ+YCA9IGAtLXVwbG9hZC1wYWNrPTxjbWQ+YCDihpIgY29tbWFuZCBleGVjdXRpb24uIFRoZSBoYXJkZW5lZCBndWFyZCBXT1VMRCBibG9jayB0aGUgam9pbmVkIHRva2VuIGlmIGl0IHNhdyBpdCDigJQgdGhlIGZsYXcgaXMgaXQgbmV2ZXIgcmVjZWl2ZXMgaXQuCgojIyMjIyBJbXBhY3QKQXJiaXRyYXJ5IE9TIGNvbW1hbmQgZXhlY3V0aW9uIGFzIHRoZSBob3N0IHByb2Nlc3MgKHZpYSBgLS11cGxvYWQtcGFja2ApIGF0IGRlZmF1bHQgYGFsbG93X3Vuc2FmZV9vcHRpb25zPUZhbHNlYCwgYWZmZWN0aW5nIGFsbCBndWFyZGVkIG1ldGhvZHMgdGhhdCBmb3J3YXJkIGt3YXJncy4gUHJlY29uZGl0aW9uOiB0aGUgYXBwIGZvcndhcmRzIGEgdXNlci1jb250cm9sbGVkIGt3YXJncyBkaWN0IGNvbnRhaW5pbmcgYHNwbGl0X3NpbmdsZV9jaGFyX29wdGlvbnM9RmFsc2VgIHBsdXMgYSBzaW5nbGUtY2hhciBrZXkgKHNhbWUgdXNlci1kaWN0LWZvcndhcmRpbmcgbW9kZWwgR0hTQS1yOW1yLW0zN2MtNWZyMyBhY2NlcHRzKS4KCiMjIyMjIFByb29mIG9mIENvbmNlcHQKYGBgcHl0aG9uCmZyb20gZ2l0IGltcG9ydCBSZXBvClJlcG8uY2xvbmVfZnJvbShzcmMsIGRzdCwKICAgIG49InV0b3VjaCAvdG1wL0FDRTtnaXQtdXBsb2FkLXBhY2siLAogICAgc3BsaXRfc2luZ2xlX2NoYXJfb3B0aW9ucz1GYWxzZSkgICAjIC90bXAvQUNFIGNyZWF0ZWQgLT4gQUNFCmBgYAoKIyMjIyMgQXR0YWNrIENoYWluCjEuIEVudHJ5OiBhcHAgZm9yd2FyZHMgdXNlciBrd2FyZ3MgdG8gYFJlcG8uY2xvbmVfZnJvbSh1cmwsIHBhdGgsICoqa3dhcmdzKWA6IGB7c3BsaXRfc2luZ2xlX2NoYXJfb3B0aW9uczogRmFsc2UsIG46ICd1dG91Y2ggL3RtcC9BQ0U7Z2l0LXVwbG9hZC1wYWNrJ31gLgoyLiBDaGVjazogYGNoZWNrX3Vuc2FmZV9vcHRpb25zKF9vcHRpb25fY2FuZGlkYXRlcyhbXSwga3dhcmdzKSwgdW5zYWZlX2dpdF9jbG9uZV9vcHRpb25zKWAuIEd1YXJkOiBkZW55bGlzdCBpbmNsdWRlcyBgLS11cGxvYWQtcGFja2AvYC11YC4gQnlwYXNzIHByb29mOiBgX29wdGlvbl9jYW5kaWRhdGVzYCB5aWVsZHMgb25seSBgWyctbiddYCAodmFsdWUgdG9rZW4gc2tpcHBlZCBiZWNhdXNlIGBzcGxpdD1GYWxzZWApOyBndWFyZCBuZXZlciBzZWVzIGAtdWAuCjMuIFNpbms6IGB0cmFuc2Zvcm1fa3dhcmdgIGVtaXRzIGpvaW5lZCB0b2tlbiAoY21kLnB5OjE2MzEpLiBhcmd2IChvYnNlcnZlZCk6IGBbJ2dpdCcsJ2Nsb25lJywnLXYnLCctbnV0b3VjaCAvdG1wL0FDRTtnaXQtdXBsb2FkLXBhY2snLCctLScsJzxzcmM+JywnPGRzdD4nXWAuCjQuIEltcGFjdDogZ2l0IGNsdXN0ZXJzIGAtbmAgKyBgLXU8Y21kPmAg4oaSIHJ1bnMgdXBsb2FkLXBhY2sgY29tbWFuZCDihpIgQUNFLgoKIyMjIyMgQnlwYXNzIEV2aWRlbmNlCkluZGVwZW5kZW50bHkgcmVwcm9kdWNlZCAoZ2F0ZSBoYXJuZXNzLCBkZWZhdWx0IGBhbGxvd191bnNhZmVfb3B0aW9ucz1GYWxzZWApOiB0aGUgYHNwbGl0PUZhbHNlYCBwYXlsb2FkIGNyZWF0ZWQgdGhlIG1hcmtlciBgVkgwNV9HQVRFX0FDRWAgKEFDRSk7IHRoZSBjbG9uZSByZXR1cm5lZCBub3JtYWxseSAoZ3VhcmQgYnlwYXNzZWQpLiBDb250cm9sOiBgbj0nLS11cGxvYWQtcGFjaz3igKYnYCAoc3BsaXQgZGVmYXVsdCBUcnVlKSDihpIgYFVuc2FmZU9wdGlvbkVycm9yOiAtLXVwbG9hZC1wYWNrIGlzIG5vdCBhbGxvd2VkYC4gRml4LWNvbW1pdCByZWFkOiBgZThkMGZiZjdgIGV4dGVuZHMgY2FuZGlkYXRlcyBvbmx5IHVuZGVyIGBpZiBsZW4oa2V5KT09MSBhbmQgc3BsaXRfc2luZ2xlX2NoYXJfb3B0aW9uczpgIOKAlCBzcGxpdD1GYWxzZSBza2lwcyB2YWx1ZSBlbWlzc2lvbi4gQWxzbyBjb25maXJtZWQgdGhlIGVhcmxpZXIgY2x1c3RlcmluZy1wYXJzZSBmaXggKGNvbW1pdCBgNTY4MDYwODBgKSBkb2VzIG5vdCBjb3ZlciB0aGlzIGJlY2F1c2UgdGhlIGd1YXJkIG9ubHkgZXZlciByZWNlaXZlcyBgWyctbiddYC4KCiMjIyMjIEFmZmVjdGVkIFZlcnNpb25zCmBHaXRQeXRob24gPD0gMy4xLjU3YCAoY29kZSBwcmVzZW50IHZlcmJhdGltIG9uIHRoZSBsYXRlc3QgcmVsZWFzZSB0YWcpLgoKIyMjIyMgU3VnZ2VzdGVkIEZpeApNYWtlIGBfb3B0aW9uX2NhbmRpZGF0ZXNgIGVtaXQgdmFsdWUtZGVyaXZlZCBjYW5kaWRhdGVzIHJlZ2FyZGxlc3Mgb2YgYHNwbGl0X3NpbmdsZV9jaGFyX29wdGlvbnNgIChpLmUuIGFsc28gZm9yIHRoZSBqb2luZWQgYC1uPHZhbHVlPmAgZm9ybSksIE9SIHJ1biBgY2hlY2tfdW5zYWZlX29wdGlvbnNgIG92ZXIgdGhlIGZ1bGx5LXRyYW5zZm9ybWVkIGFyZ3YgcmF0aGVyIHRoYW4gdGhlIHJlY29uc3RydWN0ZWQgbmFtZS1vbmx5IGNhbmRpZGF0ZSBsaXN0LgoKLS0tClJlcG9ydGVkIGJ5ICoqenggKEphY2UpKiog4oCUIEdpdEh1YjogQCYjODIwMzttYW51cy11c2UKCiMjIyMgU2V2ZXJpdHkKLSBDVlNTIFNjb3JlOiA4LjggLyAxMCAoSGlnaCkKLSBWZWN0b3IgU3RyaW5nOiBgQ1ZTUzozLjEvQVY6Ti9BQzpML1BSOkwvVUk6Ti9TOlUvQzpIL0k6SC9BOkhgCgojIyMjIFJlZmVyZW5jZXMKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9zZWN1cml0eS9hZHZpc29yaWVzL0dIU0Etd3ZwcC04aHg5LXA2NmpdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vc2VjdXJpdHkvYWR2aXNvcmllcy9HSFNBLXd2cHAtOGh4OS1wNjZqKQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3B1bGwvMjIwNF0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9wdWxsLzIyMDQpCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vY29tbWl0Lzk2YTg4OGY0ZDc4MmNiMmY4MDQ1MjE0OGU0OGU2MGNlNGFmNmQ1NDFdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vY29tbWl0Lzk2YTg4OGY0ZDc4MmNiMmY4MDQ1MjE0OGU0OGU2MGNlNGFmNmQ1NDEpCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob25dKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24pCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcmVsZWFzZXMvdGFnLzMuMS41OF0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9yZWxlYXNlcy90YWcvMy4xLjU4KQoKVGhpcyBkYXRhIGlzIHByb3ZpZGVkIGJ5IFtPU1ZdKGh0dHBzOi8vb3N2LmRldi92dWxuZXJhYmlsaXR5L0dIU0Etd3ZwcC04aHg5LXA2NmopIGFuZCB0aGUgW0dpdEh1YiBBZHZpc29yeSBEYXRhYmFzZV0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdGh1Yi9hZHZpc29yeS1kYXRhYmFzZSkgKFtDQy1CWSA0LjBdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRodWIvYWR2aXNvcnktZGF0YWJhc2UvYmxvYi9tYWluL0xJQ0VOU0UubWQpKS4KPC9kZXRhaWxzPgoKLS0tCgojIyMgUmVsZWFzZSBOb3RlcwoKPGRldGFpbHM+CjxzdW1tYXJ5PmdpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbiAoR2l0UHl0aG9uKTwvc3VtbWFyeT4KCiMjIyBbYHYzLjEuNThgXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3JlbGVhc2VzL3RhZy8zLjEuNTgpOiBTZWN1cml0eSBhbmQgRml4ZXMKCltDb21wYXJlIFNvdXJjZV0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9jb21wYXJlLzMuMS41Ny4uLjMuMS41OCkKCiMjIyMjIFdoYXQncyBDaGFuZ2VkCgotIHRlc3Q6IGFsbG93IFB5dGhvbiBzdGFydHVwIGJlZm9yZSB0aW1lb3V0IGJ5IFtAJiM4MjAzO0J5cm9uXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vQnlyb24pIGluIFsjJiM4MjAzOzIxOTVdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcHVsbC8yMTk1KQotIFJlc29sdmUgV2luZG93cyBob29rIEJhc2ggdGhyb3VnaCBQQVRIIGJ5IFtAJiM4MjAzO0J5cm9uXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vQnlyb24pIGluIFsjJiM4MjAzOzIxOTldKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcHVsbC8yMTk5KQotIFJldmVydCAiUmVzb2x2ZSBXaW5kb3dzIGhvb2sgQmFzaCB0aHJvdWdoIFBBVEgiIGJ5IFtAJiM4MjAzO0J5cm9uXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vQnlyb24pIGluIFsjJiM4MjAzOzIyMDBdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcHVsbC8yMjAwKQotIHRlc3Q6IGZvY3VzIHB5dGVzdCBzdW1tYXJ5IG9uIHVuZXhwZWN0ZWQgZmFpbHVyZXMgYnkgW0AmIzgyMDM7cmFpc3VsY2hvd2RodXJ5XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vcmFpc3VsY2hvd2RodXJ5KSBpbiBbIyYjODIwMzsyMjAzXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3B1bGwvMjIwMykKLSBWYWxpZGF0ZSBzdWJtb2R1bGUgbmFtZXMgYmVmb3JlIGZpbGVzeXN0ZW0gb3BlcmF0aW9ucyBieSBbQCYjODIwMztCeXJvbl0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL0J5cm9uKSBpbiBbIyYjODIwMzsyMjAyXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3B1bGwvMjIwMikKLSBIYW5kbGUgaW52YWxpZCBzdWJtb2R1bGUgbmFtZXMgZHVyaW5nIHJlY3Vyc2l2ZSB1cGRhdGVzIGJ5IFtAJiM4MjAzO0J5cm9uXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vQnlyb24pIGluIFsjJiM4MjAzOzIyMDVdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcHVsbC8yMjA1KQotIEZpeCBXaW5kb3dzIHBhdGggaGFuZGxpbmcgb24gUHl0aG9uIDMuMTMrIGJ5IFtAJiM4MjAzO0J5cm9uXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vQnlyb24pIGluIFsjJiM4MjAzOzIxOTZdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcHVsbC8yMTk2KQotIGZpeHVwIDIyMDIgYnkgW0AmIzgyMDM7Qnlyb25dKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9CeXJvbikgaW4gWyMmIzgyMDM7MjIwNl0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9wdWxsLzIyMDYpCi0gQ29ycmVjdCBXaW5kb3dzIGhvb2sgQmFzaCBwcmVjZWRlbmNlIGJ5IFtAJiM4MjAzO0J5cm9uXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vQnlyb24pIGluIFsjJiM4MjAzOzIyMDFdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcHVsbC8yMjAxKQotIEhhcmRlbiBjb25maWcgYW5kIEdpdCBvcHRpb24gdmFsaWRhdGlvbiBieSBbQCYjODIwMztCeXJvbl0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL0J5cm9uKSBpbiBbIyYjODIwMzsyMjA0XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3B1bGwvMjIwNCkKLSBTa2lwIHRlc3RzIHRoYXQgbmVlZCBzeW1saW5rIHByaXZpbGVnZXMgaW5zdGVhZCBvZiBlcnJvcmluZyBieSBbQCYjODIwMztDeXJ1czU4MDUyOV0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL0N5cnVzNTgwNTI5KSBpbiBbIyYjODIwMzsyMTk3XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3B1bGwvMjE5NykKCiMjIyMjIE5ldyBDb250cmlidXRvcnMKCi0gW0AmIzgyMDM7cmFpc3VsY2hvd2RodXJ5XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vcmFpc3VsY2hvd2RodXJ5KSBtYWRlIHRoZWlyIGZpcnN0IGNvbnRyaWJ1dGlvbiBpbiBbIyYjODIwMzsyMjAzXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3B1bGwvMjIwMykKLSBbQCYjODIwMztDeXJ1czU4MDUyOV0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL0N5cnVzNTgwNTI5KSBtYWRlIHRoZWlyIGZpcnN0IGNvbnRyaWJ1dGlvbiBpbiBbIyYjODIwMzsyMTk3XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3B1bGwvMjE5NykKCioqRnVsbCBDaGFuZ2Vsb2cqKjogPGh0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vY29tcGFyZS8zLjEuNTcuLi4zLjEuNTg+Cgo8L2RldGFpbHM+CgotLS0KCiMjIyBDb25maWd1cmF0aW9uCgrwn5OFICoqU2NoZWR1bGUqKjogKFVUQykKCi0gQnJhbmNoIGNyZWF0aW9uCiAgLSBBdCBhbnkgdGltZSAobm8gc2NoZWR1bGUgZGVmaW5lZCkKLSBBdXRvbWVyZ2UKICAtIEF0IGFueSB0aW1lIChubyBzY2hlZHVsZSBkZWZpbmVkKQoK8J+apiAqKkF1dG9tZXJnZSoqOiBEaXNhYmxlZCBieSBjb25maWcuIFBsZWFzZSBtZXJnZSB0aGlzIG1hbnVhbGx5IG9uY2UgeW91IGFyZSBzYXRpc2ZpZWQuCgrimbsgKipSZWJhc2luZyoqOiBXaGVuZXZlciBQUiBiZWNvbWVzIGNvbmZsaWN0ZWQsIG9yIHlvdSB0aWNrIHRoZSByZWJhc2UvcmV0cnkgY2hlY2tib3guCgrwn5SVICoqSWdub3JlKio6IENsb3NlIHRoaXMgUFIgYW5kIHlvdSB3b24ndCBiZSByZW1pbmRlZCBhYm91dCB0aGVzZSB1cGRhdGVzIGFnYWluLgoKLS0tCgogLSBbIF0gPCEtLSByZWJhc2UtY2hlY2sgLS0+SWYgeW91IHdhbnQgdG8gcmViYXNlL3JldHJ5IHRoaXMgUFIsIGNoZWNrIHRoaXMgYm94CgotLS0KClRoaXMgUFIgd2FzIGdlbmVyYXRlZCBieSBbTWVuZCBSZW5vdmF0ZV0oaHR0cHM6Ly9tZW5kLmlvL3Jlbm92YXRlLykuIFZpZXcgdGhlIFtyZXBvc2l0b3J5IGpvYiBsb2ddKGh0dHBzOi8vZGV2ZWxvcGVyLm1lbmQuaW8vZ2l0aHViL29zaXNtL25ldGJveC1tYW5hZ2VyKS4KPCEtLXJlbm92YXRlLWRlYnVnOmV5SmpjbVZoZEdWa1NXNVdaWElpT2lJME5DNHhNaTR3SWl3aWRYQmtZWFJsWkVsdVZtVnlJam9pTkRRdU1USXVNQ0lzSW5SaGNtZGxkRUp5WVc1amFDSTZJbTFoYVc0aUxDSnNZV0psYkhNaU9sc2ljbVZ1YjNaaGRHVWlYWDA9LS0+Cg==
      patchset: 916c14ee794a8c2453de3bc8d0a3293f7d9ae186
      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/yamllint/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/netbox-manager
        name: osism/netbox-manager
        short_name: netbox-manager
        src_dir: src/github.com/osism/netbox-manager
      projects:
        github.com/osism/netbox-manager:
          canonical_hostname: github.com
          canonical_name: github.com/osism/netbox-manager
          checkout: main
          checkout_description: zuul branch
          commit: 9f7bc941d1d21c52ad61f1856a9e993dd68963fd
          name: osism/netbox-manager
          required: false
          short_name: netbox-manager
          src_dir: src/github.com/osism/netbox-manager
      ref: refs/pull/293/head
      resources: {}
      tenant: osism
      timeout: 1800
      topic: null
      voting: true
