javascript.monaco-editor.security.audit.monaco-hover-htmlsupport.monaco-hover-htmlsupport

profile photo of semgrepsemgrep
Author
unknown
Download Count*

If user input reaches HoverProvider while supportHml is set to true it may introduce an XSS vulnerability. Do not produce HTML for hovers with dynamically generated input.

Run Locally

Run in CI

Defintion

rules:
  - id: monaco-hover-htmlsupport
    message: If user input reaches `HoverProvider` while `supportHml` is set to
      `true` it may introduce an XSS vulnerability. Do not produce HTML for
      hovers with dynamically generated input.
    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://github.com/microsoft/monaco-editor/issues/801
      category: security
      technology:
        - monaco
        - monaco-editor
      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]
      vulnerability_class:
        - Cross-Site-Scripting (XSS)
    languages:
      - typescript
      - javascript
    severity: WARNING
    patterns:
      - pattern-either:
          - pattern-inside: |
              import "monaco-editor"
              ...
          - pattern-inside: |
              require("monaco-editor")
              ...
      - pattern-either:
          - pattern: |
              {value: $VAL, supportHtml: true}
          - pattern: |
              {value: $VAL, isTrusted: true}
      - pattern-inside: |
          {range: $R, contents: [...]}
      - pattern-not: |
          {..., value: "...", ...}

Examples

monaco-hover-htmlsupport.js

import { editor, languages, Range } from "monaco-editor";

function test1 (userInput) {
  languages.registerHoverProvider('mySpecialLanguage', {
    provideHover: function (model) {
      return {
        range: new Range(1, 1, model.getLineCount(), model.getLineMaxColumn(model.getLineCount())),
        contents: [
          // ruleid:monaco-hover-htmlsupport
          {
            value: `<a href="${userInput}">Hello</a>`,
            supportHtml: true,
            isTrusted: true
          },
        ]
      }
    }
  });
}

function okTest1 () {
  languages.registerHoverProvider('mySpecialLanguage', {
    provideHover: function (model) {
      return {
        range: new Range(1, 1, model.getLineCount(), model.getLineMaxColumn(model.getLineCount())),
        contents: [
          {
            value: `<a href="//google.com">Hello</a>`,
            supportHtml: true,
            isTrusted: true
          },
        ]
      }
    }
  });
}

function okTest2 (userInput) {
  languages.registerHoverProvider('mySpecialLanguage', {
    provideHover: function (model) {
      return {
        range: new Range(1, 1, model.getLineCount(), model.getLineMaxColumn(model.getLineCount())),
        contents: [
          {
            value: `** Hello ${userInput}`,
          },
        ]
      }
    }
  });
}