fix(security): demo sends nothing, hidden SMTP password, body limits (FLAW-33..38)
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m52s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m52s
- 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>
This commit is contained in:
1 parent
3709282a4f
commit
9d9698186c
21 files changed
+631
-304
No files matched your search
@@ -0,0 +1,42 @@
|
||||
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))
|
||||
}
|
||||
Reference in new issue
Block a user