Inital build
Some checks failed
Automated Container Build / build-and-push (push) Failing after 12s

This commit is contained in:
Elijah 2026-05-22 12:29:43 -07:00
parent fa2be029a2
commit 724d70e58b
3339 changed files with 1075535 additions and 0 deletions

View file

@ -0,0 +1,68 @@
package middleware
import (
"fmt"
"path/filepath"
"strings"
"github.com/gofiber/fiber/v2"
)
// PathJail middleware ensures all file path parameters are confined within
// the storage root. Any path that resolves outside the jail is rejected
// immediately, preventing directory traversal attacks.
func PathJail(storageRoot string) fiber.Handler {
// Resolve the absolute jail root once at startup
absRoot, err := filepath.Abs(storageRoot)
if err != nil {
panic(fmt.Sprintf("pathjail: invalid storage root: %v", err))
}
// Ensure it ends with separator for prefix matching
absRootSlash := absRoot + string(filepath.Separator)
return func(c *fiber.Ctx) error {
// Extract the path parameter from the request.
// Handlers attach the relative file path as "filepath" param or query.
rawPath := c.Params("*")
if rawPath == "" {
rawPath = c.Query("path", "")
}
// If no path param, assume root path '.'
if rawPath == "" {
rawPath = "."
}
// Clean and resolve the path
cleaned := filepath.Clean(rawPath)
// Reject obvious traversal attempts before even joining
if strings.Contains(cleaned, "..") {
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{
"error": "path traversal detected",
})
}
// Build the full absolute path within the jail
fullPath := filepath.Join(absRoot, cleaned)
absPath, err := filepath.Abs(fullPath)
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": "invalid path",
})
}
// Final check: resolved path must be within the jail root
if absPath != absRoot && !strings.HasPrefix(absPath, absRootSlash) {
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{
"error": "access denied: path outside storage boundary",
})
}
// Store the validated absolute path for downstream handlers
c.Locals("resolvedPath", absPath)
c.Locals("relativePath", cleaned)
return c.Next()
}
}