Harden git_gate.py shell rendering #164

Closed
didericis-claude wants to merge 0 commits from harden-git-gate-shell-rendering into main
Collaborator

Closes #155.

Summary

  • bot_bottle/git_gate.pygit_gate_render_entrypoint() now calls shlex.quote() on both name and upstream_url before embedding them in the generated sh script, so values containing single quotes, spaces, semicolons, or other shell metacharacters cannot break or inject into the entrypoint.
  • bot_bottle/manifest.pyGitEntry.from_repos_entry() now rejects repo names that do not match [A-Za-z0-9._-]+, making the manifest the first line of defence and shlex.quote() the belt-and-suspenders backstop.
  • tests/unit/test_git_gate.py — regression tests for a single-quoted URL and a URL with spaces/semicolons; the existing test_one_init_repo_call_per_upstream assertion is updated to parse the call via shlex.split rather than string-matching the raw quoted form.
  • tests/unit/test_manifest_git.py — four name-validation tests (', , ;, $ all rejected; my.repo-name_1 accepted).

Changes (1 commit)

  • 0693107 fix(security): harden git_gate.py shell rendering with shlex.quote and name validation
Closes #155. ## Summary - **`bot_bottle/git_gate.py`** — `git_gate_render_entrypoint()` now calls `shlex.quote()` on both `name` and `upstream_url` before embedding them in the generated sh script, so values containing single quotes, spaces, semicolons, or other shell metacharacters cannot break or inject into the entrypoint. - **`bot_bottle/manifest.py`** — `GitEntry.from_repos_entry()` now rejects repo names that do not match `[A-Za-z0-9._-]+`, making the manifest the first line of defence and `shlex.quote()` the belt-and-suspenders backstop. - **`tests/unit/test_git_gate.py`** — regression tests for a single-quoted URL and a URL with spaces/semicolons; the existing `test_one_init_repo_call_per_upstream` assertion is updated to parse the call via `shlex.split` rather than string-matching the raw quoted form. - **`tests/unit/test_manifest_git.py`** — four name-validation tests (`'`, ` `, `;`, `$` all rejected; `my.repo-name_1` accepted). ## Changes (1 commit) - [`0693107`](https://gitea.dideric.is/didericis/bot-bottle/src/commit/0693107dd6a67178e752668ed4f18bb4bdcff184/bot_bottle/git_gate.py) fix(security): harden git_gate.py shell rendering with shlex.quote and name validation
didericis-claude added 7 commits 2026-06-03 00:19:53 -04:00
docs(prd): add git-gate manifest redesign plan
test / unit (pull_request) Successful in 37s
test / integration (pull_request) Successful in 54s
5b26b22a69
PRD 0047 proposes replacing git.remotes with a top-level git-gate.repos
section and snake_case field names to make clear the config is
specifically for git-gate routing, not generic git or SSH config.

Closes #160
docs(prd): consolidate git.user into git-gate per review
test / unit (pull_request) Successful in 38s
test / integration (pull_request) Successful in 53s
02d61e337f
Move git.user under git-gate and remove git as a top-level key
entirely, so all git configuration lives under a single section.
feat(manifest): replace git key with git-gate (PRD 0047)
test / unit (pull_request) Failing after 43s
test / integration (pull_request) Successful in 54s
b7df5b5865
- BOTTLE_KEYS and AGENT_KEYS_OPTIONAL: "git" → "git-gate"
- GitEntry: remove from_dict/from_remote_dict; add from_repos_entry
  parsing url/identity/host_key with repo name as the dict key
- GitUser.from_dict: error messages updated to git-gate.user
- _parse_git_config → _parse_git_gate_config; repos/user subkeys
- Bottle.from_dict: reads git-gate key; "git" key raises a migration error
- Agent.from_dict: reads git-gate key; repos rejected at agent level
- manifest_extends: _child_declares_git_remotes → _child_declares_git_gate_repos
- manifest_loader: threads git-gate frontmatter key into agent_dict
test: update test suite for git-gate manifest redesign (PRD 0047)
test / unit (pull_request) Successful in 37s
test / integration (pull_request) Successful in 55s
58d76a50a6
- fixtures.py: fixture_with_git_dict uses git-gate.repos + url/identity/host_key
- test_manifest_git: rewrite to use git-gate.repos; replace duplicate-name
  test (names = dict keys, always unique) with two-repos-different-hosts test
- test_manifest_git_user: _manifest → git-gate.user; update error message assertions
- test_manifest_agent_git_user: git → git-gate throughout; repos rejection test
- test_manifest_extends: git.remotes/git.user → git-gate.repos/git-gate.user
- test_provision_git: IP test updated — no host alias, single insteadOf
- test_compose: git.remotes → git-gate.repos + new field names
- test_docker_provision_git_user: git.user → git-gate.user
- test_git_gate: inline manifest dict updated to git-gate.repos
- test_smolmachines_provision: git_json → git_gate_json; remove _remote_host
bot-bottle.demo.json: git array → git-gate.repos with url/identity/host_key
examples/agents/implementer.md: git.user → git-gate.user
docs(prd): activate git-gate manifest redesign
test / unit (pull_request) Successful in 40s
test / integration (pull_request) Successful in 55s
9cd2272498
PRD 0047 is now shipped to main.
fix(security): harden git_gate.py shell rendering with shlex.quote and name validation
test / unit (pull_request) Successful in 39s
test / integration (pull_request) Successful in 53s
0693107dd6
Use shlex.quote() on name and upstream_url in git_gate_render_entrypoint()
so special characters (single quotes, spaces, semicolons) cannot break or
inject into the generated sh script.

Add _GIT_NAME_RE validation in GitEntry.from_repos_entry() to restrict
repo names to [A-Za-z0-9._-]+, making the manifest the first line of
defence and shlex.quote() the belt-and-suspenders backstop.

Closes #155
didericis added 1 commit 2026-06-03 00:30:22 -04:00
chore: merge main into harden-git-gate-shell-rendering
test / unit (pull_request) Successful in 34s
test / integration (pull_request) Successful in 43s
062fce5e9a
didericis approved these changes 2026-06-03 00:31:46 -04:00
didericis closed this pull request 2026-06-03 00:36:03 -04:00
didericis deleted branch harden-git-gate-shell-rendering 2026-06-03 00:36:04 -04:00
didericis-claude reopened this pull request 2026-06-03 00:36:43 -04:00
didericis closed this pull request 2026-06-03 00:40:27 -04:00
didericis deleted branch harden-git-gate-shell-rendering 2026-06-03 00:40:28 -04:00
didericis-claude reopened this pull request 2026-06-03 00:40:32 -04:00
didericis-claude closed this pull request 2026-06-03 00:41:26 -04:00
Some checks are pending
test / unit (pull_request) Successful in 35s
test / integration (pull_request) Successful in 44s
test / unit (push) Successful in 32s
test / integration (push) Successful in 41s

Pull request closed

Sign in to join this conversation.