feat(security): use bcrypt hashes and safe paths for boxes

- Replace legacy salted password hashing with bcrypt and store hash alg
- Accept existing bcrypt hashes while keeping legacy verification fallback
- Validate box IDs and use SafeChildPath for box/file operations to prevent traversal
- Refactor download flow to share zip writer logic and correctly handle one-time deletes and optional renew-on-download only after a successful zip writefeat(security): use bcrypt hashes and safe paths for boxes

- Replace legacy salted password hashing with bcrypt and store hash alg
- Accept existing bcrypt hashes while keeping legacy verification fallback
- Validate box IDs and use SafeChildPath for box/file operations to prevent traversal
- Refactor download flow to share zip writer logic and correctly handle one-time deletes and optional renew-on-download only after a successful zip write
This commit is contained in:
2026-04-28 21:42:36 +03:00
parent a5d6d69be0
commit cb026d4fd1
15 changed files with 545 additions and 68 deletions

View File

@@ -14,8 +14,19 @@ func SafeFilename(name string) (string, bool) {
}
func SafeChildPath(parent string, filename string) (string, bool) {
path := filepath.Join(parent, filename)
return path, strings.HasPrefix(path, parent+string(filepath.Separator))
parent = filepath.Clean(parent)
filename = strings.TrimSpace(filename)
if parent == "" || filename == "" || filepath.IsAbs(filename) {
return "", false
}
path := filepath.Clean(filepath.Join(parent, filename))
relative, err := filepath.Rel(parent, path)
if err != nil || relative == "." || strings.HasPrefix(relative, ".."+string(filepath.Separator)) || relative == ".." {
return "", false
}
return path, true
}
func UniqueFilename(directory string, filename string) string {