3.5 KiB
3.5 KiB
Security Fixes Log
Tracks remediation progress against findings in SECURITY_AUDIT.md.
C1. Weak JWT Secret — FIXED
Ref: SECURITY_AUDIT.md > C1
Changes:
src/servers/jwt.ts— Added startup guard that throws ifJWT_SECRETis absent or shorter than 32 characters.env.example— Updated placeholder to<generate with: openssl rand -base64 32>
Note: The actual .env secret must be rotated manually per deployment.
C2. Global CORS Wildcard on All API Routes — FIXED
Ref: SECURITY_AUDIT.md > C2
Changes:
src/servers/hono.ts— Replacedorigin: '*'with dynamic origin validation using theALLOWED_ORIGINSallowlist fromorigin-validation.ts
C3. Server-Settings Routes Entirely Unauthenticated — FIXED
Ref: SECURITY_AUDIT.md > C3
Changes:
src/servers/hono.ts— MovedserverSettingsRouterinsideprotectedRoutersrc/servers/api/server-settings/server-settings.ts— Added Super Admin role checks on all write operationssrc/servers/_middlewares/super-admin-middleware.ts— New middleware for Super Admin enforcement- Exempted
GET /api/server-settings/onboarding-completeas public (mounted before auth)
C4. Unauthenticated Dev-Server WebSocket Proxy — FIXED
Ref: SECURITY_AUDIT.md > C4
Changes:
src/servers/api/dev-server/router.ts:- Replaced slug-based proxy URLs with server-generated UUID v4 (
proxyId). Proxy lookup is now by UUID, eliminating cross-user slug collisions. - Added
proxyIdIndexmap for O(1) lookup andpendingStartsguard against duplicate spawns. - JWT validation required on HTML requests (
Accept: text/html) — the iframe entry point. Sub-resources pass on proxyId alone (browsers can't add custom headers to native loads). ?token=query param stripped before forwarding to dev server.proxyOverrideScriptextended to injectAuthorization: Bearerheaders on fetch/XHR and append?token=on WebSocket connections, reading fresh tokens from localStorage.
- Replaced slug-based proxy URLs with server-generated UUID v4 (
src/server.tsx:- WebSocket upgrades require
?token=query param. Token stored inWSData.wsTokenfor deferred async validation in theopenhandler (Bun requires synchronousserver.upgrade()). devServerWebsocket.openvalidates JWT + blacklist check before opening upstream connection. Closes with code4001if invalid.
- WebSocket upgrades require
src/workspaces/officerdev/src/apps/Preview/PreviewProvider.tsx:startServerand status checkuseEffectappend?token=to iframe URL usingclient.token.
Security model: Two-layer capability — proxyId (unguessable UUID) as primary token, JWT as defense-in-depth on entry points (HTML, WebSocket).
C5. AI Chat Messages Rendered with rehype-raw — LLM-Driven XSS — FIXED
Ref: SECURITY_AUDIT.md > C5
Changes:
- Installed
rehype-sanitize(v6) src/workspaces/officerdev/src/apps/Chat/components/MessageBubble.tsx:- Added
rehypeSanitizewith a schema that strips<script>,<iframe>,<object>,<embed>,<form>tags and allon*event handler attributes - Applied to both
ReactMarkdowninstances (assistant messages + streaming bubble) rehype-rawretained so legitimate HTML (tables,<details>, etc.) still renders — sanitized before hitting the DOM
- Added
Remaining
See SECURITY_AUDIT.md for the full list. Next priorities:
- H3 —
rehype-sanitizefor the other 6 Markdown rendering locations - H1/H2 — Move token to
HttpOnlycookies - H7/M5 — URL validation for git-clone/yt-dlp/scrape
- H9/H10 — Rate limiting fixes