javascript.jquery.security.audit.jquery-insecure-selector.jquery-insecure-selector

profile photo of semgrepsemgrep
Author
6,418
Download Count*

User controlled data in a $(...) is an anti-pattern that can lead to XSS vulnerabilities

Run Locally

Run in CI

Defintion

rules:
  - id: jquery-insecure-selector
    message: User controlled data in a `$(...)` is an anti-pattern that can lead to
      XSS vulnerabilities
    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://owasp.org/www-community/attacks/xss/
        - https://bugs.jquery.com/ticket/9521
      category: security
      technology:
        - jquery
      cwe2022-top25: true
      cwe2021-top25: true
      subcategory:
        - audit
      likelihood: LOW
      impact: MEDIUM
      confidence: LOW
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Cross-Site-Scripting (XSS)
    languages:
      - javascript
      - typescript
    severity: WARNING
    patterns:
      - pattern-either:
          - pattern: |
              $(<... window ...>)
          - pattern: |
              $(<... location ...>)
          - patterns:
              - pattern: |
                  $X = <... window ...>;
                  ...
                  $(<... $X ...>);
              - focus-metavariable: $X
          - patterns:
              - pattern: |
                  $X = <... location ...>;
                  ...
                  $(<... $X ...>);
              - focus-metavariable: $X
          - patterns:
              - pattern-either:
                  - pattern-inside: |
                      function $FUNC(..., $Y, ...) {
                        ...
                      }
                  - pattern-inside: |
                      function (..., $Y, ...) {
                        ...
                      }
                  - pattern-inside: |
                      function $FUNC(...,$Z,...) {
                        ...
                        $Y = <... $Z ...>;
                        ...
                      }
                  - pattern-inside: |
                      function (...,$Z,...) {
                        ...
                        $Y = <... $Z ...>;
                        ...
                      }
              - pattern-either:
                  - pattern: |
                      $(<... $Y ...>)
                  - pattern: |
                      $("..." + (<... $Y ...>))
                  - pattern: |
                      $((<... $Y ...>) + "...")
              - pattern-not-inside: |
                  $JQUERY.each(function($INDEX, $Y) {
                    ...
                  })
              - focus-metavariable: $Y
      - pattern-not: |
          $(window)
      - pattern-not: |
          $(document)
      - pattern-not: |
          $(this)

Examples

jquery-insecure-selector.js

(function ($) {

  function bad1() {
    // ruleid: jquery-insecure-selector
    var item = '.item-' + window.location.hash;
    $(item).css({});
  }

  function bad2() {
    // ruleid: jquery-insecure-selector
    $(location.hash).css('z-index', '99999');
  }

  function bad3() {
    // ruleid: jquery-insecure-selector
    var item = window.location.hash;
    $('.item-' + item).css({});
  }

  function bad4() {
    // ruleid: jquery-insecure-selector
    $('#' + location.hash).css('z-index', '99999');
  }

  function bad5(userInput) {
    // ruleid: jquery-insecure-selector
    $('#' + userInput).css('z-index', '99999');
  }

  function ok1() {
    // ok: jquery-insecure-selector
    var item = 'my-selector';
    $('#' + item).css('z-index', '99999');
  }

  function ok2(userInput) {
    // ok: jquery-insecure-selector
    $('#' + somethingElse).css('z-index', '99999');
  }

  function ok3() {
    // ok: jquery-insecure-selector
    $(window).css('z-index', '99999');
  }

  function ok4() {
    // ok: jquery-insecure-selector
    $( "li" ).each(function(index, el) {
        $(el).addClass( "foo" );
    });
  }

})(jQUery);


//https://github.com/ebmdatalab/openprescribing/blob/9e511903eb6343f804c4e14cc29103b1056fcead/openprescribing/media/js/src/measures.js
var measures = {
  highlightSelectedMeasure: function(selectedMeasure) {
    if ( ! selectedMeasure || selectedMeasure === '') return;
    var measureId = '#measure_' + selectedMeasure.substring(selectedMeasure.indexOf('#') + 1);
    // ruleid: jquery-insecure-selector
    if ($(measureId).length === 0) return;
    $('#overlay').fadeIn(300);
    // ruleid: jquery-insecure-selector
    $(measureId).css('z-index', '99999');
    $('html, body').animate({
      // ruleid: jquery-insecure-selector
      scrollTop: $(measureId).offset().top,
    }, 1000);
    $('#overlay').on('click', function() {
      $('#overlay').stop().fadeOut(300);
    });
  }
};