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

@ -1,7 +1,9 @@
package handlers
import (
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"fmt"
"mime"
"net/http"
@ -22,12 +24,13 @@ type WebDAVHandler struct {
Handler *webdav.Handler
DB *database.DB
Config *config.Config
Guard *middleware.BruteForceGuard
authCache map[string]time.Time
cacheMu sync.RWMutex
}
func NewWebDAVHandler(db *database.DB, cfg *config.Config) *WebDAVHandler {
func NewWebDAVHandler(db *database.DB, cfg *config.Config, guard *middleware.BruteForceGuard) *WebDAVHandler {
fs := webdav.Dir(cfg.StorageDir)
// Create a custom locking system (in-memory for now, could be DB backed)
@ -48,6 +51,7 @@ func NewWebDAVHandler(db *database.DB, cfg *config.Config) *WebDAVHandler {
Handler: h,
DB: db,
Config: cfg,
Guard: guard,
authCache: make(map[string]time.Time),
}
}
@ -70,7 +74,8 @@ func (h *WebDAVHandler) Handle(c *fiber.Ctx) error {
}
if hasBasicAuth {
cacheKey := user + ":" + pass
hasher := sha256.Sum256([]byte(user + ":" + pass))
cacheKey := hex.EncodeToString(hasher[:])
h.cacheMu.RLock()
expireTime, ok := h.authCache[cacheKey]
@ -81,20 +86,26 @@ func (h *WebDAVHandler) Handle(c *fiber.Ctx) error {
var storedHash string
err := h.DB.QueryRow("SELECT password_hash FROM users WHERE username = ?", user).Scan(&storedHash)
if err != nil || !verifyPassword(pass, storedHash) {
h.Guard.RecordFailure(c.IP())
c.Set("WWW-Authenticate", `Basic realm="Drive WebDAV"`)
return c.SendStatus(fiber.StatusUnauthorized)
}
h.Guard.RecordSuccess(c.IP())
// Cache successful auth for 5 minutes
h.cacheMu.Lock()
h.authCache[cacheKey] = time.Now().Add(5 * time.Minute)
// Simple cache cleanup
for k, v := range h.authCache {
if time.Now().After(v) {
delete(h.authCache, k)
// Bounded cache to prevent DoS
if len(h.authCache) >= 1000 {
now := time.Now()
for k, v := range h.authCache {
if now.After(v) {
delete(h.authCache, k)
}
}
}
if len(h.authCache) < 1000 {
h.authCache[cacheKey] = time.Now().Add(5 * time.Minute)
}
h.cacheMu.Unlock()
}
} else if c.Locals("userID") == nil {