getCustomBuildDir allows GIT_CLONE_PATH values outside of `builds_dir`
Summary
Follow-up to https://gitlab.com/gitlab-org/gitlab-runner/-/issues/25840#note_368297037
The Build.getCustomBuildDir
method has a simple check to guarantee that the custom build directory lies within builds_dir
. However since it is made with strings.HasPrefix
, the check will succeed for the scenario where builds_dir
=/builds
and GIT_CLONE_PATH
= e.g. /builds/../home/user
.
Steps to reproduce
.gitlab-ci.yml
image: alpine:latest
variables:
GIT_CLONE_PATH: /tmp/builds/../clone
stages:
- setup
start_evaluation:
stage: setup
script:
- date > .date
- echo Done
Actual behavior
https://gitlab.com/pedropombeiro/playground/-/jobs/617930121
/bin/bash: line 95: cd: /tmp/builds/../clone: No such file or directory
ERROR: Job failed: exit code 1
Expected behavior
https://gitlab.com/pedropombeiro/playground/-/jobs/617934164
ERROR: Failed to remove network for build
ERROR: Job failed: the GIT_CLONE_PATH="/tmp/builds/../clone" has to be within "/tmp/builds"
Relevant logs and/or screenshots
Environment description
config.toml contents
[[runners]]
executor = "docker"
builds_dir = "/tmp/builds"
[runners.custom_build_dir]
enabled = true
Used GitLab Runner version
Possible fixes
The HasPrefix()
logic is susceptible to a ../
path walking abuse, so the code should probably be changed to something like:
relDir, err := filepath.Rel(rootDir, dir)
if err != nil || strings.HasPrefix(relDir, "..") {
return "", MakeBuildError("the %s=%q has to be within %q", overrideKey, dir, rootDir)
}