screentinker/server/test
ScreenTinker 401c4b00b5 fix(security): sanitize public widget render to close stored XSS
The public, CSP-exempt widget render (GET /api/widgets/:id/render) inlined
config values straight into <style>/CSS and (for the text widget) raw into the
same-origin document. A workspace editor could store `}</style><script>...` in a
color/background/size field (bypassing the UI pickers via the API) → stored XSS
executing in the app origin for anyone who opens the render URL (JWT theft).

- safeCss(): allow colors/gradients but reject CSS breakout / url() / @import /
  expression / javascript:. Applied to background/color across clock, weather,
  rss, social renders.
- safeNumber(): coerce font_size / scroll_speed / max_items to a finite number
  so they can't smuggle markup.
- Text widget keeps its intentional raw HTML/CSS feature, but it now renders
  inside an <iframe sandbox="allow-scripts"> (NO allow-same-origin) - scripts run
  in a null origin that can't reach the dashboard's localStorage/JWT.

Tests: test/widget-render-xss.test.js (breakout rejected, numbers coerced, text
isolated, legit colors/gradients preserved). Full suite green.
2026-06-08 19:11:14 -05:00
..
admin-users.test.js feat(admin): manage a user's workspace memberships (multi + per-workspace role) 2026-06-08 16:24:52 -05:00
branding.test.js feat(branding): instance-level default white-label branding (#15) 2026-06-08 16:55:22 -05:00
operator-permissions.test.js fix(roles): make platform_operator assignable + add deny/assign regression tests 2026-06-05 12:44:39 -05:00
security-fixes.test.js fix(security): patch quick-win findings from the codebase review 2026-06-08 19:02:19 -05:00
tenant-cascade-migration.test.js fix(db): cascade tenant resources on workspace/org delete (#18 follow-up) 2026-06-08 16:01:52 -05:00
user-deletion.test.js fix(admin): user deletion failed with FOREIGN KEY constraint (#18) 2026-06-08 10:51:32 -05:00
widget-render-xss.test.js fix(security): sanitize public widget render to close stored XSS 2026-06-08 19:11:14 -05:00