javascript.jquery.security.audit.jquery-insecure-selector.jquery-insecure-selector
semgrep
Author
6,418
Download Count*
License
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);
});
}
};
Short Link: https://sg.run/W8NL