Files
tm-landing/SECURITY.md
T
AmirReza Jamali 3e5e135b47 feat(security): Add XSS protection with DOMPurify sanitization
- Add sanitize.ts utility module with sanitizeText(), sanitizeUrl(), and sanitizeHtml() functions
- Implement server-side HTML entity escaping and client-side DOMPurify sanitization
- Add comprehensive test suite for sanitization functions in lib/__tests__/sanitize.test.ts
- Secure marketing pages by sanitizing all CMS data (hero, features, challenges, advantages, footer)
- Secure inquiries form by sanitizing field labels, placeholders, and button text
- Add SECURITY.md documentation outlining XSS protection measures and best practices
- Add USAGE_EXAMPLES.md with detailed examples of sanitization function usage
- Add XSS_PROTECTION_SUMMARY.md with implementation overview
- Update package.json to include dompurify (^3.3.0) dependency
- Protects against common XSS attack vectors including script injection, event handlers, and malicious URLs
2025-11-30 11:14:42 +03:30

3.2 KiB

Security - XSS Protection

This document outlines the XSS (Cross-Site Scripting) protection measures implemented in this application.

Overview

All external data from the CMS API is sanitized using DOMPurify before being rendered to prevent XSS attacks.

Sanitization Functions

Located in lib/sanitize.ts:

sanitizeText()

Strips all HTML tags from text. Use this for plain text content that should never contain HTML.

import { sanitizeText } from "@/lib/sanitize";

// Example usage
<h1>{sanitizeText(cmsData?.title)}</h1>;

sanitizeHtml()

Allows specific HTML tags while removing dangerous content. Use this when you need to render formatted text.

import { sanitizeHtml } from "@/lib/sanitize";

// Example usage with default allowed tags (b, i, em, strong, a, br, p)
<div dangerouslySetInnerHTML={{ __html: sanitizeHtml(cmsData?.content) }} />

// Example with custom allowed tags
<div dangerouslySetInnerHTML={{ __html: sanitizeHtml(cmsData?.content, ["p", "br"]) }} />

sanitizeUrl()

Sanitizes URLs to prevent javascript:, data:, and vbscript: URI attacks.

import { sanitizeUrl } from "@/lib/sanitize";

// Example usage
<Link href={sanitizeUrl(cmsData?.link) || "#"}>Click here</Link>
<Image src={sanitizeUrl(cmsData?.imageUrl) || "/fallback.svg"} />

Protected Areas

The following components have been secured:

  1. Marketing Pages (app/marketing/[id]/page.tsx)

    • Hero section (title, description, button text, links)
    • Features section (titles, descriptions, icons)
    • Challenges section (titles, descriptions, icons)
    • Advantages section (titles, descriptions, icons)
    • Footer (email, phone, location, tagline, copyright)
  2. Inquiries Form (app/_inquires/form.tsx, app/_inquires/page.tsx)

    • Form field labels and placeholders
    • Submit button text
    • Section titles and descriptions

Best Practices

  1. Always sanitize external data - Any data from APIs, databases, or user input should be sanitized
  2. Use the right function - Use sanitizeText() for plain text, sanitizeUrl() for URLs, and sanitizeHtml() for formatted content
  3. Validate on the server - While client-side sanitization helps, always validate and sanitize on the server as well
  4. Keep DOMPurify updated - Regularly update the DOMPurify package to get the latest security fixes

Server-Side Rendering

The sanitization functions work in both client and server environments:

  • Server-side: Uses HTML entity escaping to prevent XSS attacks
  • Client-side: Uses DOMPurify for advanced HTML sanitization

This hybrid approach ensures:

  1. Fast server-side rendering without heavy dependencies
  2. Robust client-side protection with DOMPurify
  3. No build issues with Node.js-specific modules

Dependencies

  • dompurify (^3.3.0) - HTML sanitization library (client-side only)

Testing XSS Protection

To verify XSS protection is working, try injecting malicious content through the CMS:

// These should be sanitized and rendered harmless:
<script>alert('XSS')</script>
<img src=x onerror=alert('XSS')>
javascript:alert('XSS')
<iframe src="javascript:alert('XSS')"></iframe>

All of these should be stripped or neutralized by the sanitization functions.