feat: bypass security for health checks and support HEAD downloads
All checks were successful
Build and Publish Docker Image / deploy (push) Successful in 2m30s

- Allow the `/health` endpoint to bypass the security middleware, ensuring container health checks succeed even if the proxy IP is banned.
- Add a test to verify health checks from banned IPs.
- Register a HEAD route for file downloads.
- Refactor admin alert status checks to use a new `isUnacknowledgedAlert` helper.
- Update the security runbook documentation with clearer instructions and examples for trusted proxy configuration.
This commit is contained in:
2026-05-23 19:07:11 +03:00
parent a2c80ac105
commit f0dcdd50ca
10 changed files with 250 additions and 11 deletions

View File

@@ -4,8 +4,10 @@ import (
"archive/zip"
"fmt"
"io"
"mime"
"net/http"
"os"
"strings"
"sync"
"github.com/gin-gonic/gin"
@@ -233,7 +235,8 @@ func (app *App) handleDownloadFile(ctx *gin.Context) {
return
}
if _, err := os.Stat(path); err != nil {
info, err := os.Stat(path)
if err != nil {
ctx.String(http.StatusNotFound, "File not found")
return
}
@@ -242,12 +245,49 @@ func (app *App) handleDownloadFile(ctx *gin.Context) {
return
}
ctx.FileAttachment(path, filename)
if !app.serveDownloadFile(ctx, path, filename, info) {
return
}
if hasManifest && app.config.RenewOnDownloadEnabled {
boxstore.RenewManifest(boxID, manifest.RetentionSecs)
}
}
func (app *App) serveDownloadFile(ctx *gin.Context, path string, filename string, info os.FileInfo) bool {
file, err := os.Open(path)
if err != nil {
ctx.String(http.StatusInternalServerError, "Could not read file")
return false
}
defer file.Close()
mimeType := helpers.MimeTypeForFile(path, filename)
ctx.Header("Content-Type", mimeType)
ctx.Header("Content-Disposition", contentDispositionForDownload(filename, mimeType))
ctx.Header("X-Content-Type-Options", "nosniff")
http.ServeContent(ctx.Writer, ctx.Request, filename, info.ModTime(), file)
return true
}
func contentDispositionForDownload(filename string, mimeType string) string {
disposition := "attachment"
if isEmbeddableMimeType(mimeType) {
disposition = "inline"
}
return mime.FormatMediaType(disposition, map[string]string{"filename": filename})
}
func isEmbeddableMimeType(mimeType string) bool {
baseType := strings.ToLower(strings.TrimSpace(strings.Split(mimeType, ";")[0]))
if strings.HasPrefix(baseType, "video/") || strings.HasPrefix(baseType, "audio/") {
return true
}
if strings.HasPrefix(baseType, "image/") {
return baseType != "image/svg+xml"
}
return baseType == "application/pdf" || baseType == "text/plain"
}
func (app *App) handleDownloadThumbnail(ctx *gin.Context) {
boxID := ctx.Param("id")
fileID := ctx.Param("file_id")