Skip to content

Bug: Stored XSS via unsanitized dangerouslySetInnerHTML in blog post rendering #15

@FuturMix

Description

@FuturMix

Description

The blog post page (apps/web/app/blog/[slug]/page.tsx) renders post.content using dangerouslySetInnerHTML without any HTML sanitization (line 96):

dangerouslySetInnerHTML={{ __html: post.content }}

If an attacker can inject malicious HTML into a blog post's content field (via the admin panel, database, or any content pipeline), the injected JavaScript will execute in every visitor's browser.

Impact

  • Severity: High
  • Session hijacking, credential theft, phishing
  • Any compromise of the blog content pipeline immediately escalates to client-side code execution

Steps to Reproduce

  1. Insert a blog post with content containing <img onerror="alert('XSS')" src=x> or <script>alert('XSS')</script>
  2. Visit the blog post page
  3. The injected script executes

Suggested Fix

Sanitize HTML before rendering using a library like sanitize-html or isomorphic-dompurify:

import sanitizeHtml from 'sanitize-html';

// In the component:
const cleanContent = sanitizeHtml(post.content, {
  allowedTags: sanitizeHtml.defaults.allowedTags.concat(['img', 'h1', 'h2', 'h3']),
  allowedAttributes: {
    ...sanitizeHtml.defaults.allowedAttributes,
    img: ['src', 'alt', 'width', 'height'],
  },
});

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions