security(review): fix invite bypass via smuggled seed flag, login rate limit, server-side logout, attachment preview XSS hardening

- /auth/register: strip client-supplied seed flag (PoC confirmed it bypassed
  invite code, MAX_USERS quota AND first-user auto-admin, granting admin
  without any credential); demo-rebuild internal path unaffected
- /auth/login: per-IP+username of 5 consecutive failures gets a 10-minute
  cooldown against in-memory counter (brute-force guard)
- /auth/logout: new endpoint revokes the current Bearer token server-side;
  frontend calls it (best-effort) before local clearToken on sidebar logout
- attachment docx/xlsx preview: sanitize generated HTML (strip scripts,
  event handlers, dangerous protocols) before dangerouslySetInnerHTML
  render, preventing token theft via malicious previewed documents

PoC suite: seed smuggling rejected, 429 on 6th login attempt, token dead
after logout, per-user isolation intact (403/401/404 as before);
integration 61/61 green
This commit is contained in:
root
2026-10-17 21:18:55 +08:00
parent 3613b9f5e1
commit 17ab5f0390
20 changed files with 416 additions and 358 deletions
@@ -0,0 +1,16 @@
import{c as t}from"./index-DuP8O2p4.js";/**
* @license lucide-react v0.475.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const e=[["path",{d:"m9 18 6-6-6-6",key:"mthhwq"}]],c=t("ChevronRight",e);/**
* @license lucide-react v0.475.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const a=[["path",{d:"M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2",key:"143wyd"}],["path",{d:"M6 9V3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v6",key:"1itne7"}],["rect",{x:"6",y:"14",width:"12",height:"8",rx:"1",key:"1ue0tg"}]],n=t("Printer",a);/**
* @license lucide-react v0.475.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const o=[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]],i=t("RotateCcw",o);export{c as C,n as P,i as R};