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
+13
-12
@@ -51,12 +51,12 @@ func NewServer(cfg *config.Config, store *storage.Store, wsHub *ws.Hub, staticFS
|
||||
store.OnTaskCreated = func(th *domain.Thought) {
|
||||
srv.wsHub.BroadcastToUsers(srv.taskAudience(th), "TASK_CREATED", th)
|
||||
}
|
||||
go srv.startAlarmTicker()
|
||||
go srv.startCompaction()
|
||||
if cfg.DemoMode && cfg.DemoResetMinutes > 0 {
|
||||
go srv.startDemoResetTicker()
|
||||
}
|
||||
if !cfg.DemoMode {
|
||||
go srv.startAlarmTicker() // the demo sends nothing (FLAW-33)
|
||||
go srv.startBackupScheduler()
|
||||
}
|
||||
return srv
|
||||
@@ -84,6 +84,7 @@ func (s *Server) Router() http.Handler {
|
||||
|
||||
r.Use(s.clientIPMiddleware)
|
||||
r.Use(s.securityHeaders)
|
||||
r.Use(bodyLimit)
|
||||
r.Use(s.demoResetGate)
|
||||
r.Use(middleware.Recoverer)
|
||||
r.Use(s.apiLoggingMiddleware)
|
||||
@@ -126,11 +127,11 @@ func (s *Server) Router() http.Handler {
|
||||
r.Post("/api/v1/events/rooms", s.handleSSERooms)
|
||||
r.Post("/api/v1/auth/stream-ticket", s.handleStreamTicket)
|
||||
r.Get("/api/v1/auth/sessions", s.handleListSessions)
|
||||
r.Delete("/api/v1/auth/sessions/{id}", s.handleEndSession)
|
||||
r.Delete("/api/v1/auth/sessions/{id}", s.notInDemo(s.handleEndSession))
|
||||
r.Post("/api/v1/auth/logout", s.handleLogout)
|
||||
r.Post("/api/v1/auth/revoke-all", s.handleRevokeAllSessions)
|
||||
r.Post("/api/v1/auth/revoke-all", s.notInDemo(s.handleRevokeAllSessions))
|
||||
r.Patch("/api/v1/auth/settings", s.handleUpdateUserSettings)
|
||||
r.Post("/api/v1/auth/alarms/test", s.handleTestUserAlarm)
|
||||
r.Post("/api/v1/auth/alarms/test", s.notInDemo(s.handleTestUserAlarm))
|
||||
r.Get("/api/v1/users/directory", s.handleGetUsersDirectory)
|
||||
r.Get("/api/v1/collaborators", s.handleGetCollaborators)
|
||||
r.Get("/api/v1/stats", s.handleStats)
|
||||
@@ -142,7 +143,7 @@ func (s *Server) Router() http.Handler {
|
||||
r.Get("/api/v1/export/markdown", s.handleExportMarkdown)
|
||||
r.Post("/api/v1/import/mindsift", s.handleImportMindSift)
|
||||
r.Delete("/api/v1/user/data", s.handlePurgeOwnData)
|
||||
r.Delete("/api/v1/user/account", s.handleDeleteOwnAccount)
|
||||
r.Delete("/api/v1/user/account", s.notInDemo(s.handleDeleteOwnAccount))
|
||||
r.Post("/api/v1/import/obsidian", s.handleImportObsidian)
|
||||
r.Get("/api/v1/themes", s.handleGetThemes)
|
||||
r.Post("/api/v1/themes", s.handleSaveTheme)
|
||||
@@ -251,10 +252,10 @@ func (s *Server) Router() http.Handler {
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(s.staffMiddleware)
|
||||
r.Get("/api/v1/admin/users", s.handleAdminGetUsers)
|
||||
r.Post("/api/v1/admin/users", s.handleAdminCreateUser)
|
||||
r.Patch("/api/v1/admin/users/{id}", s.handleAdminUpdateUser)
|
||||
r.Put("/api/v1/admin/users/{id}/password", s.handleAdminResetPassword)
|
||||
r.Delete("/api/v1/admin/users/{id}", s.handleAdminDeleteUser)
|
||||
r.Post("/api/v1/admin/users", s.notInDemo(s.handleAdminCreateUser))
|
||||
r.Patch("/api/v1/admin/users/{id}", s.notInDemo(s.handleAdminUpdateUser))
|
||||
r.Put("/api/v1/admin/users/{id}/password", s.notInDemo(s.handleAdminResetPassword))
|
||||
r.Delete("/api/v1/admin/users/{id}", s.notInDemo(s.handleAdminDeleteUser))
|
||||
|
||||
r.Get("/api/v1/admin/invites", s.handleAdminGetInvites)
|
||||
r.Post("/api/v1/admin/invites", s.handleAdminCreateInvite)
|
||||
@@ -266,9 +267,9 @@ func (s *Server) Router() http.Handler {
|
||||
r.Use(s.adminMiddleware)
|
||||
r.Get("/api/v1/admin/settings", s.handleAdminGetSettings)
|
||||
r.Get("/api/v1/admin/backups", s.handleAdminListBackups)
|
||||
r.Post("/api/v1/admin/backups", s.handleAdminRunBackup)
|
||||
r.Post("/api/v1/admin/backups", s.notInDemo(s.handleAdminRunBackup))
|
||||
r.Get("/api/v1/admin/backups/{name}", s.handleAdminDownloadBackup)
|
||||
r.Put("/api/v1/admin/settings", s.handleAdminUpdateSettings)
|
||||
r.Put("/api/v1/admin/settings", s.notInDemo(s.handleAdminUpdateSettings))
|
||||
r.Get("/api/v1/admin/settings/sharing-impact", s.handleAdminSharingImpact)
|
||||
|
||||
// Organizations decide who can see whom; only server admins manage them
|
||||
@@ -277,7 +278,7 @@ func (s *Server) Router() http.Handler {
|
||||
r.Put("/api/v1/admin/organizations/{id}", s.handleAdminRenameOrganization)
|
||||
r.Delete("/api/v1/admin/organizations/{id}", s.handleAdminDeleteOrganization)
|
||||
r.Put("/api/v1/admin/users/{id}/organization", s.handleAdminSetUserOrganization)
|
||||
r.Post("/api/v1/admin/smtp/test", s.handleAdminTestSMTP)
|
||||
r.Post("/api/v1/admin/smtp/test", s.notInDemo(s.handleAdminTestSMTP))
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Reference in new issue
Block a user