safe-path.go 871 B

1234567891011121314151617181920212223242526272829
  1. package storage
  2. import (
  3. "errors"
  4. "path/filepath"
  5. "strings"
  6. )
  7. // Get the first file path component. We can't use filepath.Split because that breaks off the last
  8. // one. We could optimize this to avoid allocating a slice down the track.
  9. func firstComponent(filePath string) string {
  10. return strings.SplitN(filePath, string(filepath.Separator), 2)[0]
  11. }
  12. // Combines file info path components, ensuring the result won't escape into parent directories.
  13. func ToSafeFilePath(fileInfoComponents ...string) (string, error) {
  14. safeComps := make([]string, 0, len(fileInfoComponents))
  15. for _, comp := range fileInfoComponents {
  16. safeComps = append(safeComps, filepath.Clean(comp))
  17. }
  18. safeFilePath := filepath.Join(safeComps...)
  19. fc := firstComponent(safeFilePath)
  20. switch fc {
  21. case "..":
  22. return "", errors.New("escapes root dir")
  23. default:
  24. return safeFilePath, nil
  25. }
  26. }