chore: implement Phase 1 and 2 security remediations
Some checks failed
Automated Container Build / build-and-push (push) Has been cancelled

This commit is contained in:
Elijah 2026-05-26 13:32:09 -07:00
parent 82731e93b1
commit 701766b611
14 changed files with 213 additions and 55 deletions

View file

@ -3,6 +3,7 @@ package handlers
import (
"archive/zip"
"bufio"
"context"
"database/sql"
"encoding/json"
"fmt"
@ -293,12 +294,22 @@ func (h *FSHandler) GetExtendedFileInfo(c *fiber.Ctx) error {
// For files, attempt to get media metadata
cat := categorizeFile(filepath.Ext(info.Name()))
if cat == "images" || cat == "videos" || cat == "audio" {
cmd := exec.Command("exiftool", "-json", "--", resolvedPath)
output, err := cmd.Output()
if err == nil {
var meta []map[string]interface{}
if err := json.Unmarshal(output, &meta); err == nil && len(meta) > 0 {
fi.Metadata = meta[0]
ext := strings.ToLower(filepath.Ext(info.Name()))
validExts := map[string]bool{
".jpg": true, ".jpeg": true, ".png": true, ".gif": true, ".webp": true,
".mp4": true, ".mov": true, ".webm": true, ".mkv": true,
".mp3": true, ".wav": true, ".flac": true, ".m4a": true,
}
if validExts[ext] {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
cmd := exec.CommandContext(ctx, "exiftool", "-json", "--", resolvedPath)
output, err := cmd.Output()
if err == nil {
var meta []map[string]interface{}
if err := json.Unmarshal(output, &meta); err == nil && len(meta) > 0 {
fi.Metadata = meta[0]
}
}
}
}
@ -548,9 +559,9 @@ func (h *FSHandler) Delete(c *fiber.Ctx) error {
}
// Remove both potential locations to be safe
os.RemoveAll(resolvedPath)
safeRemovePath(h.Config.StorageDir, resolvedPath)
if relativePath != "." {
os.RemoveAll(trashPath)
safeRemovePath(h.Config.TrashDir, trashPath)
}
cleanPath := filepath.ToSlash(relativePath)
@ -584,7 +595,7 @@ func (h *FSHandler) Delete(c *fiber.Ctx) error {
if err := copyFile(resolvedPath, trashPath); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "failed to move to trash"})
}
os.RemoveAll(resolvedPath)
safeRemovePath(h.Config.StorageDir, resolvedPath)
}
// Update DB
@ -691,7 +702,7 @@ func (h *FSHandler) RestoreFromTrash(c *fiber.Ctx) error {
if err := copyFile(trashPath, destFull); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "failed to restore file"})
}
os.RemoveAll(trashPath)
safeRemovePath(h.Config.TrashDir, trashPath)
}
h.DB.Exec("UPDATE files SET path = ?, name = ?, is_trashed = 0, trashed_at = NULL WHERE path = ?", originalPath, filepath.Base(originalPath), body.Path)
@ -715,10 +726,15 @@ func (h *FSHandler) RestoreFromTrash(c *fiber.Ctx) error {
// EmptyTrash permanently deletes all trashed items.
// DELETE /api/trash
func (h *FSHandler) EmptyTrash(c *fiber.Ctx) error {
if err := os.RemoveAll(h.Config.TrashDir); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "failed to empty trash"})
if err := safeRemovePath(h.Config.TrashDir, h.Config.TrashDir); err != nil {
// safeRemovePath blocks deleting the root directory, so we just clear its contents instead
entries, err := os.ReadDir(h.Config.TrashDir)
if err == nil {
for _, e := range entries {
os.RemoveAll(filepath.Join(h.Config.TrashDir, e.Name()))
}
}
}
os.MkdirAll(h.Config.TrashDir, 0755)
h.DB.Exec("DELETE FROM files WHERE is_trashed = 1")
h.DB.AddAuditLog("emptied_trash", "User emptied trash", c.IP())