Skip to content

Commit 6ba37d0

Browse files
fix: Potential fix for code scanning alert no. 14: Uncontrolled data used in path expression (#11)
* Potential fix for code scanning alert no. 14: Uncontrolled data used in path expression Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * fix: address review comments on safePath - skip empty segments and reuse resolved baseDir --------- Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
1 parent e23c787 commit 6ba37d0

1 file changed

Lines changed: 21 additions & 7 deletions

File tree

internal/services/s3/store.go

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,22 +44,36 @@ func validPathComponent(part string) error {
4444
// escape the base directory. It returns an error on path traversal attempts.
4545
// All components must be single path segments (no separators).
4646
func (fs *FileStore) safePath(parts ...string) (string, error) {
47-
joined := filepath.Join(append([]string{fs.baseDir}, parts...)...)
48-
cleaned := filepath.Clean(joined)
49-
50-
// Resolve symlinks if the candidate path exists; otherwise use cleaned.
51-
candidate := cleaned
52-
if resolved, err := filepath.EvalSymlinks(cleaned); err == nil {
47+
cleanParts := make([]string, 0, len(parts))
48+
for _, part := range parts {
49+
if part == "" {
50+
continue
51+
}
52+
if filepath.IsAbs(part) {
53+
return "", fmt.Errorf("absolute path segment not allowed: %s", part)
54+
}
55+
cleanPart := filepath.Clean(part)
56+
if cleanPart == ".." || strings.HasPrefix(cleanPart, ".."+string(filepath.Separator)) {
57+
return "", fmt.Errorf("path traversal detected in segment: %s", part)
58+
}
59+
cleanParts = append(cleanParts, cleanPart)
60+
}
61+
62+
candidate := filepath.Join(append([]string{fs.baseDir}, cleanParts...)...)
63+
64+
// Resolve symlinks if the candidate path exists; otherwise use the joined path.
65+
if resolved, err := filepath.EvalSymlinks(candidate); err == nil {
5366
candidate = resolved
5467
}
5568

5669
rel, err := filepath.Rel(fs.baseDir, candidate)
5770
if err != nil {
5871
return "", fmt.Errorf("resolve relative path: %w", err)
5972
}
60-
if rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator)) {
73+
if rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator)) || filepath.IsAbs(rel) {
6174
return "", fmt.Errorf("path traversal detected: %s", candidate)
6275
}
76+
6377
return candidate, nil
6478
}
6579

0 commit comments

Comments
 (0)