SafeFilename returns a safe filename based on the given name. - Using filepath.Base and filepath.ToSlash: This ensures that only the base file name is used, without any directory components, and converts all separators to slashes. This is a good practice to prevent directory traversal. - Regular Exp
(prefixDir string, name string)
| 2399 | // |
| 2400 | // It returns the safe prefix directory (destination directory), the safe filename, a boolean indicating whether the filename is safe, and an error if any. |
| 2401 | func SafeFilename(prefixDir string, name string) (string, string, bool, error) { |
| 2402 | // Security fix for go < 1.17.5: |
| 2403 | // Reported by Kirill Efimov (snyk.io) through security reports. |
| 2404 | filename := filepath.Base(filepath.ToSlash(name)) |
| 2405 | |
| 2406 | // CWE-99. |
| 2407 | |
| 2408 | // Sanitize the user input by using a regular expression |
| 2409 | // and an allowlist of valid extensions |
| 2410 | isValidFilename := ValidFilenameRegexp.MatchString(filename) |
| 2411 | if !isValidFilename { |
| 2412 | // Reject the input as it is invalid or unsafe. |
| 2413 | return prefixDir, name, false, nil |
| 2414 | } |
| 2415 | |
| 2416 | if ValidExtensionRegexp != nil && !ValidExtensionRegexp.MatchString(filename) { |
| 2417 | // Reject the input as it is invalid or unsafe. |
| 2418 | return prefixDir, name, false, nil |
| 2419 | } |
| 2420 | |
| 2421 | var destPath string |
| 2422 | if prefixDir != "" { |
| 2423 | // Join the sanitized input with the destination directory. |
| 2424 | destPath = filepath.Join(prefixDir, filename) |
| 2425 | |
| 2426 | // Get the canonical path of the destination directory. |
| 2427 | canonicalDestDir, err := filepath.EvalSymlinks(prefixDir) // the prefix dir should exists. |
| 2428 | if err != nil { |
| 2429 | return prefixDir, name, false, fmt.Errorf("dest directory: %s: eval symlinks: %w", prefixDir, err) |
| 2430 | } |
| 2431 | |
| 2432 | // Check if the destination path is within the destination directory. |
| 2433 | if !strings.HasPrefix(destPath, canonicalDestDir) { |
| 2434 | // Reject the input as it is a path traversal attempt. |
| 2435 | return prefixDir, name, false, nil |
| 2436 | } |
| 2437 | } |
| 2438 | |
| 2439 | return destPath, filename, true, nil |
| 2440 | } |
| 2441 | |
| 2442 | // UploadFormFiles uploads any received file(s) from the client |
| 2443 | // to the system physical location "destDirectory". |
no test coverage detected
searching dependent graphs…