|
1 | 1 | package config |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "errors" |
4 | 5 | "log/slog" |
5 | 6 | "os" |
| 7 | + "path/filepath" |
6 | 8 | "strconv" |
7 | 9 | "strings" |
8 | 10 | "time" |
@@ -132,10 +134,41 @@ func getEnvFloat32(key string, fallback float32) float32 { |
132 | 134 | return float32(f) |
133 | 135 | } |
134 | 136 |
|
| 137 | +func validateCredentialsFilePath(path string) (string, error) { |
| 138 | + path = strings.TrimSpace(path) |
| 139 | + if path == "" { |
| 140 | + return "", errors.New("empty credentials file path") |
| 141 | + } |
| 142 | + if strings.Contains(path, "..") { |
| 143 | + return "", errors.New("credentials file path must not contain parent segments") |
| 144 | + } |
| 145 | + clean := filepath.Clean(path) |
| 146 | + if !filepath.IsAbs(clean) { |
| 147 | + return "", errors.New("credentials file path must be absolute") |
| 148 | + } |
| 149 | + return clean, nil |
| 150 | +} |
| 151 | + |
135 | 152 | func loadRegistryCredentialsFromEnv() map[string]registryauth.Credential { |
136 | | - filePath := strings.TrimSpace(os.Getenv("HELM_WATCH_REGISTRY_CREDENTIALS_FILE")) |
137 | | - if filePath != "" { |
138 | | - data, err := os.ReadFile(filePath) |
| 153 | + rawPath := strings.TrimSpace(os.Getenv("HELM_WATCH_REGISTRY_CREDENTIALS_FILE")) |
| 154 | + if rawPath != "" { |
| 155 | + filePath, err := validateCredentialsFilePath(rawPath) |
| 156 | + if err != nil { |
| 157 | + slog.Warn("registry credentials file path invalid", "path", rawPath, "error", err) |
| 158 | + return nil |
| 159 | + } |
| 160 | + dir, name := filepath.Split(filePath) |
| 161 | + if name == "" || name == "." || name == ".." { |
| 162 | + slog.Warn("registry credentials file path invalid", "path", filePath, "error", "invalid file name") |
| 163 | + return nil |
| 164 | + } |
| 165 | + root, err := os.OpenRoot(dir) |
| 166 | + if err != nil { |
| 167 | + slog.Warn("registry credentials file not loaded", "path", filePath, "error", err) |
| 168 | + return nil |
| 169 | + } |
| 170 | + defer func() { _ = root.Close() }() |
| 171 | + data, err := root.ReadFile(name) |
139 | 172 | if err != nil { |
140 | 173 | slog.Warn("registry credentials file not loaded", "path", filePath, "error", err) |
141 | 174 | return nil |
|
0 commit comments