Files
MindSift/internal/api/bodylimit.go
T
sandrodachandClaude Opus 5.5 9d9698186c
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m52s
fix(security): demo sends nothing, hidden SMTP password, body limits (FLAW-33..38)
- Demo: senders for mail, Discord and webhooks refuse, no alarm ticker;
  test alarm, SMTP test, server settings, backups, account and session
  changes of the shared demo accounts answer 403; the session list only
  shows the own device. The UI shows the notices and disables the controls.
- SMTP password is never sent back (smtpPassSet), empty keeps it.
- ?token= on webhook ingest accepts only API keys.
- Request bodies capped at 2 MB (sync 8 MB, imports 101 MB).
- Deleting an account removes its server backups.
- Backup downloads, exports and import uploads get 30 minutes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 19:43:23 +01:00

43 lines
1.3 KiB
Go

package api
import (
"net/http"
"strings"
"time"
"github.com/sandrodach/mindsift/internal/storage"
)
// Request bodies are capped for every endpoint (FLAW-36), so a session or API key cannot tie up memory
// with huge uploads. Note sync and imports need more; their handlers apply the same limits again.
const defaultMaxBody = 2 << 20
func bodyLimitFor(path string) int64 {
switch {
case strings.HasPrefix(path, "/api/v1/import/"):
return storage.MaxImportUploadBytes + 1<<20
case strings.HasPrefix(path, "/api/v1/docs/") && strings.HasSuffix(path, "/sync"):
return syncMaxBody
}
return defaultMaxBody
}
func bodyLimit(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Body != nil && r.Body != http.NoBody {
r.Body = http.MaxBytesReader(w, r.Body, bodyLimitFor(r.URL.Path))
}
next.ServeHTTP(w, r)
})
}
// The server gives every request 15 s to send its body and 30 s for the answer. Whole archives on a slow
// line need longer: downloads of backups and exports, uploads of imports (FLAW-38).
const longTransferTime = 30 * time.Minute
func allowLongTransfer(w http.ResponseWriter) {
rc := http.NewResponseController(w)
_ = rc.SetWriteDeadline(time.Now().Add(longTransferTime))
_ = rc.SetReadDeadline(time.Now().Add(longTransferTime))
}