typescript.react.security.react-markdown-insecure-html.react-markdown-insecure-html

Verifed by r2c
Community Favorite
profile photo of returntocorpreturntocorp
Author
64,103
Download Count*

Overwriting transformLinkUri or transformImageUri to something insecure, or turning allowDangerousHtml on, or turning escapeHtml off, will open the code up to XSS vectors.

Run Locally

Run in CI

Defintion

rules:
  - id: react-markdown-insecure-html
    message: Overwriting `transformLinkUri` or `transformImageUri` to something
      insecure, or turning `allowDangerousHtml` on, or turning `escapeHtml` off,
      will open the code up to XSS vectors.
    metadata:
      cwe:
        - "CWE-79: Improper Neutralization of Input During Web Page Generation
          ('Cross-site Scripting')"
      owasp:
        - A07:2017 - Cross-Site Scripting (XSS)
        - A03:2021 - Injection
      references:
        - https://www.npmjs.com/package/react-markdown#security
      category: security
      technology:
        - react
      cwe2022-top25: true
      cwe2021-top25: true
      subcategory:
        - audit
      likelihood: LOW
      impact: LOW
      confidence: LOW
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
    languages:
      - typescript
      - javascript
    severity: WARNING
    patterns:
      - pattern-either:
          - pattern-inside: |
              $X = require('react-markdown/with-html');
              ...
          - pattern-inside: |
              $X = require('react-markdown');
              ...
          - pattern-inside: |
              import 'react-markdown/with-html';
              ...
          - pattern-inside: |
              import 'react-markdown';
              ...
      - pattern-either:
          - pattern: |
              <$EL allowDangerousHtml />
          - pattern: |
              <$EL escapeHtml={false} />
          - pattern: |
              <$EL transformLinkUri=... />
          - pattern: |
              <$EL transformImageUri=... />

Examples

react-markdown-insecure-html.jsx

import ReactMarkdown from "react-markdown";
import htmlParser from "react-markdown/plugins/html-parser";

// For more info on the processing instructions, see
// <https://github.com/aknuds1/html-to-react#with-custom-processing-instructions>
const parseHtml = htmlParser({
  isValidNode: (node) => node.type !== 'script',
  processingInstructions: [
    /* ... */
  ]
})

function bad1() {
// ruleid: react-markdown-insecure-html
    return <ReactMarkdown astPlugins={[parseHtml]} allowDangerousHtml children={markdown} />;
}

function bad2() {
// ruleid: react-markdown-insecure-html
    return <ReactMarkdown astPlugins={[parseHtml]} escapeHtml={false} children={markdown} />;
}

function ok1() {
// ok: react-markdown-insecure-html
    return <ReactMarkdown renderers={renderers} children={markdown} />;
}

function ok2() {
// ok: react-markdown-insecure-html
    return <ReactMarkdown renderers={renderers} escapeHtml={true} children={markdown} />;
}

react-markdown-insecure-html.tsx

import ReactMarkdown from "react-markdown";
import htmlParser from "react-markdown/plugins/html-parser";

// For more info on the processing instructions, see
// <https://github.com/aknuds1/html-to-react#with-custom-processing-instructions>
const parseHtml = htmlParser({
  isValidNode: (node) => node.type !== 'script',
  processingInstructions: [
    /* ... */
  ]
})

function bad1() {
// ruleid: react-markdown-insecure-html
    return <ReactMarkdown astPlugins={[parseHtml]} allowDangerousHtml children={markdown} />;
}

function bad2() {
// ruleid: react-markdown-insecure-html
    return <ReactMarkdown astPlugins={[parseHtml]} escapeHtml={false} children={markdown} />;
}

function ok1() {
// ok: react-markdown-insecure-html
    return <ReactMarkdown renderers={renderers} children={markdown} />;
}

function ok2() {
// ok: react-markdown-insecure-html
    return <ReactMarkdown renderers={renderers} escapeHtml={true} children={markdown} />;
}