Skip to content

fix: resolve stored XSS vulnerability in peer messaging module (#1852) - #1867

Open
atul-upadhyay-7 wants to merge 1 commit into
durdana3105:mainfrom
atul-upadhyay-7:fix/xss-peer-messaging-1852
Open

fix: resolve stored XSS vulnerability in peer messaging module (#1852)#1867
atul-upadhyay-7 wants to merge 1 commit into
durdana3105:mainfrom
atul-upadhyay-7:fix/xss-peer-messaging-1852

Conversation

@atul-upadhyay-7

@atul-upadhyay-7 atul-upadhyay-7 commented Jul 27, 2026

Copy link
Copy Markdown

Summary

This PR fixes the Stored Cross-Site Scripting (XSS) vulnerability described in #1852. The fix ensures that user-generated content in peer messaging is sanitized before storage and rendering, preventing attackers from executing arbitrary JavaScript in victims' browsers.

Problem

Messages containing malicious JavaScript payloads (e.g., <script>alert(document.cookie)</script>) were stored in the database and rendered in victims' browsers without proper escaping. This enables session hijacking, credential theft, and unauthorized actions.

Changes

Defense-in-Depth: Input Sanitization (Before Storage)

  • New src/utils/sanitize.ts: DOMPurify-based sanitization utility that strips all HTML tags, scripts, event handlers, and dangerous attributes from user content
  • src/hooks/useMessages.ts: Added validateMessageContent() before message insert
  • src/hooks/useRoomChat.ts: Added validateMessageContent() before message insert
  • src/hooks/useSessions.ts: Added validateMessageContent() before message insert

Defense-in-Depth: Output Sanitization (On Render)

  • src/components/chat/MessageBubble.tsx: Added sanitizeMessageContent() on text render
  • src/components/messages/utils.ts: getMessageBody() now sanitizes message content

Content Security Policy (CSP)

  • backend/app.js: Added CSP HTTP header blocking inline scripts, restricting sources, and preventing clickjacking
  • Added security headers: X-Content-Type-Options, X-Frame-Options, X-XSS-Protection, Referrer-Policy

Dependency

  • Added dompurify + @types/dompurify for browser-side HTML sanitization

Security Architecture

The fix implements a defense-in-depth strategy:

  1. Input validation — messages are sanitized before database storage
  2. Output sanitization — messages are sanitized again on render (protects against legacy data)
  3. CSP headers — inline scripts are blocked even if XSS bypasses sanitization
  4. Security headers — additional protections against MIME sniffing, clickjacking, etc.

Testing

  • TypeScript compilation: ✅ Clean (no errors)
  • Security tests: ✅ 5/5 passed
  • MessageBubble tests: ✅ 6/6 passed
  • All unit tests: ✅ 37/37 passed

Fixes #1852

Summary by CodeRabbit

  • Security

    • Added protections against common web security risks through enhanced browser security headers.
    • Improved handling of user-provided message content by removing unsafe HTML and scripts.
  • Bug Fixes

    • Invalid, empty, or overly long messages are now blocked with clear error notifications.
    • Sanitized message content is consistently used when sending and displaying messages.

@vercel

vercel Bot commented Jul 27, 2026

Copy link
Copy Markdown

@atul-upadhyay-7 is attempting to deploy a commit to the durdana3105's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Message inputs are validated and sanitized before storage, rendered messages are sanitized before display, DOMPurify is upgraded, and backend middleware adds security-related HTTP response headers.

Changes

Message Security

Layer / File(s) Summary
Sanitization and validation contract
src/utils/sanitize.ts, package.json
Adds DOMPurify-based sanitization and validation for non-empty messages with a configurable 1,000-character default limit, and updates the DOMPurify version.
Outbound message validation
src/hooks/useMessages.ts, src/hooks/useRoomChat.ts, src/hooks/useSessions.ts
Validates outgoing messages, reports invalid input through toasts, and persists sanitized content to Supabase.
Rendered message sanitization
src/components/chat/MessageBubble.tsx, src/components/messages/utils.ts
Sanitizes message content before rendering in the chat bubble and message-body utility.
Backend response security headers
backend/app.js
Adds CSP, content-type, frame, XSS, and referrer-policy response headers through middleware.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Sender
  participant MessageHooks
  participant validateMessageContent
  participant Supabase
  participant MessageBubble

  Sender->>MessageHooks: submit message
  MessageHooks->>validateMessageContent: validate and sanitize text
  validateMessageContent-->>MessageHooks: sanitized content or validation error
  MessageHooks->>Supabase: insert sanitized content
  Supabase-->>MessageBubble: stored message
  MessageBubble->>MessageBubble: sanitize text before display
Loading

Possibly related PRs

Suggested labels: type:bug

Suggested reviewers: arshvermagit

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: fixing a stored XSS vulnerability in the peer messaging module.
Linked Issues check ✅ Passed The PR satisfies #1852 by sanitizing and validating message content before storage/rendering and adding a strong CSP.
Out of Scope Changes check ✅ Passed The changes stay focused on XSS mitigation and related security hardening, with no clear unrelated code added.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/app.js`:
- Line 82: Remove the res.setHeader call that sets X-XSS-Protection in the
backend response setup, leaving the existing CSP protections and other response
headers unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 94d4e95a-0a52-4518-886b-19ddb4595a92

📥 Commits

Reviewing files that changed from the base of the PR and between 3565841 and c1ce7eb.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (8)
  • backend/app.js
  • package.json
  • src/components/chat/MessageBubble.tsx
  • src/components/messages/utils.ts
  • src/hooks/useMessages.ts
  • src/hooks/useRoomChat.ts
  • src/hooks/useSessions.ts
  • src/utils/sanitize.ts

Comment thread backend/app.js
// Additional security headers
res.setHeader("X-Content-Type-Options", "nosniff");
res.setHeader("X-Frame-Options", "DENY");
res.setHeader("X-XSS-Protection", "1; mode=block");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== repo files matching backend/app.js =="
fd -a 'app\.js$' . | sed 's#^\./##'

echo
echo "== backend/app.js outline/snippet =="
if [ -f backend/app.js ]; then
  wc -l backend/app.js
  cat -n backend/app.js | sed -n '60,95p'
fi

echo
echo "== header-related usages =="
rg -n "X-XSS-Protection|Content-Security-Policy|X-Frame|X-Content-Type|Referrer" backend/app.js backend || true

echo
echo "== package/security/middleware context =="
fd -a 'package.json$' . | sed 's#^\./##' | while read -r f; do
  echo "--- $f"
  node -e "const p=require('${f//\'/\\\'}'); console.log(JSON.stringify({name:p.name, dependencies:p.dependencies, devDependencies:p.devDependencies, scripts:p.scripts}, null, 2))" 2>/dev/null || sed -n '1,160p' "$f"
done

Repository: durdana3105/peer-learning

Length of output: 7445


🌐 Web query:

MDN X-XSS-Protection deprecated 0 XSS protection disabled

💡 Result:

The X-XSS-Protection HTTP header is deprecated and no longer recommended for use in modern web development [1][2][3][4]. The header was originally designed to control a browser-level feature known as the XSS Auditor, which attempted to detect and block reflected cross-site scripting (XSS) attacks [2][5][6]. However, this auditor was found to be unreliable, prone to bypasses, and in some instances, capable of introducing new security vulnerabilities (such as enabling cross-site information leaks or creating XSS where none existed) [2][7][8][9]. Regarding the specific configuration X-XSS-Protection: 0: - Meaning: This value explicitly disables the legacy XSS auditor [2][7][6]. - Recommendation: While the header itself is deprecated and ignored by modern browsers, many security experts recommend explicitly setting X-XSS-Protection: 0 as a defensive measure [9][5][6]. Doing so ensures that if a user visits the site with a very old browser that still includes an XSS auditor, the feature is explicitly turned off rather than defaulting to an potentially harmful enabled state [9][6]. - Alternative: Simply omitting the header is also acceptable, as modern browsers have removed the XSS auditor entirely [6][4]. In 2026, the industry-standard approach for preventing XSS is to implement a robust Content Security Policy (CSP) [3][6][4]. CSP provides much stronger and more reliable protection against XSS by restricting the sources from which scripts can be loaded and executed, rendering the legacy XSS auditor obsolete [8][6][4].

Citations:


Remove the deprecated X-XSS-Protection header.

This non-standard header is deprecated, and modern protections are provided by your existing CSP. Remove it here, or use 0 only if the browser-support policy requires explicitly disabling legacy XSS auditors.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/app.js` at line 82, Remove the res.setHeader call that sets
X-XSS-Protection in the backend response setup, leaving the existing CSP
protections and other response headers unchanged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Urgent: Stored Cross-Site Scripting (XSS) in Peer Messaging Module

1 participant