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

@@ -140,7 +140,15 @@ func canGenerateThumbnail(file models.BoxFile) bool {
}
func generateThumbnail(task thumbnailTask) error {
source, err := os.Open(filepath.Join(BoxPath(task.BoxID), task.Name))
sourcePath, ok := SafeBoxFilePath(task.BoxID, task.Name)
if !ok {
return os.ErrInvalid
}
if err := ensureRegularFile(sourcePath); err != nil {
return err
}
source, err := os.Open(sourcePath)
if err != nil {
return err
}
@@ -161,15 +169,28 @@ func generateThumbnail(task thumbnailTask) error {
return os.ErrInvalid
}
target, err := os.Create(path)
target, tempPath, err := createTempSibling(path)
if err != nil {
return err
}
defer target.Close()
committed := false
defer func() {
target.Close()
if !committed {
os.Remove(tempPath)
}
}()
if err := jpeg.Encode(target, thumb, &jpeg.Options{Quality: 82}); err != nil {
return err
}
if err := target.Close(); err != nil {
return err
}
if err := os.Rename(tempPath, path); err != nil {
return err
}
committed = true
return markThumbnailReady(task.BoxID, task.FileID)
}