Skip to content

Security: nishantkluhera/CodeQuorum

Security

SECURITY.md

Security

CodeQuorum is a real-time collaborative editor that also runs user-supplied code and renders user-supplied HTML/Markdown. That makes its trust boundaries the most important part of its design. This document is the threat model and the controls that address it.

Trust boundaries

Boundary Untrusted input Risk
HTTP API request bodies, cookies injection, auth bypass, brute force
WebSocket Yjs/awareness binary, room id unauthorized edits, access to private rooms
Code runner a JS file's contents arbitrary code execution
Live preview an HTML file's contents XSS, navigation/network abuse
Notebook/Markdown render markdown from any collaborator stored XSS

Controls

Authentication & sessions

  • Passwords hashed with scrypt (node:crypto) using a per-user random salt; verified with crypto.timingSafeEqual to avoid timing leaks.
  • Sessions are JWTs in an httpOnly, SameSite=Lax cookie (Secure in production). JS never touches the token.
  • JWT_SECRET is required in production — the server refuses to boot with a default secret when NODE_ENV=production.

Authorization (enforced server-side)

  • Room roles are resolved on the server (repo.effectiveRole): owner / editor / viewer / no-access.
  • Private rooms reject non-members at the socket layer (access-denied); the client UI is never trusted to gate this.
  • Read-only is enforced on the server: y-update events from a viewer are dropped, not merely disabled in the UI.

Input validation & data access

  • All API bodies are validated with zod before use; failures return 400 with no DB contact.
  • Every SQL statement is parameterized (prepared statements in repo.js) — no string interpolation of user input, so the data layer is injection-safe by construction.
  • Auth endpoints are rate-limited (express-rate-limit); the whole API has a global limit.

Transport & headers

  • helmet sets Content-Security-Policy, Strict-Transport-Security, X-Content-Type-Options: nosniff, X-Frame-Options: SAMEORIGIN, Referrer-Policy, and removes X-Powered-By.
  • CSP uses script-src 'self' 'wasm-unsafe-eval' (no inline app scripts — they are external files; 'wasm-unsafe-eval' permits only WebAssembly compilation for the self-hosted Python runtime, not arbitrary JS eval), object-src 'none', base-uri 'self', frame-ancestors 'self'.
  • The Python runtime (Pyodide) is self-hosted (served from our own origin), so no third-party script/CDN origin is whitelisted in the CSP.

Sandboxing of user code (defense in depth)

  • JavaScript execution (the Run button and notebook cells) runs in a Web Worker — no DOM, separate thread — with a wall-clock timeout that terminates infinite loops. The user's code is embedded as the worker's own script rather than eval'd, so the app keeps a strict script-src 'self' CSP with no 'unsafe-eval'.
  • HTML preview is served from a short-lived, same-origin URL (/preview/:token) inside an <iframe sandbox="allow-scripts"> without allow-same-origin — so it cannot read cookies, the parent DOM, or storage. That document carries its own locked-down CSP (default-src 'none'), which both lets the user's page run and blocks all network access from the preview (no exfiltration). Console output is relayed to the parent via postMessage.
  • Markdown (notebook cells and .md preview) is rendered with marked and then sanitized with DOMPurify before insertion, preventing stored XSS from a malicious collaborator.

Known limitations / production hardening

  • The code runner and HTML preview execute arbitrary code in the viewer's browser. They are isolated (Worker / sandboxed iframe) but, for a hardened multi-tenant deployment, previews should additionally be served from a separate origin so CSP and cookie isolation are absolute.
  • SQLite suits a single-node deployment. For horizontal scale, move sessions/rooms to Postgres and add a Socket.IO Redis adapter (see ARCHITECTURE notes in the README).
  • No email verification or password reset flow yet.

Reporting

Found an issue? Please open a private report rather than a public issue.

There aren't any published security advisories