You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi team 👋 — this issue is a friendly follow-up to PR #11.
PR #11 hardened the real-time presence channel so the "Currently Being Consulted" panel no longer trusts untrusted payload text and now resolves titles from server-owned data.
Objective
Complete broader XSS hardening (and close remaining injection-adjacent gaps) across user-controlled content paths, while keeping the current UI behavior intact.
Concrete implementation plan
1) Inventory and triage all user-input sinks (quick pass)
Enumerate every request/response path that accepts user input (query params, bodies, route params, WS messages).
Map each path to the DOM sink:
Raw HTML injection points (dangerouslySetInnerHTML, HTML parsing/rewrite output)
No newly introduced regressions in existing user flows (comments, article read, search, sidebar).
Notes
If this helps, I can split the above into milestone-sized PRs (ex: #A sanitizer hardening, #B comment validation, #C headers/CSP). That usually keeps review faster and safer.
Summary
Hi team 👋 — this issue is a friendly follow-up to PR #11.
PR #11 hardened the real-time presence channel so the
"Currently Being Consulted"panel no longer trusts untrusted payload text and now resolves titles from server-owned data.Objective
Complete broader XSS hardening (and close remaining injection-adjacent gaps) across user-controlled content paths, while keeping the current UI behavior intact.
Concrete implementation plan
1) Inventory and triage all user-input sinks (quick pass)
dangerouslySetInnerHTML, HTML parsing/rewrite output){value},setState+ render)Low / Medium / Highrisk and prioritize fixes.2) Comments path: input validation + output encoding
Goal: comments body/content stays text-safe and cannot break out of React render context.
Files likely involved:
src/worker/comments.tssrc/client/Comments.tsxChecklist:
body(and any other user-provided fields).<,>,on*=/javascript:in server-side validation (at minimum log + hard reject, or escape strategy for legacy compatibility).<img src=x onerror=alert(1)>andjavascript:links.3) Sidebar/presence and title surfaces
Goal: preserve PR #11 trust boundary and lock down any remaining title/title-like paths.
{ t: "r", s }.toppayload titles are only sourced from trusted metadata/fallback.src/worker/presence.tsthat rejects absurdly long/empty slugs post-slugify.tiout of any inbound message contract definitions/docs.4) Link/title metadata hardening for rendered HTML
Files:
src/worker/sanitize.tsChecklist:
javascript:,data:,vbscript:, protocol-relative, and uppercase variants in hrefs.'consistently where relevant.5) Route/query handling sanity checks
Files:
src/client/App.tsxsrc/worker/index.ts(search/page handlers)slug/qdirectlyChecklist:
slugify/query normalization path is applied before any cache/db/file-system/identifier usage.title, or DOM attributes.6) Transport-layer hardening
Content-Security-Policyand related safe-response headers (as practical for this app/Cloudflare setup).X-Content-Type-Options: nosniffand frame protection headers are set consistently.noopenerlinks where external targets are used.7) Verification pass (acceptance checklist)
Acceptance criteria
"Currently Being Consulted"remains stable and trusted (as in PR Harden presence titles using server-owned metadata #11).Notes
If this helps, I can split the above into milestone-sized PRs (ex: #A sanitizer hardening, #B comment validation, #C headers/CSP). That usually keeps review faster and safer.