From fef918ac13b9f990a71bf55081156600707cad9a Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen Date: Fri, 17 Jan 2020 10:02:39 +0100 Subject: [PATCH 01/10] JS: add query "Unsafe jQuery plugin" --- change-notes/1.24/analysis-javascript.md | 1 + javascript/config/suites/javascript/security | 1 + .../Security/CWE-079/UnsafeJQueryPlugin.qhelp | 98 ++++ .../Security/CWE-079/UnsafeJQueryPlugin.ql | 25 + .../CWE-079/examples/UnsafeJQueryPlugin.js | 6 + .../examples/UnsafeJQueryPlugin_safe.js | 6 + .../security/dataflow/UnsafeJQueryPlugin.qll | 41 ++ .../UnsafeJQueryPluginCustomizations.qll | 242 +++++++++ .../javascript/security/dataflow/Xss.qll | 2 +- .../CWE-079/UnsafeJQueryPlugin.expected | 488 ++++++++++++++++++ .../Security/CWE-079/UnsafeJQueryPlugin.qlref | 1 + .../Security/CWE-079/unsafe-jquery-plugin.js | 159 ++++++ 12 files changed, 1069 insertions(+), 1 deletion(-) create mode 100644 javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.qhelp create mode 100644 javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.ql create mode 100644 javascript/ql/src/Security/CWE-079/examples/UnsafeJQueryPlugin.js create mode 100644 javascript/ql/src/Security/CWE-079/examples/UnsafeJQueryPlugin_safe.js create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll create mode 100644 javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.expected create mode 100644 javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.qlref create mode 100644 javascript/ql/test/query-tests/Security/CWE-079/unsafe-jquery-plugin.js diff --git a/change-notes/1.24/analysis-javascript.md b/change-notes/1.24/analysis-javascript.md index b19d0e49b75..17d1fdd7f7a 100644 --- a/change-notes/1.24/analysis-javascript.md +++ b/change-notes/1.24/analysis-javascript.md @@ -28,6 +28,7 @@ | Regular expression always matches (`js/regex/always-matches`) | correctness, regular-expressions | Highlights regular expression checks that trivially succeed by matching an empty substring. Results are shown on LGTM by default. | | Missing await (`js/missing-await`) | correctness | Highlights expressions that operate directly on a promise object in a nonsensical way, instead of awaiting its result. Results are shown on LGTM by default. | | Prototype pollution in utility function (`js/prototype-pollution-utility`) | security, external/cwe/cwe-400, external/cwe/cwe-471 | Highlights recursive copying operations that are susceptible to prototype pollution. Results are shown on LGTM by default. | +| Unsafe jQuery plugin (`js/unsafe-jquery-plugin`) | Highlights potential XSS vulnerabilities in unsafely designed jQuery plugins. | ## Changes to existing queries diff --git a/javascript/config/suites/javascript/security b/javascript/config/suites/javascript/security index 301cfc8ed05..59ba38b0435 100644 --- a/javascript/config/suites/javascript/security +++ b/javascript/config/suites/javascript/security @@ -14,6 +14,7 @@ + semmlecode-javascript-queries/Security/CWE-079/ReflectedXss.ql: /Security/CWE/CWE-079 + semmlecode-javascript-queries/Security/CWE-079/StoredXss.ql: /Security/CWE/CWE-079 + semmlecode-javascript-queries/Security/CWE-079/Xss.ql: /Security/CWE/CWE-079 ++ semmlecode-javascript-queries/Security/CWE-079/UnsafeJQueryPlugin.ql: /Security/CWE/CWE-079 + semmlecode-javascript-queries/Security/CWE-089/SqlInjection.ql: /Security/CWE/CWE-089 + semmlecode-javascript-queries/Security/CWE-094/CodeInjection.ql: /Security/CWE/CWE-094 + semmlecode-javascript-queries/Security/CWE-094/UnsafeDynamicMethodAccess.ql: /Security/CWE/CWE-094 diff --git a/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.qhelp b/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.qhelp new file mode 100644 index 00000000000..71679dadaf3 --- /dev/null +++ b/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.qhelp @@ -0,0 +1,98 @@ + + + + +

+ + Library plugins, such as those for the jQuery library, are often + configurable through options provided by the clients of the + plugin. + + Clients, however, do not know the implementation details of the + plugin, so it is important to document the capabilities of each + option. Of particular importance is the documentation for the plugin + options that the client is responsible for sanitizing. + + Otherwise, the plugin may write user input (for example, a URL query + parameter) to a web page without properly sanitizing the input first, + which allows for a cross-site scripting vulnerability in the client + application. + +

+
+ + +

+ + Document all options that can lead to cross-site scripting attacks. + +

+
+ + +

+ + The following example shows a jQuery plugin that selects a DOM + element, and copies its text content another DOM element. The + selection is performed by using the plugin option + sourceSelector as a CSS selector. + +

+ + + +

+ + This is however not a safe plugin, since the call to + jQuery interprets sourceSelector as HTML if + it is a string that starts with <. + +

+ +

+ + Instead of documenting that the client is responsible for + sanitizing sourceSelector, the plugin can use + jQuery.find to always interpret + sourceSelector as a CSS selector: + +

+ + + + +
+ + +
  • + OWASP: + DOM based + XSS Prevention Cheat Sheet. +
  • +
  • + OWASP: + XSS + (Cross Site Scripting) Prevention Cheat Sheet. +
  • +
  • + OWASP + DOM Based XSS. +
  • +
  • + OWASP + Types of Cross-Site + Scripting. +
  • +
  • + Wikipedia: Cross-site scripting. +
  • +
  • + jQuery: Plugin creation. +
  • +
  • + Bootstrap: XSS vulnerable bootstrap plugins. +
  • +
    +
    diff --git a/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.ql b/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.ql new file mode 100644 index 00000000000..7d5525c1d29 --- /dev/null +++ b/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.ql @@ -0,0 +1,25 @@ +/** + * @name Unsafe jQuery plugin + * @description A jQuery plugin that unintentionally constructs HTML from some of its options may be unsafe to use for clients. + * @kind path-problem + * @problem.severity error + * @precision high + * @id js/unsafe-jquery-plugin + * @tags security + * external/cwe/cwe-079 + * external/cwe/cwe-116 + * frameworks/jquery + */ + +import javascript +import semmle.javascript.security.dataflow.UnsafeJQueryPlugin::UnsafeJQueryPlugin +import DataFlow::PathGraph + +from + Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, JQueryPluginMethod plugin +where + cfg.hasFlowPath(source, sink) and + source.getNode().(Source).getPlugin() = plugin and + not isLikelyIntentionalHtmlSink(plugin, sink.getNode()) +select sink.getNode(), source, sink, "Potential XSS vulnerability in the $@.", plugin, + "'$.fn." + plugin.getPluginName() + "' plugin" diff --git a/javascript/ql/src/Security/CWE-079/examples/UnsafeJQueryPlugin.js b/javascript/ql/src/Security/CWE-079/examples/UnsafeJQueryPlugin.js new file mode 100644 index 00000000000..eb5ae7f9704 --- /dev/null +++ b/javascript/ql/src/Security/CWE-079/examples/UnsafeJQueryPlugin.js @@ -0,0 +1,6 @@ +jQuery.fn.copyText = function(options) { + // BAD may evaluate `options.sourceSelector` as HTML + var source = jQuery(options.sourceSelector), + text = source.text(); + jQuery(this).text(text); +} diff --git a/javascript/ql/src/Security/CWE-079/examples/UnsafeJQueryPlugin_safe.js b/javascript/ql/src/Security/CWE-079/examples/UnsafeJQueryPlugin_safe.js new file mode 100644 index 00000000000..ea613642d0f --- /dev/null +++ b/javascript/ql/src/Security/CWE-079/examples/UnsafeJQueryPlugin_safe.js @@ -0,0 +1,6 @@ +jQuery.fn.copyText = function(options) { + // GOOD may not evaluate `options.sourceSelector` as HTML + var source = jQuery.find(options.sourceSelector), + text = source.text(); + jQuery(this).text(text); +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll new file mode 100644 index 00000000000..176a32c1d3f --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll @@ -0,0 +1,41 @@ +/** + * Provides a taint-tracking configuration for reasoning about DOM-based + * cross-site scripting vulnerabilities in unsafe jQuery plugins. + */ + +import javascript +import semmle.javascript.security.dataflow.Xss + +module UnsafeJQueryPlugin { + import UnsafeJQueryPluginCustomizations::UnsafeJQueryPlugin + + /** + * A taint-tracking configuration for reasoning about XSS in unsafe jQuery plugins. + */ + class Configuration extends TaintTracking::Configuration { + Configuration() { this = "UnsafeJQueryPlugin" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) + or + node instanceof DomBasedXss::Sanitizer + or + node instanceof Sanitizer + } + + override predicate isAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) { + // jQuery plugins tend to be implemented as classes that store data in fields initialized by the constructor. + DataFlow::localFieldStep(src, sink) + } + + override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode node) { + super.isSanitizerGuard(node) or + node instanceof IsElementSanitizer or + node instanceof IsJQueryObjectSanitizer + } + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll new file mode 100644 index 00000000000..c4cd7f81a09 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll @@ -0,0 +1,242 @@ +/** + * Provides default sources, sinks and sanitizers for reasoning about + * unsafe jQuery plugins, as well as extension points for adding your + * own. + */ + +import javascript +private import semmle.javascript.dataflow.InferredTypes +import semmle.javascript.security.dataflow.Xss + +module UnsafeJQueryPlugin { + private import DataFlow::FlowLabel + + /** + * A data flow source for unsafe jQuery plugins. + */ + abstract class Source extends DataFlow::Node { + /** + * Gets the plugin that this source is used in. + */ + abstract JQueryPluginMethod getPlugin(); + } + + /** + * A data flow sink for unsafe jQuery plugins. + */ + abstract class Sink extends DataFlow::Node { } + + /** + * A sanitizer for unsafe jQuery plugins. + */ + abstract class Sanitizer extends DataFlow::Node { } + + /** + * An argument that may act as a HTML fragment rather than a CSS selector, as a sink for remote unsafe jQuery plugins. + */ + class AmbiguousHtmlOrSelectorArgument extends DataFlow::Node { + AmbiguousHtmlOrSelectorArgument() { + exists(JQuery::MethodCall call | + call.interpretsArgumentAsSelector(this) and call.interpretsArgumentAsHtml(this) + ) and + // the $-function in particular will not construct HTML for non-string values + analyze().getAType() = TTString() and + // any fixed prefix makes the call unambiguous + not exists(DataFlow::Node prefix | + DomBasedXss::isPrefixOfJQueryHtmlString(this, prefix) and + prefix.mayHaveStringValue(_) + ) + } + } + + /** + * Holds for jQuery plugin definitions of the form `$.fn. = `. + */ + private predicate jQueryPluginDefinition(string pluginName, DataFlow::Node plugin) { + exists(DataFlow::PropRead fn, DataFlow::PropWrite write | + fn = jquery().getAPropertyRead("fn") and + ( + write = fn.getAPropertyWrite() + or + exists(ExtendCall extend, DataFlow::SourceNode source | + fn.flowsTo(extend.getDestinationOperand()) and + source = extend.getASourceOperand() and + write = source.getAPropertyWrite() + ) + ) and + plugin = write.getRhs() and + ( + pluginName = write.getPropertyName() or + write.getPropertyNameExpr().flow().mayHaveStringValue(pluginName) + ) + ) + } + + /** + * Gets an function that is registered as a jQuery plugin method at `def`. + */ + private DataFlow::FunctionNode getAJQueryPluginMethod( + DataFlow::TypeBackTracker t, DataFlow::Node def + ) { + t.start() and + jQueryPluginDefinition(_, def) and + result.flowsTo(def) + or + exists(DataFlow::TypeBackTracker t2 | result = getAJQueryPluginMethod(t2, def).backtrack(t2, t)) + } + + /** + * Gets an operand to `extend`. + */ + private DataFlow::SourceNode getAnExtendOperand(DataFlow::TypeBackTracker t, ExtendCall extend) { + t.start() and + result.flowsTo(extend.getAnOperand()) + or + exists(DataFlow::TypeBackTracker t2 | result = getAnExtendOperand(t2, extend).backtrack(t2, t)) + } + + /** + * A function that is registered as a jQuery plugin method. + */ + class JQueryPluginMethod extends DataFlow::FunctionNode { + string pluginName; + + JQueryPluginMethod() { + exists(DataFlow::Node def | + jQueryPluginDefinition(pluginName, def) and + this = getAJQueryPluginMethod(DataFlow::TypeBackTracker::end(), def) + ) + } + + /** + * Gets the name of this plugin. + */ + string getPluginName() { result = pluginName } + } + + /** + * Holds if `plugin` has a default option defined a `def`. + */ + private predicate hasDefaultOption(JQueryPluginMethod plugin, DataFlow::PropWrite def) { + exists(ExtendCall extend, JQueryPluginOptions options, DataFlow::SourceNode default | + options.getPlugin() = plugin and + options = getAnExtendOperand(DataFlow::TypeBackTracker::end(), extend) and + default = getAnExtendOperand(DataFlow::TypeBackTracker::end(), extend) and + default.getAPropertyWrite() = def + ) + } + + /** + * The client-provided options object for a jQuery plugin. + */ + class JQueryPluginOptions extends DataFlow::ParameterNode { + JQueryPluginMethod method; + + JQueryPluginOptions() { + exists(string optionsPattern | + optionsPattern = "(?i)(opt(ion)?s?)" and + if method.getAParameter().getName().regexpMatch(optionsPattern) + then ( + // use the last parameter named something like "options" if it exists ... + getName().regexpMatch(optionsPattern) and + this = method.getAParameter() + ) else ( + // ... otherwise, use the last parameter, unless it looks like a DOM node + this = method.getLastParameter() and + not getName().regexpMatch("(?i)(e(l(em(ent(s)?)?)?)?)") + ) + ) + } + + /** + * Gets the plugin method that these options are used in. + */ + JQueryPluginMethod getPlugin() { result = method } + } + + /** + * Expression of form `isElement(x)`, which sanitizes `x`. + */ + class IsElementSanitizer extends TaintTracking::SanitizerGuardNode, DataFlow::CallNode { + IsElementSanitizer() { + // common ad hoc sanitizing calls + exists(string name | getCalleeName() = name | + name = "isElement" or name = "isWindow" or name = "isWindow" + ) + } + + override predicate sanitizes(boolean outcome, Expr e) { + outcome = true and e = getArgument(0).asExpr() + } + } + + /** + * Expression of form `typeof x.jquery !== "undefined"` or `x.jquery`, which sanitizes `x`. + */ + class IsJQueryObjectSanitizer extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode { + DataFlow::Node input; + boolean polarity; + + IsJQueryObjectSanitizer() { + exists(DataFlow::PropRead read | read.accesses(input, "jquery") | + exists(EqualityTest test | + polarity = test.getPolarity().booleanNot() and + this = test.flow() + | + exists(Expr undef | test.hasOperands(read.asExpr(), undef) | + SyntacticConstants::isUndefined(undef) + ) + or + exists(Expr op1, Expr op2 | test.hasOperands(op1, op2) | + read.asExpr() = op1.(TypeofExpr).getOperand() and + op2.mayHaveStringValue(any(InferredType t | t = TTUndefined()).getTypeofTag()) + ) + ) + or + polarity = true and + this = read + ) + } + + override predicate sanitizes(boolean outcome, Expr e) { + outcome = polarity and + e = input.asExpr() + } + } + + /** + * The client-provided options object for a jQuery plugin, considered as a source for unsafe jQuery plugins. + */ + class JQueryPluginOptionsAsSource extends Source, JQueryPluginOptions { + override JQueryPluginMethod getPlugin() { result = JQueryPluginOptions.super.getPlugin() } + } + + /** + * An argument that may act as a HTML fragment rather than a CSS selector, as a sink for remote unsafe jQuery plugins. + */ + class AmbiguousHtmlOrSelectorArgumentAsSink extends Sink { + AmbiguousHtmlOrSelectorArgumentAsSink() { this instanceof AmbiguousHtmlOrSelectorArgument } + } + + /** + * A hint that a value is expected to be treated as a HTML fragment later. + */ + class IntentionalHtmlFragmentHint extends Sanitizer { + IntentionalHtmlFragmentHint() { + this.(DataFlow::PropRead).getPropertyName().regexpMatch("(?i).*(html|template).*") + } + } + + /** + * Holds if `plugin` likely expects `sink` to be treated as a HTML fragment. + */ + predicate isLikelyIntentionalHtmlSink(JQueryPluginMethod plugin, Sink sink) { + exists(DataFlow::PropWrite defaultDef, string default, DataFlow::PropRead finalRead | + hasDefaultOption(plugin, defaultDef) and + defaultDef.getPropertyName() = finalRead.getPropertyName() and + defaultDef.getRhs().mayHaveStringValue(default) and + default.regexpMatch("\\s*<.*") and + finalRead.flowsTo(sink) + ) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/Xss.qll b/javascript/ql/src/semmle/javascript/security/dataflow/Xss.qll index 71b2a463f7a..9f272252ef0 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/Xss.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/Xss.qll @@ -106,7 +106,7 @@ module DomBasedXss { * Holds if `prefix` is a prefix of `htmlString`, which may be intepreted as * HTML by a jQuery method. */ - private predicate isPrefixOfJQueryHtmlString(DataFlow::Node htmlString, DataFlow::Node prefix) { + predicate isPrefixOfJQueryHtmlString(DataFlow::Node htmlString, DataFlow::Node prefix) { any(JQuery::MethodCall call).interpretsArgumentAsHtml(htmlString) and prefix = htmlString or diff --git a/javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.expected b/javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.expected new file mode 100644 index 00000000000..b6cbaede45b --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.expected @@ -0,0 +1,488 @@ +nodes +| DELETE_ME/bootstrap-post-27047_src/affix.js:16:34:16:40 | options | +| DELETE_ME/bootstrap-post-27047_src/affix.js:17:20:17:56 | $.exten ... ptions) | +| DELETE_ME/bootstrap-post-27047_src/affix.js:17:29:17:30 | {} | +| DELETE_ME/bootstrap-post-27047_src/affix.js:17:49:17:55 | options | +| DELETE_ME/bootstrap-post-27047_src/affix.js:19:68:19:79 | this.options | +| DELETE_ME/bootstrap-post-27047_src/affix.js:19:68:19:86 | this.options.target | +| DELETE_ME/bootstrap-post-27047_src/affix.js:19:68:19:86 | this.options.target | +| DELETE_ME/bootstrap-post-27047_src/affix.js:121:19:121:24 | option | +| DELETE_ME/bootstrap-post-27047_src/affix.js:121:19:121:24 | option | +| DELETE_ME/bootstrap-post-27047_src/affix.js:125:11:125:55 | options | +| DELETE_ME/bootstrap-post-27047_src/affix.js:125:21:125:55 | typeof ... option | +| DELETE_ME/bootstrap-post-27047_src/affix.js:125:50:125:55 | option | +| DELETE_ME/bootstrap-post-27047_src/affix.js:127:65:127:71 | options | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:16:31:16:37 | options | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:19:27:19:67 | $.exten ... ptions) | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:19:36:19:37 | {} | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:19:60:19:66 | options | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:27:20:53 | (this.o ... \|\| '') | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:28:20:39 | this.options | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:28:20:46 | this.options.target | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:28:20:52 | this.op ... t \|\| '' | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:109:9:111:47 | selector | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:109:20:109:32 | this.selector | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:109:20:111:47 | this.se ... + '"]' | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:111:7:111:19 | this.selector | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:113:20:113:27 | selector | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:113:20:113:27 | selector | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:127:7:127:19 | this.selector | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:127:7:127:19 | this.selector | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:136:19:136:24 | option | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:136:19:136:24 | option | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:140:11:140:55 | options | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:140:21:140:55 | typeof ... option | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:140:50:140:55 | option | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:142:73:142:79 | options | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:16:34:16:40 | options | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:17:20:17:56 | $.exten ... ptions) | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:17:29:17:30 | {} | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:17:49:17:55 | options | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:19:22:19:33 | this.options | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:19:22:19:40 | this.options.target | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:19:22:19:40 | this.options.target | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:119:19:119:24 | option | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:119:19:119:24 | option | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:123:11:123:55 | options | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:123:21:123:55 | typeof ... option | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:123:50:123:55 | option | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:125:65:125:71 | options | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:17:37:17:43 | options | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:19:26:19:65 | $.exten ... ptions) | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:19:35:19:36 | {} | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:19:58:19:64 | options | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:140:14:140:25 | this.options | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:140:14:140:32 | this.options.parent | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:140:14:140:32 | this.options.parent | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:170:19:170:24 | option | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:170:19:170:24 | option | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:11:174:102 | options | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:21:174:102 | $.exten ... option) | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:30:174:31 | {} | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:67:174:101 | typeof ... option | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:96:174:101 | option | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:177:71:177:77 | options | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:16:31:16:37 | options | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:19:27:19:67 | $.exten ... ptions) | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:19:36:19:37 | {} | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:19:60:19:66 | options | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:27:20:53 | (this.o ... \|\| '') | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:28:20:39 | this.options | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:28:20:46 | this.options.target | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:28:20:52 | this.op ... t \|\| '' | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:109:9:111:47 | selector | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:109:20:109:32 | this.selector | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:109:20:111:47 | this.se ... + '"]' | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:111:7:111:19 | this.selector | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:113:20:113:27 | selector | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:113:20:113:27 | selector | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:127:7:127:19 | this.selector | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:127:7:127:19 | this.selector | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:136:19:136:24 | option | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:136:19:136:24 | option | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:140:11:140:55 | options | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:140:21:140:55 | typeof ... option | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:140:50:140:55 | option | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:142:73:142:79 | options | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:17:36:17:42 | options | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:26:35:26:41 | options | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:49:53:49:59 | options | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:53:22:53:45 | this.ge ... ptions) | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:53:38:53:44 | options | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:49:54:193 | $.isFun ... ewport) | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:49:54:193 | $.isFun ... ewport) | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:137:54:193 | (this.o ... ewport) | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:149 | this.options | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:158 | this.op ... iewport | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:167 | this.op ... elector | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:192 | this.op ... iewport | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:172:54:183 | this.options | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:172:54:192 | this.op ... iewport | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:207:46:207:57 | this.options | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:207:46:207:67 | this.op ... ntainer | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:207:46:207:67 | this.op ... ntainer | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:494:19:494:24 | option | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:494:19:494:24 | option | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:498:11:498:55 | options | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:498:21:498:55 | typeof ... option | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:498:50:498:55 | option | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:501:69:501:75 | options | +| unsafe-jquery-plugin.js:2:38:2:44 | options | +| unsafe-jquery-plugin.js:2:38:2:44 | options | +| unsafe-jquery-plugin.js:3:5:3:11 | options | +| unsafe-jquery-plugin.js:3:5:3:11 | options | +| unsafe-jquery-plugin.js:5:5:5:11 | options | +| unsafe-jquery-plugin.js:5:5:5:18 | options.target | +| unsafe-jquery-plugin.js:5:5:5:18 | options.target | +| unsafe-jquery-plugin.js:11:7:11:29 | target | +| unsafe-jquery-plugin.js:11:16:11:22 | options | +| unsafe-jquery-plugin.js:11:16:11:29 | options.target | +| unsafe-jquery-plugin.js:22:6:22:11 | target | +| unsafe-jquery-plugin.js:22:6:22:11 | target | +| unsafe-jquery-plugin.js:30:6:30:11 | target | +| unsafe-jquery-plugin.js:30:6:30:11 | target | +| unsafe-jquery-plugin.js:36:6:36:11 | target | +| unsafe-jquery-plugin.js:36:6:36:11 | target | +| unsafe-jquery-plugin.js:40:6:40:11 | target | +| unsafe-jquery-plugin.js:40:6:40:11 | target | +| unsafe-jquery-plugin.js:48:6:48:11 | target | +| unsafe-jquery-plugin.js:48:6:48:11 | target | +| unsafe-jquery-plugin.js:52:6:52:11 | target | +| unsafe-jquery-plugin.js:52:6:52:11 | target | +| unsafe-jquery-plugin.js:60:6:60:11 | target | +| unsafe-jquery-plugin.js:60:6:60:11 | target | +| unsafe-jquery-plugin.js:65:47:65:53 | options | +| unsafe-jquery-plugin.js:65:47:65:53 | options | +| unsafe-jquery-plugin.js:67:24:67:44 | $.exten ... ptions) | +| unsafe-jquery-plugin.js:67:33:67:34 | {} | +| unsafe-jquery-plugin.js:67:37:67:43 | options | +| unsafe-jquery-plugin.js:68:45:68:56 | this.options | +| unsafe-jquery-plugin.js:68:45:68:63 | this.options.parent | +| unsafe-jquery-plugin.js:68:45:68:63 | this.options.parent | +| unsafe-jquery-plugin.js:71:38:71:44 | options | +| unsafe-jquery-plugin.js:71:38:71:44 | options | +| unsafe-jquery-plugin.js:72:5:72:11 | options | +| unsafe-jquery-plugin.js:72:5:72:15 | options.foo | +| unsafe-jquery-plugin.js:72:5:72:19 | options.foo.bar | +| unsafe-jquery-plugin.js:72:5:72:23 | options.foo.bar.baz | +| unsafe-jquery-plugin.js:72:5:72:23 | options.foo.bar.baz | +| unsafe-jquery-plugin.js:76:38:76:44 | options | +| unsafe-jquery-plugin.js:76:38:76:44 | options | +| unsafe-jquery-plugin.js:77:17:77:23 | options | +| unsafe-jquery-plugin.js:77:17:77:27 | options.foo | +| unsafe-jquery-plugin.js:77:17:77:31 | options.foo.bar | +| unsafe-jquery-plugin.js:77:17:77:35 | options.foo.bar.baz | +| unsafe-jquery-plugin.js:77:17:77:35 | options.foo.bar.baz | +| unsafe-jquery-plugin.js:84:38:84:44 | options | +| unsafe-jquery-plugin.js:84:38:84:44 | options | +| unsafe-jquery-plugin.js:85:14:85:14 | o | +| unsafe-jquery-plugin.js:86:13:86:27 | $.extend({}, o) | +| unsafe-jquery-plugin.js:86:22:86:23 | {} | +| unsafe-jquery-plugin.js:86:26:86:26 | o | +| unsafe-jquery-plugin.js:87:8:87:24 | t | +| unsafe-jquery-plugin.js:87:12:87:17 | this.o | +| unsafe-jquery-plugin.js:87:12:87:24 | this.o.target | +| unsafe-jquery-plugin.js:90:6:90:6 | t | +| unsafe-jquery-plugin.js:90:6:90:6 | t | +| unsafe-jquery-plugin.js:92:5:92:11 | options | +| unsafe-jquery-plugin.js:101:38:101:44 | options | +| unsafe-jquery-plugin.js:101:38:101:44 | options | +| unsafe-jquery-plugin.js:102:3:105:13 | options | +| unsafe-jquery-plugin.js:102:13:105:13 | $.exten ... ptions) | +| unsafe-jquery-plugin.js:102:22:105:3 | {\\n\\t\\t\\tme ... in'\\n\\t\\t} | +| unsafe-jquery-plugin.js:105:6:105:12 | options | +| unsafe-jquery-plugin.js:106:5:106:11 | options | +| unsafe-jquery-plugin.js:106:5:106:16 | options.menu | +| unsafe-jquery-plugin.js:106:5:106:16 | options.menu | +| unsafe-jquery-plugin.js:107:5:107:11 | options | +| unsafe-jquery-plugin.js:107:5:107:18 | options.target | +| unsafe-jquery-plugin.js:107:5:107:18 | options.target | +| unsafe-jquery-plugin.js:114:38:114:44 | options | +| unsafe-jquery-plugin.js:114:38:114:44 | options | +| unsafe-jquery-plugin.js:115:3:115:58 | options | +| unsafe-jquery-plugin.js:115:13:115:58 | $.exten ... ptions) | +| unsafe-jquery-plugin.js:115:22:115:23 | {} | +| unsafe-jquery-plugin.js:115:51:115:57 | options | +| unsafe-jquery-plugin.js:116:5:116:11 | options | +| unsafe-jquery-plugin.js:116:5:116:16 | options.menu | +| unsafe-jquery-plugin.js:116:5:116:16 | options.menu | +| unsafe-jquery-plugin.js:117:5:117:11 | options | +| unsafe-jquery-plugin.js:117:5:117:18 | options.target | +| unsafe-jquery-plugin.js:117:5:117:18 | options.target | +| unsafe-jquery-plugin.js:121:40:121:46 | options | +| unsafe-jquery-plugin.js:121:40:121:46 | options | +| unsafe-jquery-plugin.js:122:5:122:11 | options | +| unsafe-jquery-plugin.js:122:5:122:18 | options.target | +| unsafe-jquery-plugin.js:122:5:122:18 | options.target | +| unsafe-jquery-plugin.js:126:33:126:39 | options | +| unsafe-jquery-plugin.js:126:33:126:39 | options | +| unsafe-jquery-plugin.js:127:6:127:12 | options | +| unsafe-jquery-plugin.js:127:6:127:19 | options.target | +| unsafe-jquery-plugin.js:127:6:127:19 | options.target | +| unsafe-jquery-plugin.js:131:34:131:40 | options | +| unsafe-jquery-plugin.js:131:34:131:40 | options | +| unsafe-jquery-plugin.js:132:5:132:11 | options | +| unsafe-jquery-plugin.js:132:5:132:18 | options.target | +| unsafe-jquery-plugin.js:132:5:132:18 | options.target | +| unsafe-jquery-plugin.js:135:36:135:42 | options | +| unsafe-jquery-plugin.js:135:36:135:42 | options | +| unsafe-jquery-plugin.js:136:5:136:11 | options | +| unsafe-jquery-plugin.js:136:5:136:20 | options.viewport | +| unsafe-jquery-plugin.js:136:5:136:29 | options ... elector | +| unsafe-jquery-plugin.js:136:5:136:29 | options ... elector | +| unsafe-jquery-plugin.js:153:38:153:44 | options | +| unsafe-jquery-plugin.js:153:38:153:44 | options | +| unsafe-jquery-plugin.js:154:7:154:29 | target | +| unsafe-jquery-plugin.js:154:16:154:22 | options | +| unsafe-jquery-plugin.js:154:16:154:29 | options.target | +| unsafe-jquery-plugin.js:155:33:155:38 | target | +| unsafe-jquery-plugin.js:155:33:155:38 | target | +| unsafe-jquery-plugin.js:156:41:156:47 | options | +| unsafe-jquery-plugin.js:156:41:156:54 | options.target | +| unsafe-jquery-plugin.js:156:41:156:54 | options.target | +| unsafe-jquery-plugin.js:157:44:157:50 | options | +| unsafe-jquery-plugin.js:157:44:157:57 | options.target | +| unsafe-jquery-plugin.js:157:44:157:59 | options.target.a | +| unsafe-jquery-plugin.js:157:44:157:59 | options.target.a | +edges +| DELETE_ME/bootstrap-post-27047_src/affix.js:16:34:16:40 | options | DELETE_ME/bootstrap-post-27047_src/affix.js:17:49:17:55 | options | +| DELETE_ME/bootstrap-post-27047_src/affix.js:17:20:17:56 | $.exten ... ptions) | DELETE_ME/bootstrap-post-27047_src/affix.js:19:68:19:79 | this.options | +| DELETE_ME/bootstrap-post-27047_src/affix.js:17:29:17:30 | {} | DELETE_ME/bootstrap-post-27047_src/affix.js:17:20:17:56 | $.exten ... ptions) | +| DELETE_ME/bootstrap-post-27047_src/affix.js:17:49:17:55 | options | DELETE_ME/bootstrap-post-27047_src/affix.js:17:20:17:56 | $.exten ... ptions) | +| DELETE_ME/bootstrap-post-27047_src/affix.js:17:49:17:55 | options | DELETE_ME/bootstrap-post-27047_src/affix.js:17:29:17:30 | {} | +| DELETE_ME/bootstrap-post-27047_src/affix.js:19:68:19:79 | this.options | DELETE_ME/bootstrap-post-27047_src/affix.js:19:68:19:86 | this.options.target | +| DELETE_ME/bootstrap-post-27047_src/affix.js:19:68:19:79 | this.options | DELETE_ME/bootstrap-post-27047_src/affix.js:19:68:19:86 | this.options.target | +| DELETE_ME/bootstrap-post-27047_src/affix.js:121:19:121:24 | option | DELETE_ME/bootstrap-post-27047_src/affix.js:125:50:125:55 | option | +| DELETE_ME/bootstrap-post-27047_src/affix.js:121:19:121:24 | option | DELETE_ME/bootstrap-post-27047_src/affix.js:125:50:125:55 | option | +| DELETE_ME/bootstrap-post-27047_src/affix.js:125:11:125:55 | options | DELETE_ME/bootstrap-post-27047_src/affix.js:127:65:127:71 | options | +| DELETE_ME/bootstrap-post-27047_src/affix.js:125:21:125:55 | typeof ... option | DELETE_ME/bootstrap-post-27047_src/affix.js:125:11:125:55 | options | +| DELETE_ME/bootstrap-post-27047_src/affix.js:125:50:125:55 | option | DELETE_ME/bootstrap-post-27047_src/affix.js:125:21:125:55 | typeof ... option | +| DELETE_ME/bootstrap-post-27047_src/affix.js:127:65:127:71 | options | DELETE_ME/bootstrap-post-27047_src/affix.js:16:34:16:40 | options | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:16:31:16:37 | options | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:19:60:19:66 | options | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:19:27:19:67 | $.exten ... ptions) | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:28:20:39 | this.options | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:19:36:19:37 | {} | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:19:27:19:67 | $.exten ... ptions) | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:19:60:19:66 | options | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:19:27:19:67 | $.exten ... ptions) | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:19:60:19:66 | options | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:19:36:19:37 | {} | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:27:20:53 | (this.o ... \|\| '') | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:109:20:109:32 | this.selector | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:111:7:111:19 | this.selector | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:127:7:127:19 | this.selector | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:127:7:127:19 | this.selector | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:28:20:39 | this.options | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:28:20:46 | this.options.target | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:28:20:46 | this.options.target | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:28:20:52 | this.op ... t \|\| '' | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:28:20:52 | this.op ... t \|\| '' | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:27:20:53 | (this.o ... \|\| '') | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:109:9:111:47 | selector | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:113:20:113:27 | selector | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:109:9:111:47 | selector | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:113:20:113:27 | selector | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:109:20:109:32 | this.selector | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:109:20:111:47 | this.se ... + '"]' | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:109:20:111:47 | this.se ... + '"]' | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:109:9:111:47 | selector | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:111:7:111:19 | this.selector | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:109:20:111:47 | this.se ... + '"]' | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:136:19:136:24 | option | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:140:50:140:55 | option | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:136:19:136:24 | option | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:140:50:140:55 | option | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:140:11:140:55 | options | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:142:73:142:79 | options | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:140:21:140:55 | typeof ... option | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:140:11:140:55 | options | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:140:50:140:55 | option | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:140:21:140:55 | typeof ... option | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:142:73:142:79 | options | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:16:31:16:37 | options | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:16:34:16:40 | options | DELETE_ME/bootstrap-pre-27047_src/affix.js:17:49:17:55 | options | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:17:20:17:56 | $.exten ... ptions) | DELETE_ME/bootstrap-pre-27047_src/affix.js:19:22:19:33 | this.options | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:17:29:17:30 | {} | DELETE_ME/bootstrap-pre-27047_src/affix.js:17:20:17:56 | $.exten ... ptions) | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:17:49:17:55 | options | DELETE_ME/bootstrap-pre-27047_src/affix.js:17:20:17:56 | $.exten ... ptions) | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:17:49:17:55 | options | DELETE_ME/bootstrap-pre-27047_src/affix.js:17:29:17:30 | {} | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:19:22:19:33 | this.options | DELETE_ME/bootstrap-pre-27047_src/affix.js:19:22:19:40 | this.options.target | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:19:22:19:33 | this.options | DELETE_ME/bootstrap-pre-27047_src/affix.js:19:22:19:40 | this.options.target | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:119:19:119:24 | option | DELETE_ME/bootstrap-pre-27047_src/affix.js:123:50:123:55 | option | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:119:19:119:24 | option | DELETE_ME/bootstrap-pre-27047_src/affix.js:123:50:123:55 | option | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:123:11:123:55 | options | DELETE_ME/bootstrap-pre-27047_src/affix.js:125:65:125:71 | options | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:123:21:123:55 | typeof ... option | DELETE_ME/bootstrap-pre-27047_src/affix.js:123:11:123:55 | options | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:123:50:123:55 | option | DELETE_ME/bootstrap-pre-27047_src/affix.js:123:21:123:55 | typeof ... option | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:125:65:125:71 | options | DELETE_ME/bootstrap-pre-27047_src/affix.js:16:34:16:40 | options | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:17:37:17:43 | options | DELETE_ME/bootstrap-pre-27047_src/collapse.js:19:58:19:64 | options | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:19:26:19:65 | $.exten ... ptions) | DELETE_ME/bootstrap-pre-27047_src/collapse.js:140:14:140:25 | this.options | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:19:35:19:36 | {} | DELETE_ME/bootstrap-pre-27047_src/collapse.js:19:26:19:65 | $.exten ... ptions) | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:19:58:19:64 | options | DELETE_ME/bootstrap-pre-27047_src/collapse.js:19:26:19:65 | $.exten ... ptions) | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:19:58:19:64 | options | DELETE_ME/bootstrap-pre-27047_src/collapse.js:19:35:19:36 | {} | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:140:14:140:25 | this.options | DELETE_ME/bootstrap-pre-27047_src/collapse.js:140:14:140:32 | this.options.parent | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:140:14:140:25 | this.options | DELETE_ME/bootstrap-pre-27047_src/collapse.js:140:14:140:32 | this.options.parent | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:170:19:170:24 | option | DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:96:174:101 | option | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:170:19:170:24 | option | DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:96:174:101 | option | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:11:174:102 | options | DELETE_ME/bootstrap-pre-27047_src/collapse.js:177:71:177:77 | options | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:21:174:102 | $.exten ... option) | DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:11:174:102 | options | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:30:174:31 | {} | DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:21:174:102 | $.exten ... option) | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:67:174:101 | typeof ... option | DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:21:174:102 | $.exten ... option) | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:67:174:101 | typeof ... option | DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:30:174:31 | {} | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:96:174:101 | option | DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:67:174:101 | typeof ... option | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:177:71:177:77 | options | DELETE_ME/bootstrap-pre-27047_src/collapse.js:17:37:17:43 | options | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:16:31:16:37 | options | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:19:60:19:66 | options | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:19:27:19:67 | $.exten ... ptions) | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:28:20:39 | this.options | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:19:36:19:37 | {} | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:19:27:19:67 | $.exten ... ptions) | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:19:60:19:66 | options | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:19:27:19:67 | $.exten ... ptions) | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:19:60:19:66 | options | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:19:36:19:37 | {} | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:27:20:53 | (this.o ... \|\| '') | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:109:20:109:32 | this.selector | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:111:7:111:19 | this.selector | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:127:7:127:19 | this.selector | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:127:7:127:19 | this.selector | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:28:20:39 | this.options | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:28:20:46 | this.options.target | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:28:20:46 | this.options.target | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:28:20:52 | this.op ... t \|\| '' | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:28:20:52 | this.op ... t \|\| '' | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:27:20:53 | (this.o ... \|\| '') | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:109:9:111:47 | selector | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:113:20:113:27 | selector | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:109:9:111:47 | selector | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:113:20:113:27 | selector | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:109:20:109:32 | this.selector | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:109:20:111:47 | this.se ... + '"]' | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:109:20:111:47 | this.se ... + '"]' | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:109:9:111:47 | selector | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:111:7:111:19 | this.selector | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:109:20:111:47 | this.se ... + '"]' | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:136:19:136:24 | option | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:140:50:140:55 | option | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:136:19:136:24 | option | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:140:50:140:55 | option | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:140:11:140:55 | options | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:142:73:142:79 | options | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:140:21:140:55 | typeof ... option | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:140:11:140:55 | options | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:140:50:140:55 | option | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:140:21:140:55 | typeof ... option | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:142:73:142:79 | options | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:16:31:16:37 | options | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:17:36:17:42 | options | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:26:35:26:41 | options | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:26:35:26:41 | options | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:49:53:49:59 | options | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:49:53:49:59 | options | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:53:38:53:44 | options | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:53:22:53:45 | this.ge ... ptions) | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:149 | this.options | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:53:22:53:45 | this.ge ... ptions) | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:172:54:183 | this.options | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:53:22:53:45 | this.ge ... ptions) | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:207:46:207:57 | this.options | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:53:38:53:44 | options | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:53:22:53:45 | this.ge ... ptions) | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:137:54:193 | (this.o ... ewport) | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:49:54:193 | $.isFun ... ewport) | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:137:54:193 | (this.o ... ewport) | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:49:54:193 | $.isFun ... ewport) | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:149 | this.options | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:158 | this.op ... iewport | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:158 | this.op ... iewport | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:167 | this.op ... elector | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:167 | this.op ... elector | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:192 | this.op ... iewport | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:192 | this.op ... iewport | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:137:54:193 | (this.o ... ewport) | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:172:54:183 | this.options | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:172:54:192 | this.op ... iewport | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:172:54:192 | this.op ... iewport | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:192 | this.op ... iewport | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:207:46:207:57 | this.options | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:207:46:207:67 | this.op ... ntainer | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:207:46:207:57 | this.options | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:207:46:207:67 | this.op ... ntainer | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:494:19:494:24 | option | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:498:50:498:55 | option | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:494:19:494:24 | option | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:498:50:498:55 | option | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:498:11:498:55 | options | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:501:69:501:75 | options | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:498:21:498:55 | typeof ... option | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:498:11:498:55 | options | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:498:50:498:55 | option | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:498:21:498:55 | typeof ... option | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:501:69:501:75 | options | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:17:36:17:42 | options | +| unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:3:5:3:11 | options | +| unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:3:5:3:11 | options | +| unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:3:5:3:11 | options | +| unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:3:5:3:11 | options | +| unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:5:5:5:11 | options | +| unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:5:5:5:11 | options | +| unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:11:16:11:22 | options | +| unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:11:16:11:22 | options | +| unsafe-jquery-plugin.js:5:5:5:11 | options | unsafe-jquery-plugin.js:5:5:5:18 | options.target | +| unsafe-jquery-plugin.js:5:5:5:11 | options | unsafe-jquery-plugin.js:5:5:5:18 | options.target | +| unsafe-jquery-plugin.js:11:7:11:29 | target | unsafe-jquery-plugin.js:22:6:22:11 | target | +| unsafe-jquery-plugin.js:11:7:11:29 | target | unsafe-jquery-plugin.js:22:6:22:11 | target | +| unsafe-jquery-plugin.js:11:7:11:29 | target | unsafe-jquery-plugin.js:30:6:30:11 | target | +| unsafe-jquery-plugin.js:11:7:11:29 | target | unsafe-jquery-plugin.js:30:6:30:11 | target | +| unsafe-jquery-plugin.js:11:7:11:29 | target | unsafe-jquery-plugin.js:36:6:36:11 | target | +| unsafe-jquery-plugin.js:11:7:11:29 | target | unsafe-jquery-plugin.js:36:6:36:11 | target | +| unsafe-jquery-plugin.js:11:7:11:29 | target | unsafe-jquery-plugin.js:40:6:40:11 | target | +| unsafe-jquery-plugin.js:11:7:11:29 | target | unsafe-jquery-plugin.js:40:6:40:11 | target | +| unsafe-jquery-plugin.js:11:7:11:29 | target | unsafe-jquery-plugin.js:48:6:48:11 | target | +| unsafe-jquery-plugin.js:11:7:11:29 | target | unsafe-jquery-plugin.js:48:6:48:11 | target | +| unsafe-jquery-plugin.js:11:7:11:29 | target | unsafe-jquery-plugin.js:52:6:52:11 | target | +| unsafe-jquery-plugin.js:11:7:11:29 | target | unsafe-jquery-plugin.js:52:6:52:11 | target | +| unsafe-jquery-plugin.js:11:7:11:29 | target | unsafe-jquery-plugin.js:60:6:60:11 | target | +| unsafe-jquery-plugin.js:11:7:11:29 | target | unsafe-jquery-plugin.js:60:6:60:11 | target | +| unsafe-jquery-plugin.js:11:16:11:22 | options | unsafe-jquery-plugin.js:11:16:11:29 | options.target | +| unsafe-jquery-plugin.js:11:16:11:29 | options.target | unsafe-jquery-plugin.js:11:7:11:29 | target | +| unsafe-jquery-plugin.js:65:47:65:53 | options | unsafe-jquery-plugin.js:67:37:67:43 | options | +| unsafe-jquery-plugin.js:65:47:65:53 | options | unsafe-jquery-plugin.js:67:37:67:43 | options | +| unsafe-jquery-plugin.js:67:24:67:44 | $.exten ... ptions) | unsafe-jquery-plugin.js:68:45:68:56 | this.options | +| unsafe-jquery-plugin.js:67:33:67:34 | {} | unsafe-jquery-plugin.js:67:24:67:44 | $.exten ... ptions) | +| unsafe-jquery-plugin.js:67:37:67:43 | options | unsafe-jquery-plugin.js:67:24:67:44 | $.exten ... ptions) | +| unsafe-jquery-plugin.js:67:37:67:43 | options | unsafe-jquery-plugin.js:67:33:67:34 | {} | +| unsafe-jquery-plugin.js:68:45:68:56 | this.options | unsafe-jquery-plugin.js:68:45:68:63 | this.options.parent | +| unsafe-jquery-plugin.js:68:45:68:56 | this.options | unsafe-jquery-plugin.js:68:45:68:63 | this.options.parent | +| unsafe-jquery-plugin.js:71:38:71:44 | options | unsafe-jquery-plugin.js:72:5:72:11 | options | +| unsafe-jquery-plugin.js:71:38:71:44 | options | unsafe-jquery-plugin.js:72:5:72:11 | options | +| unsafe-jquery-plugin.js:72:5:72:11 | options | unsafe-jquery-plugin.js:72:5:72:15 | options.foo | +| unsafe-jquery-plugin.js:72:5:72:15 | options.foo | unsafe-jquery-plugin.js:72:5:72:19 | options.foo.bar | +| unsafe-jquery-plugin.js:72:5:72:19 | options.foo.bar | unsafe-jquery-plugin.js:72:5:72:23 | options.foo.bar.baz | +| unsafe-jquery-plugin.js:72:5:72:19 | options.foo.bar | unsafe-jquery-plugin.js:72:5:72:23 | options.foo.bar.baz | +| unsafe-jquery-plugin.js:76:38:76:44 | options | unsafe-jquery-plugin.js:77:17:77:23 | options | +| unsafe-jquery-plugin.js:76:38:76:44 | options | unsafe-jquery-plugin.js:77:17:77:23 | options | +| unsafe-jquery-plugin.js:77:17:77:23 | options | unsafe-jquery-plugin.js:77:17:77:27 | options.foo | +| unsafe-jquery-plugin.js:77:17:77:27 | options.foo | unsafe-jquery-plugin.js:77:17:77:31 | options.foo.bar | +| unsafe-jquery-plugin.js:77:17:77:31 | options.foo.bar | unsafe-jquery-plugin.js:77:17:77:35 | options.foo.bar.baz | +| unsafe-jquery-plugin.js:77:17:77:31 | options.foo.bar | unsafe-jquery-plugin.js:77:17:77:35 | options.foo.bar.baz | +| unsafe-jquery-plugin.js:84:38:84:44 | options | unsafe-jquery-plugin.js:92:5:92:11 | options | +| unsafe-jquery-plugin.js:84:38:84:44 | options | unsafe-jquery-plugin.js:92:5:92:11 | options | +| unsafe-jquery-plugin.js:85:14:85:14 | o | unsafe-jquery-plugin.js:86:26:86:26 | o | +| unsafe-jquery-plugin.js:86:13:86:27 | $.extend({}, o) | unsafe-jquery-plugin.js:87:12:87:17 | this.o | +| unsafe-jquery-plugin.js:86:22:86:23 | {} | unsafe-jquery-plugin.js:86:13:86:27 | $.extend({}, o) | +| unsafe-jquery-plugin.js:86:26:86:26 | o | unsafe-jquery-plugin.js:86:13:86:27 | $.extend({}, o) | +| unsafe-jquery-plugin.js:86:26:86:26 | o | unsafe-jquery-plugin.js:86:22:86:23 | {} | +| unsafe-jquery-plugin.js:87:8:87:24 | t | unsafe-jquery-plugin.js:90:6:90:6 | t | +| unsafe-jquery-plugin.js:87:8:87:24 | t | unsafe-jquery-plugin.js:90:6:90:6 | t | +| unsafe-jquery-plugin.js:87:12:87:17 | this.o | unsafe-jquery-plugin.js:87:12:87:24 | this.o.target | +| unsafe-jquery-plugin.js:87:12:87:24 | this.o.target | unsafe-jquery-plugin.js:87:8:87:24 | t | +| unsafe-jquery-plugin.js:92:5:92:11 | options | unsafe-jquery-plugin.js:85:14:85:14 | o | +| unsafe-jquery-plugin.js:101:38:101:44 | options | unsafe-jquery-plugin.js:105:6:105:12 | options | +| unsafe-jquery-plugin.js:101:38:101:44 | options | unsafe-jquery-plugin.js:105:6:105:12 | options | +| unsafe-jquery-plugin.js:102:3:105:13 | options | unsafe-jquery-plugin.js:106:5:106:11 | options | +| unsafe-jquery-plugin.js:102:3:105:13 | options | unsafe-jquery-plugin.js:107:5:107:11 | options | +| unsafe-jquery-plugin.js:102:13:105:13 | $.exten ... ptions) | unsafe-jquery-plugin.js:102:3:105:13 | options | +| unsafe-jquery-plugin.js:102:22:105:3 | {\\n\\t\\t\\tme ... in'\\n\\t\\t} | unsafe-jquery-plugin.js:102:13:105:13 | $.exten ... ptions) | +| unsafe-jquery-plugin.js:105:6:105:12 | options | unsafe-jquery-plugin.js:102:13:105:13 | $.exten ... ptions) | +| unsafe-jquery-plugin.js:105:6:105:12 | options | unsafe-jquery-plugin.js:102:22:105:3 | {\\n\\t\\t\\tme ... in'\\n\\t\\t} | +| unsafe-jquery-plugin.js:106:5:106:11 | options | unsafe-jquery-plugin.js:106:5:106:16 | options.menu | +| unsafe-jquery-plugin.js:106:5:106:11 | options | unsafe-jquery-plugin.js:106:5:106:16 | options.menu | +| unsafe-jquery-plugin.js:107:5:107:11 | options | unsafe-jquery-plugin.js:107:5:107:18 | options.target | +| unsafe-jquery-plugin.js:107:5:107:11 | options | unsafe-jquery-plugin.js:107:5:107:18 | options.target | +| unsafe-jquery-plugin.js:114:38:114:44 | options | unsafe-jquery-plugin.js:115:51:115:57 | options | +| unsafe-jquery-plugin.js:114:38:114:44 | options | unsafe-jquery-plugin.js:115:51:115:57 | options | +| unsafe-jquery-plugin.js:115:3:115:58 | options | unsafe-jquery-plugin.js:116:5:116:11 | options | +| unsafe-jquery-plugin.js:115:3:115:58 | options | unsafe-jquery-plugin.js:117:5:117:11 | options | +| unsafe-jquery-plugin.js:115:13:115:58 | $.exten ... ptions) | unsafe-jquery-plugin.js:115:3:115:58 | options | +| unsafe-jquery-plugin.js:115:22:115:23 | {} | unsafe-jquery-plugin.js:115:13:115:58 | $.exten ... ptions) | +| unsafe-jquery-plugin.js:115:51:115:57 | options | unsafe-jquery-plugin.js:115:13:115:58 | $.exten ... ptions) | +| unsafe-jquery-plugin.js:115:51:115:57 | options | unsafe-jquery-plugin.js:115:22:115:23 | {} | +| unsafe-jquery-plugin.js:116:5:116:11 | options | unsafe-jquery-plugin.js:116:5:116:16 | options.menu | +| unsafe-jquery-plugin.js:116:5:116:11 | options | unsafe-jquery-plugin.js:116:5:116:16 | options.menu | +| unsafe-jquery-plugin.js:117:5:117:11 | options | unsafe-jquery-plugin.js:117:5:117:18 | options.target | +| unsafe-jquery-plugin.js:117:5:117:11 | options | unsafe-jquery-plugin.js:117:5:117:18 | options.target | +| unsafe-jquery-plugin.js:121:40:121:46 | options | unsafe-jquery-plugin.js:122:5:122:11 | options | +| unsafe-jquery-plugin.js:121:40:121:46 | options | unsafe-jquery-plugin.js:122:5:122:11 | options | +| unsafe-jquery-plugin.js:122:5:122:11 | options | unsafe-jquery-plugin.js:122:5:122:18 | options.target | +| unsafe-jquery-plugin.js:122:5:122:11 | options | unsafe-jquery-plugin.js:122:5:122:18 | options.target | +| unsafe-jquery-plugin.js:126:33:126:39 | options | unsafe-jquery-plugin.js:127:6:127:12 | options | +| unsafe-jquery-plugin.js:126:33:126:39 | options | unsafe-jquery-plugin.js:127:6:127:12 | options | +| unsafe-jquery-plugin.js:127:6:127:12 | options | unsafe-jquery-plugin.js:127:6:127:19 | options.target | +| unsafe-jquery-plugin.js:127:6:127:12 | options | unsafe-jquery-plugin.js:127:6:127:19 | options.target | +| unsafe-jquery-plugin.js:131:34:131:40 | options | unsafe-jquery-plugin.js:132:5:132:11 | options | +| unsafe-jquery-plugin.js:131:34:131:40 | options | unsafe-jquery-plugin.js:132:5:132:11 | options | +| unsafe-jquery-plugin.js:132:5:132:11 | options | unsafe-jquery-plugin.js:132:5:132:18 | options.target | +| unsafe-jquery-plugin.js:132:5:132:11 | options | unsafe-jquery-plugin.js:132:5:132:18 | options.target | +| unsafe-jquery-plugin.js:135:36:135:42 | options | unsafe-jquery-plugin.js:136:5:136:11 | options | +| unsafe-jquery-plugin.js:135:36:135:42 | options | unsafe-jquery-plugin.js:136:5:136:11 | options | +| unsafe-jquery-plugin.js:136:5:136:11 | options | unsafe-jquery-plugin.js:136:5:136:20 | options.viewport | +| unsafe-jquery-plugin.js:136:5:136:20 | options.viewport | unsafe-jquery-plugin.js:136:5:136:29 | options ... elector | +| unsafe-jquery-plugin.js:136:5:136:20 | options.viewport | unsafe-jquery-plugin.js:136:5:136:29 | options ... elector | +| unsafe-jquery-plugin.js:153:38:153:44 | options | unsafe-jquery-plugin.js:154:16:154:22 | options | +| unsafe-jquery-plugin.js:153:38:153:44 | options | unsafe-jquery-plugin.js:154:16:154:22 | options | +| unsafe-jquery-plugin.js:153:38:153:44 | options | unsafe-jquery-plugin.js:156:41:156:47 | options | +| unsafe-jquery-plugin.js:153:38:153:44 | options | unsafe-jquery-plugin.js:156:41:156:47 | options | +| unsafe-jquery-plugin.js:153:38:153:44 | options | unsafe-jquery-plugin.js:157:44:157:50 | options | +| unsafe-jquery-plugin.js:153:38:153:44 | options | unsafe-jquery-plugin.js:157:44:157:50 | options | +| unsafe-jquery-plugin.js:154:7:154:29 | target | unsafe-jquery-plugin.js:155:33:155:38 | target | +| unsafe-jquery-plugin.js:154:7:154:29 | target | unsafe-jquery-plugin.js:155:33:155:38 | target | +| unsafe-jquery-plugin.js:154:16:154:22 | options | unsafe-jquery-plugin.js:154:16:154:29 | options.target | +| unsafe-jquery-plugin.js:154:16:154:29 | options.target | unsafe-jquery-plugin.js:154:7:154:29 | target | +| unsafe-jquery-plugin.js:156:41:156:47 | options | unsafe-jquery-plugin.js:156:41:156:54 | options.target | +| unsafe-jquery-plugin.js:156:41:156:47 | options | unsafe-jquery-plugin.js:156:41:156:54 | options.target | +| unsafe-jquery-plugin.js:157:44:157:50 | options | unsafe-jquery-plugin.js:157:44:157:57 | options.target | +| unsafe-jquery-plugin.js:157:44:157:57 | options.target | unsafe-jquery-plugin.js:157:44:157:59 | options.target.a | +| unsafe-jquery-plugin.js:157:44:157:57 | options.target | unsafe-jquery-plugin.js:157:44:157:59 | options.target.a | +#select +| DELETE_ME/bootstrap-post-27047_src/affix.js:19:68:19:86 | this.options.target | DELETE_ME/bootstrap-post-27047_src/affix.js:121:19:121:24 | option | DELETE_ME/bootstrap-post-27047_src/affix.js:19:68:19:86 | this.options.target | Potential XSS vulnerability in the $@. | DELETE_ME/bootstrap-post-27047_src/affix.js:121:3:130:3 | functio ... })\\n } | '$.fn.affix' plugin | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:113:20:113:27 | selector | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:136:19:136:24 | option | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:113:20:113:27 | selector | Potential XSS vulnerability in the $@. | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:136:3:145:3 | functio ... })\\n } | '$.fn.scrollspy' plugin | +| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:127:7:127:19 | this.selector | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:136:19:136:24 | option | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:127:7:127:19 | this.selector | Potential XSS vulnerability in the $@. | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:136:3:145:3 | functio ... })\\n } | '$.fn.scrollspy' plugin | +| DELETE_ME/bootstrap-pre-27047_src/affix.js:19:22:19:40 | this.options.target | DELETE_ME/bootstrap-pre-27047_src/affix.js:119:19:119:24 | option | DELETE_ME/bootstrap-pre-27047_src/affix.js:19:22:19:40 | this.options.target | Potential XSS vulnerability in the $@. | DELETE_ME/bootstrap-pre-27047_src/affix.js:119:3:128:3 | functio ... })\\n } | '$.fn.affix' plugin | +| DELETE_ME/bootstrap-pre-27047_src/collapse.js:140:14:140:32 | this.options.parent | DELETE_ME/bootstrap-pre-27047_src/collapse.js:170:19:170:24 | option | DELETE_ME/bootstrap-pre-27047_src/collapse.js:140:14:140:32 | this.options.parent | Potential XSS vulnerability in the $@. | DELETE_ME/bootstrap-pre-27047_src/collapse.js:170:3:180:3 | functio ... })\\n } | '$.fn.collapse' plugin | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:113:20:113:27 | selector | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:136:19:136:24 | option | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:113:20:113:27 | selector | Potential XSS vulnerability in the $@. | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:136:3:145:3 | functio ... })\\n } | '$.fn.scrollspy' plugin | +| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:127:7:127:19 | this.selector | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:136:19:136:24 | option | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:127:7:127:19 | this.selector | Potential XSS vulnerability in the $@. | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:136:3:145:3 | functio ... })\\n } | '$.fn.scrollspy' plugin | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:49:54:193 | $.isFun ... ewport) | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:494:19:494:24 | option | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:49:54:193 | $.isFun ... ewport) | Potential XSS vulnerability in the $@. | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:494:3:504:3 | functio ... })\\n } | '$.fn.tooltip' plugin | +| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:207:46:207:67 | this.op ... ntainer | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:494:19:494:24 | option | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:207:46:207:67 | this.op ... ntainer | Potential XSS vulnerability in the $@. | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:494:3:504:3 | functio ... })\\n } | '$.fn.tooltip' plugin | +| unsafe-jquery-plugin.js:3:5:3:11 | options | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:3:5:3:11 | options | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:2:19:63:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:5:5:5:18 | options.target | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:5:5:5:18 | options.target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:2:19:63:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:22:6:22:11 | target | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:22:6:22:11 | target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:2:19:63:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:30:6:30:11 | target | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:30:6:30:11 | target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:2:19:63:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:36:6:36:11 | target | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:36:6:36:11 | target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:2:19:63:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:40:6:40:11 | target | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:40:6:40:11 | target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:2:19:63:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:48:6:48:11 | target | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:48:6:48:11 | target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:2:19:63:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:52:6:52:11 | target | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:52:6:52:11 | target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:2:19:63:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:60:6:60:11 | target | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:60:6:60:11 | target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:2:19:63:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:68:45:68:63 | this.options.parent | unsafe-jquery-plugin.js:65:47:65:53 | options | unsafe-jquery-plugin.js:68:45:68:63 | this.options.parent | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:65:19:69:2 | functio ... T OK\\n\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:72:5:72:23 | options.foo.bar.baz | unsafe-jquery-plugin.js:71:38:71:44 | options | unsafe-jquery-plugin.js:72:5:72:23 | options.foo.bar.baz | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:71:19:74:2 | functio ... / OK\\n\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:77:17:77:35 | options.foo.bar.baz | unsafe-jquery-plugin.js:76:38:76:44 | options | unsafe-jquery-plugin.js:77:17:77:35 | options.foo.bar.baz | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:76:19:78:2 | functio ... T OK\\n\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:90:6:90:6 | t | unsafe-jquery-plugin.js:84:38:84:44 | options | unsafe-jquery-plugin.js:90:6:90:6 | t | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:84:19:93:2 | functio ... ns);\\n\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:107:5:107:18 | options.target | unsafe-jquery-plugin.js:101:38:101:44 | options | unsafe-jquery-plugin.js:107:5:107:18 | options.target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:101:19:108:2 | functio ... T OK\\n\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:117:5:117:18 | options.target | unsafe-jquery-plugin.js:114:38:114:44 | options | unsafe-jquery-plugin.js:117:5:117:18 | options.target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:114:19:118:2 | functio ... T OK\\n\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:122:5:122:18 | options.target | unsafe-jquery-plugin.js:121:40:121:46 | options | unsafe-jquery-plugin.js:122:5:122:18 | options.target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:121:21:123:2 | functio ... T OK\\n\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:127:6:127:19 | options.target | unsafe-jquery-plugin.js:126:33:126:39 | options | unsafe-jquery-plugin.js:127:6:127:19 | options.target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:126:14:128:3 | functio ... OK\\n\\t\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:132:5:132:18 | options.target | unsafe-jquery-plugin.js:131:34:131:40 | options | unsafe-jquery-plugin.js:132:5:132:18 | options.target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:131:15:133:2 | functio ... T OK\\n\\t} | '$.fn.affix' plugin | +| unsafe-jquery-plugin.js:136:5:136:29 | options ... elector | unsafe-jquery-plugin.js:135:36:135:42 | options | unsafe-jquery-plugin.js:136:5:136:29 | options ... elector | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:135:17:137:2 | functio ... T OK\\n\\t} | '$.fn.tooltip' plugin | +| unsafe-jquery-plugin.js:155:33:155:38 | target | unsafe-jquery-plugin.js:153:38:153:44 | options | unsafe-jquery-plugin.js:155:33:155:38 | target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:153:19:158:2 | functio ... gged\\n\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:156:41:156:54 | options.target | unsafe-jquery-plugin.js:153:38:153:44 | options | unsafe-jquery-plugin.js:156:41:156:54 | options.target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:153:19:158:2 | functio ... gged\\n\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:157:44:157:59 | options.target.a | unsafe-jquery-plugin.js:153:38:153:44 | options | unsafe-jquery-plugin.js:157:44:157:59 | options.target.a | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:153:19:158:2 | functio ... gged\\n\\t} | '$.fn.my_plugin' plugin | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.qlref b/javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.qlref new file mode 100644 index 00000000000..66c19069e07 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.qlref @@ -0,0 +1 @@ +Security/CWE-079/UnsafeJQueryPlugin.ql \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Security/CWE-079/unsafe-jquery-plugin.js b/javascript/ql/test/query-tests/Security/CWE-079/unsafe-jquery-plugin.js new file mode 100644 index 00000000000..60049e9218c --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-079/unsafe-jquery-plugin.js @@ -0,0 +1,159 @@ +(function(){ + $.fn.my_plugin = function my_plugin(options) { + $(options); // NOT OK (or is it?) + + $(options.target); // NOT OK + + if (isElement(options.target)) { + $(options.target); // OK + } + + var target = options.target; + + if (isElement(target)) { + $(target); // OK + } + + if (typeof target != "string") { + $(target); // OK + } + + if (target.jquery === undefined) { + $(target); // NOT OK + } else { + $(target); // OK + } + + if (target.jquery !== undefined) { + $(target); // OK + } else { + $(target); // NOT OK + } + + if (typeof target.jquery !== "undefined") { + $(target); // OK + } else { + $(target); // NOT OK + } + + if (typeof target.jquery === "undefined") { + $(target); // NOT OK + } else { + $(target); // OK + } + + if (target.jquery) { + $(target); // OK + } else { + $(target); // NOT OK + } + + if (!target.jquery) { + $(target); // NOT OK + } else { + $(target); // OK + } + + if (!!target.jquery) { + $(target); // OK + } else { + $(target); // NOT OK + } + + }; + + $.fn.my_plugin = function my_plugin(element, options) { + this.$element = $(element); + this.options = $.extend({}, options); + if (this.options.parent) this.$parent = $(this.options.parent) // NOT OK + }; + + $.fn.my_plugin = function my_plugin(options) { + $(options.foo.bar.baz); // NOT OK + $(options.html); // OK + }; + + $.fn.my_plugin = function my_plugin(options) { + $(x).appendTo(options.foo.bar.baz); // NOT OK + }; + + $.fn.my_plugin = function my_plugin(options) { + $("#" + options.target); // OK + }; + + $.fn.my_plugin = function my_plugin(options) { + function f(o) { + this.o = $.extend({}, o); + var t = this.o.target; + + console.log(t); + $(t); // NOT OK + } + f(options); + }; + + $.fn.my_plugin = function my_plugin(options) { + var target = options.target; + if (safe.has(target)) + $(target); // OK + }; + + $.fn.my_plugin = function my_plugin(options) { + options = $.extend({ + menu: '
    ', + target: '.my_plugin' + }, options); + $(options.menu); // OK + $(options.target); // NOT OK + }; + + $.fn.my_plugin.defaults = { + menu: '
    ', + target: '.my_plugin' + }; + $.fn.my_plugin = function my_plugin(options) { + options = $.extend({}, $.fn.my_plugin.defaults, options); + $(options.menu); // OK + $(options.target); // NOT OK + }; + + var pluginName = "my_plugin"; + $.fn[pluginName] = function my_plugin(options) { + $(options.target); // NOT OK + }; + + $.extend($.fn, { + my_plugin: function my_plugin(options) { + $(options.target); // NOT OK + } + }); + + $.fn.affix = function my_plugin(options) { + $(options.target); // NOT OK + }; + + $.fn.tooltip = function my_plugin(options) { + $(options.viewport.selector); // NOT OK + }; + + $.fn.my_plugin = function my_plugin(options) { + let intentional1 = options.target || `
    hello
    `; + $(intentional1); // OK + + let intentional2 = `
    ${options.target}
    `; + $(intentional2); // OK + + let intentional3 = `
    ` + options.target `
    `; + $(intentional3); // OK + + let unintentional = `
    `; + $(unintentional); // OK - but should be flagged by another query + } + + $.fn.my_plugin = function my_plugin(options) { + let target = options.target; + target === DEFAULTS.target? $(target): $(document).find(target); // OK - but still flagged + options.target === DEFAULTS.target? $(options.target): $(document).find(options.target); // OK - but still flagged + options.targets.a === DEFAULTS.target? $(options.target.a): $(document).find(options.target.a); // OK - but still flagged + } +}); From 9e247921fc45c57778462a4e2d1b492e10278771 Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen Date: Mon, 27 Jan 2020 10:21:02 +0100 Subject: [PATCH 02/10] JS: add FP tests for js/unsafe-jquery-plugin --- .../CWE-079/UnsafeJQueryPlugin.expected | 271 +++--------------- .../Security/CWE-079/unsafe-jquery-plugin.js | 15 + 2 files changed, 54 insertions(+), 232 deletions(-) diff --git a/javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.expected b/javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.expected index b6cbaede45b..c212607846d 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.expected @@ -1,114 +1,4 @@ nodes -| DELETE_ME/bootstrap-post-27047_src/affix.js:16:34:16:40 | options | -| DELETE_ME/bootstrap-post-27047_src/affix.js:17:20:17:56 | $.exten ... ptions) | -| DELETE_ME/bootstrap-post-27047_src/affix.js:17:29:17:30 | {} | -| DELETE_ME/bootstrap-post-27047_src/affix.js:17:49:17:55 | options | -| DELETE_ME/bootstrap-post-27047_src/affix.js:19:68:19:79 | this.options | -| DELETE_ME/bootstrap-post-27047_src/affix.js:19:68:19:86 | this.options.target | -| DELETE_ME/bootstrap-post-27047_src/affix.js:19:68:19:86 | this.options.target | -| DELETE_ME/bootstrap-post-27047_src/affix.js:121:19:121:24 | option | -| DELETE_ME/bootstrap-post-27047_src/affix.js:121:19:121:24 | option | -| DELETE_ME/bootstrap-post-27047_src/affix.js:125:11:125:55 | options | -| DELETE_ME/bootstrap-post-27047_src/affix.js:125:21:125:55 | typeof ... option | -| DELETE_ME/bootstrap-post-27047_src/affix.js:125:50:125:55 | option | -| DELETE_ME/bootstrap-post-27047_src/affix.js:127:65:127:71 | options | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:16:31:16:37 | options | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:19:27:19:67 | $.exten ... ptions) | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:19:36:19:37 | {} | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:19:60:19:66 | options | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:27:20:53 | (this.o ... \|\| '') | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:28:20:39 | this.options | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:28:20:46 | this.options.target | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:28:20:52 | this.op ... t \|\| '' | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:109:9:111:47 | selector | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:109:20:109:32 | this.selector | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:109:20:111:47 | this.se ... + '"]' | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:111:7:111:19 | this.selector | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:113:20:113:27 | selector | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:113:20:113:27 | selector | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:127:7:127:19 | this.selector | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:127:7:127:19 | this.selector | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:136:19:136:24 | option | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:136:19:136:24 | option | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:140:11:140:55 | options | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:140:21:140:55 | typeof ... option | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:140:50:140:55 | option | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:142:73:142:79 | options | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:16:34:16:40 | options | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:17:20:17:56 | $.exten ... ptions) | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:17:29:17:30 | {} | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:17:49:17:55 | options | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:19:22:19:33 | this.options | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:19:22:19:40 | this.options.target | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:19:22:19:40 | this.options.target | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:119:19:119:24 | option | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:119:19:119:24 | option | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:123:11:123:55 | options | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:123:21:123:55 | typeof ... option | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:123:50:123:55 | option | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:125:65:125:71 | options | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:17:37:17:43 | options | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:19:26:19:65 | $.exten ... ptions) | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:19:35:19:36 | {} | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:19:58:19:64 | options | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:140:14:140:25 | this.options | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:140:14:140:32 | this.options.parent | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:140:14:140:32 | this.options.parent | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:170:19:170:24 | option | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:170:19:170:24 | option | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:11:174:102 | options | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:21:174:102 | $.exten ... option) | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:30:174:31 | {} | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:67:174:101 | typeof ... option | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:96:174:101 | option | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:177:71:177:77 | options | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:16:31:16:37 | options | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:19:27:19:67 | $.exten ... ptions) | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:19:36:19:37 | {} | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:19:60:19:66 | options | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:27:20:53 | (this.o ... \|\| '') | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:28:20:39 | this.options | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:28:20:46 | this.options.target | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:28:20:52 | this.op ... t \|\| '' | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:109:9:111:47 | selector | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:109:20:109:32 | this.selector | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:109:20:111:47 | this.se ... + '"]' | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:111:7:111:19 | this.selector | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:113:20:113:27 | selector | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:113:20:113:27 | selector | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:127:7:127:19 | this.selector | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:127:7:127:19 | this.selector | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:136:19:136:24 | option | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:136:19:136:24 | option | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:140:11:140:55 | options | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:140:21:140:55 | typeof ... option | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:140:50:140:55 | option | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:142:73:142:79 | options | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:17:36:17:42 | options | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:26:35:26:41 | options | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:49:53:49:59 | options | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:53:22:53:45 | this.ge ... ptions) | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:53:38:53:44 | options | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:49:54:193 | $.isFun ... ewport) | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:49:54:193 | $.isFun ... ewport) | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:137:54:193 | (this.o ... ewport) | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:149 | this.options | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:158 | this.op ... iewport | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:167 | this.op ... elector | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:192 | this.op ... iewport | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:172:54:183 | this.options | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:172:54:192 | this.op ... iewport | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:207:46:207:57 | this.options | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:207:46:207:67 | this.op ... ntainer | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:207:46:207:67 | this.op ... ntainer | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:494:19:494:24 | option | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:494:19:494:24 | option | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:498:11:498:55 | options | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:498:21:498:55 | typeof ... option | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:498:50:498:55 | option | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:501:69:501:75 | options | | unsafe-jquery-plugin.js:2:38:2:44 | options | | unsafe-jquery-plugin.js:2:38:2:44 | options | | unsafe-jquery-plugin.js:3:5:3:11 | options | @@ -226,120 +116,24 @@ nodes | unsafe-jquery-plugin.js:157:44:157:57 | options.target | | unsafe-jquery-plugin.js:157:44:157:59 | options.target.a | | unsafe-jquery-plugin.js:157:44:157:59 | options.target.a | +| unsafe-jquery-plugin.js:160:38:160:44 | options | +| unsafe-jquery-plugin.js:160:38:160:44 | options | +| unsafe-jquery-plugin.js:161:5:161:30 | anyPref ... .target | +| unsafe-jquery-plugin.js:161:5:161:30 | anyPref ... .target | +| unsafe-jquery-plugin.js:161:17:161:23 | options | +| unsafe-jquery-plugin.js:161:17:161:30 | options.target | +| unsafe-jquery-plugin.js:163:5:163:54 | somethi ... target) | +| unsafe-jquery-plugin.js:163:5:163:54 | somethi ... target) | +| unsafe-jquery-plugin.js:163:40:163:46 | options | +| unsafe-jquery-plugin.js:163:40:163:53 | options.target | +| unsafe-jquery-plugin.js:165:7:165:29 | target | +| unsafe-jquery-plugin.js:165:16:165:22 | options | +| unsafe-jquery-plugin.js:165:16:165:29 | options.target | +| unsafe-jquery-plugin.js:167:6:167:11 | target | +| unsafe-jquery-plugin.js:167:6:167:11 | target | +| unsafe-jquery-plugin.js:170:6:170:11 | target | +| unsafe-jquery-plugin.js:170:6:170:11 | target | edges -| DELETE_ME/bootstrap-post-27047_src/affix.js:16:34:16:40 | options | DELETE_ME/bootstrap-post-27047_src/affix.js:17:49:17:55 | options | -| DELETE_ME/bootstrap-post-27047_src/affix.js:17:20:17:56 | $.exten ... ptions) | DELETE_ME/bootstrap-post-27047_src/affix.js:19:68:19:79 | this.options | -| DELETE_ME/bootstrap-post-27047_src/affix.js:17:29:17:30 | {} | DELETE_ME/bootstrap-post-27047_src/affix.js:17:20:17:56 | $.exten ... ptions) | -| DELETE_ME/bootstrap-post-27047_src/affix.js:17:49:17:55 | options | DELETE_ME/bootstrap-post-27047_src/affix.js:17:20:17:56 | $.exten ... ptions) | -| DELETE_ME/bootstrap-post-27047_src/affix.js:17:49:17:55 | options | DELETE_ME/bootstrap-post-27047_src/affix.js:17:29:17:30 | {} | -| DELETE_ME/bootstrap-post-27047_src/affix.js:19:68:19:79 | this.options | DELETE_ME/bootstrap-post-27047_src/affix.js:19:68:19:86 | this.options.target | -| DELETE_ME/bootstrap-post-27047_src/affix.js:19:68:19:79 | this.options | DELETE_ME/bootstrap-post-27047_src/affix.js:19:68:19:86 | this.options.target | -| DELETE_ME/bootstrap-post-27047_src/affix.js:121:19:121:24 | option | DELETE_ME/bootstrap-post-27047_src/affix.js:125:50:125:55 | option | -| DELETE_ME/bootstrap-post-27047_src/affix.js:121:19:121:24 | option | DELETE_ME/bootstrap-post-27047_src/affix.js:125:50:125:55 | option | -| DELETE_ME/bootstrap-post-27047_src/affix.js:125:11:125:55 | options | DELETE_ME/bootstrap-post-27047_src/affix.js:127:65:127:71 | options | -| DELETE_ME/bootstrap-post-27047_src/affix.js:125:21:125:55 | typeof ... option | DELETE_ME/bootstrap-post-27047_src/affix.js:125:11:125:55 | options | -| DELETE_ME/bootstrap-post-27047_src/affix.js:125:50:125:55 | option | DELETE_ME/bootstrap-post-27047_src/affix.js:125:21:125:55 | typeof ... option | -| DELETE_ME/bootstrap-post-27047_src/affix.js:127:65:127:71 | options | DELETE_ME/bootstrap-post-27047_src/affix.js:16:34:16:40 | options | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:16:31:16:37 | options | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:19:60:19:66 | options | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:19:27:19:67 | $.exten ... ptions) | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:28:20:39 | this.options | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:19:36:19:37 | {} | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:19:27:19:67 | $.exten ... ptions) | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:19:60:19:66 | options | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:19:27:19:67 | $.exten ... ptions) | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:19:60:19:66 | options | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:19:36:19:37 | {} | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:27:20:53 | (this.o ... \|\| '') | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:109:20:109:32 | this.selector | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:111:7:111:19 | this.selector | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:127:7:127:19 | this.selector | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:127:7:127:19 | this.selector | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:28:20:39 | this.options | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:28:20:46 | this.options.target | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:28:20:46 | this.options.target | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:28:20:52 | this.op ... t \|\| '' | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:28:20:52 | this.op ... t \|\| '' | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:20:27:20:53 | (this.o ... \|\| '') | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:109:9:111:47 | selector | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:113:20:113:27 | selector | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:109:9:111:47 | selector | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:113:20:113:27 | selector | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:109:20:109:32 | this.selector | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:109:20:111:47 | this.se ... + '"]' | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:109:20:111:47 | this.se ... + '"]' | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:109:9:111:47 | selector | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:111:7:111:19 | this.selector | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:109:20:111:47 | this.se ... + '"]' | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:136:19:136:24 | option | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:140:50:140:55 | option | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:136:19:136:24 | option | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:140:50:140:55 | option | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:140:11:140:55 | options | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:142:73:142:79 | options | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:140:21:140:55 | typeof ... option | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:140:11:140:55 | options | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:140:50:140:55 | option | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:140:21:140:55 | typeof ... option | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:142:73:142:79 | options | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:16:31:16:37 | options | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:16:34:16:40 | options | DELETE_ME/bootstrap-pre-27047_src/affix.js:17:49:17:55 | options | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:17:20:17:56 | $.exten ... ptions) | DELETE_ME/bootstrap-pre-27047_src/affix.js:19:22:19:33 | this.options | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:17:29:17:30 | {} | DELETE_ME/bootstrap-pre-27047_src/affix.js:17:20:17:56 | $.exten ... ptions) | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:17:49:17:55 | options | DELETE_ME/bootstrap-pre-27047_src/affix.js:17:20:17:56 | $.exten ... ptions) | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:17:49:17:55 | options | DELETE_ME/bootstrap-pre-27047_src/affix.js:17:29:17:30 | {} | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:19:22:19:33 | this.options | DELETE_ME/bootstrap-pre-27047_src/affix.js:19:22:19:40 | this.options.target | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:19:22:19:33 | this.options | DELETE_ME/bootstrap-pre-27047_src/affix.js:19:22:19:40 | this.options.target | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:119:19:119:24 | option | DELETE_ME/bootstrap-pre-27047_src/affix.js:123:50:123:55 | option | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:119:19:119:24 | option | DELETE_ME/bootstrap-pre-27047_src/affix.js:123:50:123:55 | option | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:123:11:123:55 | options | DELETE_ME/bootstrap-pre-27047_src/affix.js:125:65:125:71 | options | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:123:21:123:55 | typeof ... option | DELETE_ME/bootstrap-pre-27047_src/affix.js:123:11:123:55 | options | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:123:50:123:55 | option | DELETE_ME/bootstrap-pre-27047_src/affix.js:123:21:123:55 | typeof ... option | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:125:65:125:71 | options | DELETE_ME/bootstrap-pre-27047_src/affix.js:16:34:16:40 | options | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:17:37:17:43 | options | DELETE_ME/bootstrap-pre-27047_src/collapse.js:19:58:19:64 | options | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:19:26:19:65 | $.exten ... ptions) | DELETE_ME/bootstrap-pre-27047_src/collapse.js:140:14:140:25 | this.options | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:19:35:19:36 | {} | DELETE_ME/bootstrap-pre-27047_src/collapse.js:19:26:19:65 | $.exten ... ptions) | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:19:58:19:64 | options | DELETE_ME/bootstrap-pre-27047_src/collapse.js:19:26:19:65 | $.exten ... ptions) | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:19:58:19:64 | options | DELETE_ME/bootstrap-pre-27047_src/collapse.js:19:35:19:36 | {} | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:140:14:140:25 | this.options | DELETE_ME/bootstrap-pre-27047_src/collapse.js:140:14:140:32 | this.options.parent | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:140:14:140:25 | this.options | DELETE_ME/bootstrap-pre-27047_src/collapse.js:140:14:140:32 | this.options.parent | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:170:19:170:24 | option | DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:96:174:101 | option | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:170:19:170:24 | option | DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:96:174:101 | option | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:11:174:102 | options | DELETE_ME/bootstrap-pre-27047_src/collapse.js:177:71:177:77 | options | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:21:174:102 | $.exten ... option) | DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:11:174:102 | options | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:30:174:31 | {} | DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:21:174:102 | $.exten ... option) | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:67:174:101 | typeof ... option | DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:21:174:102 | $.exten ... option) | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:67:174:101 | typeof ... option | DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:30:174:31 | {} | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:96:174:101 | option | DELETE_ME/bootstrap-pre-27047_src/collapse.js:174:67:174:101 | typeof ... option | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:177:71:177:77 | options | DELETE_ME/bootstrap-pre-27047_src/collapse.js:17:37:17:43 | options | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:16:31:16:37 | options | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:19:60:19:66 | options | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:19:27:19:67 | $.exten ... ptions) | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:28:20:39 | this.options | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:19:36:19:37 | {} | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:19:27:19:67 | $.exten ... ptions) | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:19:60:19:66 | options | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:19:27:19:67 | $.exten ... ptions) | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:19:60:19:66 | options | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:19:36:19:37 | {} | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:27:20:53 | (this.o ... \|\| '') | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:109:20:109:32 | this.selector | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:111:7:111:19 | this.selector | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:127:7:127:19 | this.selector | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:27:20:70 | (this.o ... li > a' | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:127:7:127:19 | this.selector | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:28:20:39 | this.options | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:28:20:46 | this.options.target | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:28:20:46 | this.options.target | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:28:20:52 | this.op ... t \|\| '' | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:28:20:52 | this.op ... t \|\| '' | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:20:27:20:53 | (this.o ... \|\| '') | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:109:9:111:47 | selector | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:113:20:113:27 | selector | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:109:9:111:47 | selector | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:113:20:113:27 | selector | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:109:20:109:32 | this.selector | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:109:20:111:47 | this.se ... + '"]' | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:109:20:111:47 | this.se ... + '"]' | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:109:9:111:47 | selector | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:111:7:111:19 | this.selector | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:109:20:111:47 | this.se ... + '"]' | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:136:19:136:24 | option | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:140:50:140:55 | option | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:136:19:136:24 | option | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:140:50:140:55 | option | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:140:11:140:55 | options | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:142:73:142:79 | options | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:140:21:140:55 | typeof ... option | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:140:11:140:55 | options | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:140:50:140:55 | option | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:140:21:140:55 | typeof ... option | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:142:73:142:79 | options | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:16:31:16:37 | options | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:17:36:17:42 | options | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:26:35:26:41 | options | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:26:35:26:41 | options | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:49:53:49:59 | options | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:49:53:49:59 | options | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:53:38:53:44 | options | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:53:22:53:45 | this.ge ... ptions) | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:149 | this.options | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:53:22:53:45 | this.ge ... ptions) | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:172:54:183 | this.options | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:53:22:53:45 | this.ge ... ptions) | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:207:46:207:57 | this.options | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:53:38:53:44 | options | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:53:22:53:45 | this.ge ... ptions) | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:137:54:193 | (this.o ... ewport) | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:49:54:193 | $.isFun ... ewport) | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:137:54:193 | (this.o ... ewport) | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:49:54:193 | $.isFun ... ewport) | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:149 | this.options | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:158 | this.op ... iewport | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:158 | this.op ... iewport | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:167 | this.op ... elector | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:167 | this.op ... elector | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:192 | this.op ... iewport | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:192 | this.op ... iewport | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:137:54:193 | (this.o ... ewport) | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:172:54:183 | this.options | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:172:54:192 | this.op ... iewport | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:172:54:192 | this.op ... iewport | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:138:54:192 | this.op ... iewport | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:207:46:207:57 | this.options | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:207:46:207:67 | this.op ... ntainer | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:207:46:207:57 | this.options | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:207:46:207:67 | this.op ... ntainer | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:494:19:494:24 | option | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:498:50:498:55 | option | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:494:19:494:24 | option | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:498:50:498:55 | option | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:498:11:498:55 | options | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:501:69:501:75 | options | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:498:21:498:55 | typeof ... option | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:498:11:498:55 | options | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:498:50:498:55 | option | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:498:21:498:55 | typeof ... option | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:501:69:501:75 | options | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:17:36:17:42 | options | | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:3:5:3:11 | options | | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:3:5:3:11 | options | | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:3:5:3:11 | options | @@ -454,16 +248,25 @@ edges | unsafe-jquery-plugin.js:157:44:157:50 | options | unsafe-jquery-plugin.js:157:44:157:57 | options.target | | unsafe-jquery-plugin.js:157:44:157:57 | options.target | unsafe-jquery-plugin.js:157:44:157:59 | options.target.a | | unsafe-jquery-plugin.js:157:44:157:57 | options.target | unsafe-jquery-plugin.js:157:44:157:59 | options.target.a | +| unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:161:17:161:23 | options | +| unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:161:17:161:23 | options | +| unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:163:40:163:46 | options | +| unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:163:40:163:46 | options | +| unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:165:16:165:22 | options | +| unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:165:16:165:22 | options | +| unsafe-jquery-plugin.js:161:17:161:23 | options | unsafe-jquery-plugin.js:161:17:161:30 | options.target | +| unsafe-jquery-plugin.js:161:17:161:30 | options.target | unsafe-jquery-plugin.js:161:5:161:30 | anyPref ... .target | +| unsafe-jquery-plugin.js:161:17:161:30 | options.target | unsafe-jquery-plugin.js:161:5:161:30 | anyPref ... .target | +| unsafe-jquery-plugin.js:163:40:163:46 | options | unsafe-jquery-plugin.js:163:40:163:53 | options.target | +| unsafe-jquery-plugin.js:163:40:163:53 | options.target | unsafe-jquery-plugin.js:163:5:163:54 | somethi ... target) | +| unsafe-jquery-plugin.js:163:40:163:53 | options.target | unsafe-jquery-plugin.js:163:5:163:54 | somethi ... target) | +| unsafe-jquery-plugin.js:165:7:165:29 | target | unsafe-jquery-plugin.js:167:6:167:11 | target | +| unsafe-jquery-plugin.js:165:7:165:29 | target | unsafe-jquery-plugin.js:167:6:167:11 | target | +| unsafe-jquery-plugin.js:165:7:165:29 | target | unsafe-jquery-plugin.js:170:6:170:11 | target | +| unsafe-jquery-plugin.js:165:7:165:29 | target | unsafe-jquery-plugin.js:170:6:170:11 | target | +| unsafe-jquery-plugin.js:165:16:165:22 | options | unsafe-jquery-plugin.js:165:16:165:29 | options.target | +| unsafe-jquery-plugin.js:165:16:165:29 | options.target | unsafe-jquery-plugin.js:165:7:165:29 | target | #select -| DELETE_ME/bootstrap-post-27047_src/affix.js:19:68:19:86 | this.options.target | DELETE_ME/bootstrap-post-27047_src/affix.js:121:19:121:24 | option | DELETE_ME/bootstrap-post-27047_src/affix.js:19:68:19:86 | this.options.target | Potential XSS vulnerability in the $@. | DELETE_ME/bootstrap-post-27047_src/affix.js:121:3:130:3 | functio ... })\\n } | '$.fn.affix' plugin | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:113:20:113:27 | selector | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:136:19:136:24 | option | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:113:20:113:27 | selector | Potential XSS vulnerability in the $@. | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:136:3:145:3 | functio ... })\\n } | '$.fn.scrollspy' plugin | -| DELETE_ME/bootstrap-post-27047_src/scrollspy.js:127:7:127:19 | this.selector | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:136:19:136:24 | option | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:127:7:127:19 | this.selector | Potential XSS vulnerability in the $@. | DELETE_ME/bootstrap-post-27047_src/scrollspy.js:136:3:145:3 | functio ... })\\n } | '$.fn.scrollspy' plugin | -| DELETE_ME/bootstrap-pre-27047_src/affix.js:19:22:19:40 | this.options.target | DELETE_ME/bootstrap-pre-27047_src/affix.js:119:19:119:24 | option | DELETE_ME/bootstrap-pre-27047_src/affix.js:19:22:19:40 | this.options.target | Potential XSS vulnerability in the $@. | DELETE_ME/bootstrap-pre-27047_src/affix.js:119:3:128:3 | functio ... })\\n } | '$.fn.affix' plugin | -| DELETE_ME/bootstrap-pre-27047_src/collapse.js:140:14:140:32 | this.options.parent | DELETE_ME/bootstrap-pre-27047_src/collapse.js:170:19:170:24 | option | DELETE_ME/bootstrap-pre-27047_src/collapse.js:140:14:140:32 | this.options.parent | Potential XSS vulnerability in the $@. | DELETE_ME/bootstrap-pre-27047_src/collapse.js:170:3:180:3 | functio ... })\\n } | '$.fn.collapse' plugin | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:113:20:113:27 | selector | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:136:19:136:24 | option | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:113:20:113:27 | selector | Potential XSS vulnerability in the $@. | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:136:3:145:3 | functio ... })\\n } | '$.fn.scrollspy' plugin | -| DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:127:7:127:19 | this.selector | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:136:19:136:24 | option | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:127:7:127:19 | this.selector | Potential XSS vulnerability in the $@. | DELETE_ME/bootstrap-pre-27047_src/scrollspy.js:136:3:145:3 | functio ... })\\n } | '$.fn.scrollspy' plugin | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:49:54:193 | $.isFun ... ewport) | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:494:19:494:24 | option | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:54:49:54:193 | $.isFun ... ewport) | Potential XSS vulnerability in the $@. | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:494:3:504:3 | functio ... })\\n } | '$.fn.tooltip' plugin | -| DELETE_ME/bootstrap-pre-27047_src/tooltip.js:207:46:207:67 | this.op ... ntainer | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:494:19:494:24 | option | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:207:46:207:67 | this.op ... ntainer | Potential XSS vulnerability in the $@. | DELETE_ME/bootstrap-pre-27047_src/tooltip.js:494:3:504:3 | functio ... })\\n } | '$.fn.tooltip' plugin | | unsafe-jquery-plugin.js:3:5:3:11 | options | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:3:5:3:11 | options | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:2:19:63:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | | unsafe-jquery-plugin.js:5:5:5:18 | options.target | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:5:5:5:18 | options.target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:2:19:63:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | | unsafe-jquery-plugin.js:22:6:22:11 | target | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:22:6:22:11 | target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:2:19:63:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | @@ -486,3 +289,7 @@ edges | unsafe-jquery-plugin.js:155:33:155:38 | target | unsafe-jquery-plugin.js:153:38:153:44 | options | unsafe-jquery-plugin.js:155:33:155:38 | target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:153:19:158:2 | functio ... gged\\n\\t} | '$.fn.my_plugin' plugin | | unsafe-jquery-plugin.js:156:41:156:54 | options.target | unsafe-jquery-plugin.js:153:38:153:44 | options | unsafe-jquery-plugin.js:156:41:156:54 | options.target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:153:19:158:2 | functio ... gged\\n\\t} | '$.fn.my_plugin' plugin | | unsafe-jquery-plugin.js:157:44:157:59 | options.target.a | unsafe-jquery-plugin.js:153:38:153:44 | options | unsafe-jquery-plugin.js:157:44:157:59 | options.target.a | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:153:19:158:2 | functio ... gged\\n\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:161:5:161:30 | anyPref ... .target | unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:161:5:161:30 | anyPref ... .target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:160:19:173:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:163:5:163:54 | somethi ... target) | unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:163:5:163:54 | somethi ... target) | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:160:19:173:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:167:6:167:11 | target | unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:167:6:167:11 | target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:160:19:173:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:170:6:170:11 | target | unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:170:6:170:11 | target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:160:19:173:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/unsafe-jquery-plugin.js b/javascript/ql/test/query-tests/Security/CWE-079/unsafe-jquery-plugin.js index 60049e9218c..3a74a729b59 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/unsafe-jquery-plugin.js +++ b/javascript/ql/test/query-tests/Security/CWE-079/unsafe-jquery-plugin.js @@ -156,4 +156,19 @@ options.target === DEFAULTS.target? $(options.target): $(document).find(options.target); // OK - but still flagged options.targets.a === DEFAULTS.target? $(options.target.a): $(document).find(options.target.a); // OK - but still flagged } + + $.fn.my_plugin = function my_plugin(options) { + $(anyPrefix + options.target); // OK (unlikely to be a html/css prefix confusion) + + $(something.replace("%PLACEHOLDER%", options.target)); // OK (unlikely to be a html/css prefix confusion); + + let target = options.target; + if (target.foo) { + $(target); // OK (unlikely to be a string) + } + if (target.length) { + $(target); // NOT OK (can still be a string) + } + + } }); From cfd567f01d32c1470d6bb60b3d68260fc362b187 Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen Date: Mon, 27 Jan 2020 10:28:44 +0100 Subject: [PATCH 03/10] JS: fix FP for js/unsafe-jquery-plugin --- .../security/dataflow/UnsafeJQueryPlugin.qll | 2 +- .../UnsafeJQueryPluginCustomizations.qll | 10 +++++---- .../CWE-079/UnsafeJQueryPlugin.expected | 22 ------------------- 3 files changed, 7 insertions(+), 27 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll index 176a32c1d3f..326b6e78105 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll @@ -35,7 +35,7 @@ module UnsafeJQueryPlugin { override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode node) { super.isSanitizerGuard(node) or node instanceof IsElementSanitizer or - node instanceof IsJQueryObjectSanitizer + node instanceof PropertyPrecenseSanitizer } } } diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll index c4cd7f81a09..0e4cdd1afa6 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll @@ -171,14 +171,16 @@ module UnsafeJQueryPlugin { } /** - * Expression of form `typeof x.jquery !== "undefined"` or `x.jquery`, which sanitizes `x`. + * Expression of like `typeof x. !== "undefined"` or `x.`, which sanitizes `x`, as it is unlikely to be a string afterwards. */ - class IsJQueryObjectSanitizer extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode { + class PropertyPrecenseSanitizer extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode { DataFlow::Node input; boolean polarity; - IsJQueryObjectSanitizer() { - exists(DataFlow::PropRead read | read.accesses(input, "jquery") | + PropertyPrecenseSanitizer() { + exists(DataFlow::PropRead read, string name | + not name = "length" and read.accesses(input, name) + | exists(EqualityTest test | polarity = test.getPolarity().booleanNot() and this = test.flow() diff --git a/javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.expected b/javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.expected index c212607846d..32a2f887cee 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.expected @@ -23,14 +23,6 @@ nodes | unsafe-jquery-plugin.js:52:6:52:11 | target | | unsafe-jquery-plugin.js:60:6:60:11 | target | | unsafe-jquery-plugin.js:60:6:60:11 | target | -| unsafe-jquery-plugin.js:65:47:65:53 | options | -| unsafe-jquery-plugin.js:65:47:65:53 | options | -| unsafe-jquery-plugin.js:67:24:67:44 | $.exten ... ptions) | -| unsafe-jquery-plugin.js:67:33:67:34 | {} | -| unsafe-jquery-plugin.js:67:37:67:43 | options | -| unsafe-jquery-plugin.js:68:45:68:56 | this.options | -| unsafe-jquery-plugin.js:68:45:68:63 | this.options.parent | -| unsafe-jquery-plugin.js:68:45:68:63 | this.options.parent | | unsafe-jquery-plugin.js:71:38:71:44 | options | | unsafe-jquery-plugin.js:71:38:71:44 | options | | unsafe-jquery-plugin.js:72:5:72:11 | options | @@ -129,8 +121,6 @@ nodes | unsafe-jquery-plugin.js:165:7:165:29 | target | | unsafe-jquery-plugin.js:165:16:165:22 | options | | unsafe-jquery-plugin.js:165:16:165:29 | options.target | -| unsafe-jquery-plugin.js:167:6:167:11 | target | -| unsafe-jquery-plugin.js:167:6:167:11 | target | | unsafe-jquery-plugin.js:170:6:170:11 | target | | unsafe-jquery-plugin.js:170:6:170:11 | target | edges @@ -160,14 +150,6 @@ edges | unsafe-jquery-plugin.js:11:7:11:29 | target | unsafe-jquery-plugin.js:60:6:60:11 | target | | unsafe-jquery-plugin.js:11:16:11:22 | options | unsafe-jquery-plugin.js:11:16:11:29 | options.target | | unsafe-jquery-plugin.js:11:16:11:29 | options.target | unsafe-jquery-plugin.js:11:7:11:29 | target | -| unsafe-jquery-plugin.js:65:47:65:53 | options | unsafe-jquery-plugin.js:67:37:67:43 | options | -| unsafe-jquery-plugin.js:65:47:65:53 | options | unsafe-jquery-plugin.js:67:37:67:43 | options | -| unsafe-jquery-plugin.js:67:24:67:44 | $.exten ... ptions) | unsafe-jquery-plugin.js:68:45:68:56 | this.options | -| unsafe-jquery-plugin.js:67:33:67:34 | {} | unsafe-jquery-plugin.js:67:24:67:44 | $.exten ... ptions) | -| unsafe-jquery-plugin.js:67:37:67:43 | options | unsafe-jquery-plugin.js:67:24:67:44 | $.exten ... ptions) | -| unsafe-jquery-plugin.js:67:37:67:43 | options | unsafe-jquery-plugin.js:67:33:67:34 | {} | -| unsafe-jquery-plugin.js:68:45:68:56 | this.options | unsafe-jquery-plugin.js:68:45:68:63 | this.options.parent | -| unsafe-jquery-plugin.js:68:45:68:56 | this.options | unsafe-jquery-plugin.js:68:45:68:63 | this.options.parent | | unsafe-jquery-plugin.js:71:38:71:44 | options | unsafe-jquery-plugin.js:72:5:72:11 | options | | unsafe-jquery-plugin.js:71:38:71:44 | options | unsafe-jquery-plugin.js:72:5:72:11 | options | | unsafe-jquery-plugin.js:72:5:72:11 | options | unsafe-jquery-plugin.js:72:5:72:15 | options.foo | @@ -260,8 +242,6 @@ edges | unsafe-jquery-plugin.js:163:40:163:46 | options | unsafe-jquery-plugin.js:163:40:163:53 | options.target | | unsafe-jquery-plugin.js:163:40:163:53 | options.target | unsafe-jquery-plugin.js:163:5:163:54 | somethi ... target) | | unsafe-jquery-plugin.js:163:40:163:53 | options.target | unsafe-jquery-plugin.js:163:5:163:54 | somethi ... target) | -| unsafe-jquery-plugin.js:165:7:165:29 | target | unsafe-jquery-plugin.js:167:6:167:11 | target | -| unsafe-jquery-plugin.js:165:7:165:29 | target | unsafe-jquery-plugin.js:167:6:167:11 | target | | unsafe-jquery-plugin.js:165:7:165:29 | target | unsafe-jquery-plugin.js:170:6:170:11 | target | | unsafe-jquery-plugin.js:165:7:165:29 | target | unsafe-jquery-plugin.js:170:6:170:11 | target | | unsafe-jquery-plugin.js:165:16:165:22 | options | unsafe-jquery-plugin.js:165:16:165:29 | options.target | @@ -276,7 +256,6 @@ edges | unsafe-jquery-plugin.js:48:6:48:11 | target | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:48:6:48:11 | target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:2:19:63:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | | unsafe-jquery-plugin.js:52:6:52:11 | target | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:52:6:52:11 | target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:2:19:63:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | | unsafe-jquery-plugin.js:60:6:60:11 | target | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:60:6:60:11 | target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:2:19:63:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | -| unsafe-jquery-plugin.js:68:45:68:63 | this.options.parent | unsafe-jquery-plugin.js:65:47:65:53 | options | unsafe-jquery-plugin.js:68:45:68:63 | this.options.parent | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:65:19:69:2 | functio ... T OK\\n\\t} | '$.fn.my_plugin' plugin | | unsafe-jquery-plugin.js:72:5:72:23 | options.foo.bar.baz | unsafe-jquery-plugin.js:71:38:71:44 | options | unsafe-jquery-plugin.js:72:5:72:23 | options.foo.bar.baz | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:71:19:74:2 | functio ... / OK\\n\\t} | '$.fn.my_plugin' plugin | | unsafe-jquery-plugin.js:77:17:77:35 | options.foo.bar.baz | unsafe-jquery-plugin.js:76:38:76:44 | options | unsafe-jquery-plugin.js:77:17:77:35 | options.foo.bar.baz | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:76:19:78:2 | functio ... T OK\\n\\t} | '$.fn.my_plugin' plugin | | unsafe-jquery-plugin.js:90:6:90:6 | t | unsafe-jquery-plugin.js:84:38:84:44 | options | unsafe-jquery-plugin.js:90:6:90:6 | t | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:84:19:93:2 | functio ... ns);\\n\\t} | '$.fn.my_plugin' plugin | @@ -291,5 +270,4 @@ edges | unsafe-jquery-plugin.js:157:44:157:59 | options.target.a | unsafe-jquery-plugin.js:153:38:153:44 | options | unsafe-jquery-plugin.js:157:44:157:59 | options.target.a | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:153:19:158:2 | functio ... gged\\n\\t} | '$.fn.my_plugin' plugin | | unsafe-jquery-plugin.js:161:5:161:30 | anyPref ... .target | unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:161:5:161:30 | anyPref ... .target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:160:19:173:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | | unsafe-jquery-plugin.js:163:5:163:54 | somethi ... target) | unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:163:5:163:54 | somethi ... target) | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:160:19:173:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | -| unsafe-jquery-plugin.js:167:6:167:11 | target | unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:167:6:167:11 | target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:160:19:173:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | | unsafe-jquery-plugin.js:170:6:170:11 | target | unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:170:6:170:11 | target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:160:19:173:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | From 2ad9b843ae0343fc6b4242688c72363f0f42c6b5 Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen Date: Mon, 27 Jan 2020 10:41:47 +0100 Subject: [PATCH 04/10] JS: fix FP for js/unsafe-jquery-plugin --- .../security/dataflow/UnsafeJQueryPlugin.qll | 14 +++++++++++++ .../CWE-079/UnsafeJQueryPlugin.expected | 20 ------------------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll index 326b6e78105..802797db13e 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll @@ -32,6 +32,20 @@ module UnsafeJQueryPlugin { DataFlow::localFieldStep(src, sink) } + override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) { + // prefixing prevents forced html/css confusion: + + // prefixing through concatenation: + succ.asExpr().(AddExpr).getRightOperand().flow() = pred + or + // prefixing through a poor-mans templating system: + exists(DataFlow::MethodCallNode replace | + replace = succ and + pred = replace.getArgument(1) and + replace.getMethodName() = "replace" + ) + } + override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode node) { super.isSanitizerGuard(node) or node instanceof IsElementSanitizer or diff --git a/javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.expected b/javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.expected index 32a2f887cee..773bd71d85f 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.expected @@ -110,14 +110,6 @@ nodes | unsafe-jquery-plugin.js:157:44:157:59 | options.target.a | | unsafe-jquery-plugin.js:160:38:160:44 | options | | unsafe-jquery-plugin.js:160:38:160:44 | options | -| unsafe-jquery-plugin.js:161:5:161:30 | anyPref ... .target | -| unsafe-jquery-plugin.js:161:5:161:30 | anyPref ... .target | -| unsafe-jquery-plugin.js:161:17:161:23 | options | -| unsafe-jquery-plugin.js:161:17:161:30 | options.target | -| unsafe-jquery-plugin.js:163:5:163:54 | somethi ... target) | -| unsafe-jquery-plugin.js:163:5:163:54 | somethi ... target) | -| unsafe-jquery-plugin.js:163:40:163:46 | options | -| unsafe-jquery-plugin.js:163:40:163:53 | options.target | | unsafe-jquery-plugin.js:165:7:165:29 | target | | unsafe-jquery-plugin.js:165:16:165:22 | options | | unsafe-jquery-plugin.js:165:16:165:29 | options.target | @@ -230,18 +222,8 @@ edges | unsafe-jquery-plugin.js:157:44:157:50 | options | unsafe-jquery-plugin.js:157:44:157:57 | options.target | | unsafe-jquery-plugin.js:157:44:157:57 | options.target | unsafe-jquery-plugin.js:157:44:157:59 | options.target.a | | unsafe-jquery-plugin.js:157:44:157:57 | options.target | unsafe-jquery-plugin.js:157:44:157:59 | options.target.a | -| unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:161:17:161:23 | options | -| unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:161:17:161:23 | options | -| unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:163:40:163:46 | options | -| unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:163:40:163:46 | options | | unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:165:16:165:22 | options | | unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:165:16:165:22 | options | -| unsafe-jquery-plugin.js:161:17:161:23 | options | unsafe-jquery-plugin.js:161:17:161:30 | options.target | -| unsafe-jquery-plugin.js:161:17:161:30 | options.target | unsafe-jquery-plugin.js:161:5:161:30 | anyPref ... .target | -| unsafe-jquery-plugin.js:161:17:161:30 | options.target | unsafe-jquery-plugin.js:161:5:161:30 | anyPref ... .target | -| unsafe-jquery-plugin.js:163:40:163:46 | options | unsafe-jquery-plugin.js:163:40:163:53 | options.target | -| unsafe-jquery-plugin.js:163:40:163:53 | options.target | unsafe-jquery-plugin.js:163:5:163:54 | somethi ... target) | -| unsafe-jquery-plugin.js:163:40:163:53 | options.target | unsafe-jquery-plugin.js:163:5:163:54 | somethi ... target) | | unsafe-jquery-plugin.js:165:7:165:29 | target | unsafe-jquery-plugin.js:170:6:170:11 | target | | unsafe-jquery-plugin.js:165:7:165:29 | target | unsafe-jquery-plugin.js:170:6:170:11 | target | | unsafe-jquery-plugin.js:165:16:165:22 | options | unsafe-jquery-plugin.js:165:16:165:29 | options.target | @@ -268,6 +250,4 @@ edges | unsafe-jquery-plugin.js:155:33:155:38 | target | unsafe-jquery-plugin.js:153:38:153:44 | options | unsafe-jquery-plugin.js:155:33:155:38 | target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:153:19:158:2 | functio ... gged\\n\\t} | '$.fn.my_plugin' plugin | | unsafe-jquery-plugin.js:156:41:156:54 | options.target | unsafe-jquery-plugin.js:153:38:153:44 | options | unsafe-jquery-plugin.js:156:41:156:54 | options.target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:153:19:158:2 | functio ... gged\\n\\t} | '$.fn.my_plugin' plugin | | unsafe-jquery-plugin.js:157:44:157:59 | options.target.a | unsafe-jquery-plugin.js:153:38:153:44 | options | unsafe-jquery-plugin.js:157:44:157:59 | options.target.a | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:153:19:158:2 | functio ... gged\\n\\t} | '$.fn.my_plugin' plugin | -| unsafe-jquery-plugin.js:161:5:161:30 | anyPref ... .target | unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:161:5:161:30 | anyPref ... .target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:160:19:173:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | -| unsafe-jquery-plugin.js:163:5:163:54 | somethi ... target) | unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:163:5:163:54 | somethi ... target) | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:160:19:173:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | | unsafe-jquery-plugin.js:170:6:170:11 | target | unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:170:6:170:11 | target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:160:19:173:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | From 1de1c15919e9427d3f3c91e3605f0bcf434212a4 Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen Date: Wed, 29 Jan 2020 10:22:52 +0100 Subject: [PATCH 05/10] JS: minor fixups --- .../security/dataflow/UnsafeJQueryPluginCustomizations.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll index 0e4cdd1afa6..6cadd049aad 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll @@ -115,7 +115,7 @@ module UnsafeJQueryPlugin { } /** - * Holds if `plugin` has a default option defined a `def`. + * Holds if `plugin` has a default option defined at `def`. */ private predicate hasDefaultOption(JQueryPluginMethod plugin, DataFlow::PropWrite def) { exists(ExtendCall extend, JQueryPluginOptions options, DataFlow::SourceNode default | @@ -161,7 +161,7 @@ module UnsafeJQueryPlugin { IsElementSanitizer() { // common ad hoc sanitizing calls exists(string name | getCalleeName() = name | - name = "isElement" or name = "isWindow" or name = "isWindow" + name = "isElement" or name = "isDocument" or name = "isWindow" ) } @@ -171,7 +171,7 @@ module UnsafeJQueryPlugin { } /** - * Expression of like `typeof x. !== "undefined"` or `x.`, which sanitizes `x`, as it is unlikely to be a string afterwards. + * Expression like `typeof x. !== "undefined"` or `x.`, which sanitizes `x`, as it is unlikely to be a string afterwards. */ class PropertyPrecenseSanitizer extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode { DataFlow::Node input; From eaff78b37ea9e442a866f8d63ef74003495adeb8 Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen Date: Wed, 29 Jan 2020 10:25:46 +0100 Subject: [PATCH 06/10] JS: change severity to warning --- javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.ql b/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.ql index 7d5525c1d29..2df7769906d 100644 --- a/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.ql +++ b/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.ql @@ -2,7 +2,7 @@ * @name Unsafe jQuery plugin * @description A jQuery plugin that unintentionally constructs HTML from some of its options may be unsafe to use for clients. * @kind path-problem - * @problem.severity error + * @problem.severity warning * @precision high * @id js/unsafe-jquery-plugin * @tags security From c70997febfc4ea1f4e1ca7f4b11d58f2947892ee Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen Date: Thu, 30 Jan 2020 08:32:22 +0100 Subject: [PATCH 07/10] JS: address review comments for js/unsafe-jquery-plugin --- .../Security/CWE-079/UnsafeJQueryPlugin.qhelp | 6 ++-- .../security/dataflow/UnsafeJQueryPlugin.qll | 4 +-- .../UnsafeJQueryPluginCustomizations.qll | 28 ++++++++++++++----- .../CWE-079/UnsafeJQueryPlugin.expected | 10 +++++++ .../Security/CWE-079/unsafe-jquery-plugin.js | 11 ++++++++ 5 files changed, 48 insertions(+), 11 deletions(-) diff --git a/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.qhelp b/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.qhelp index 71679dadaf3..d128454b63b 100644 --- a/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.qhelp +++ b/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.qhelp @@ -18,7 +18,7 @@ Otherwise, the plugin may write user input (for example, a URL query parameter) to a web page without properly sanitizing the input first, which allows for a cross-site scripting vulnerability in the client - application. + application through dynamic HTML construction.

    @@ -26,7 +26,9 @@

    - Document all options that can lead to cross-site scripting attacks. + Document all options that can lead to cross-site scripting + attacks, and guard against unsafe inputs where dynamic HTML + construction is not intended.

    diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll index 802797db13e..591e7f21737 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll @@ -36,7 +36,7 @@ module UnsafeJQueryPlugin { // prefixing prevents forced html/css confusion: // prefixing through concatenation: - succ.asExpr().(AddExpr).getRightOperand().flow() = pred + StringConcatenation::getFirstOperand(succ) != pred or // prefixing through a poor-mans templating system: exists(DataFlow::MethodCallNode replace | @@ -49,7 +49,7 @@ module UnsafeJQueryPlugin { override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode node) { super.isSanitizerGuard(node) or node instanceof IsElementSanitizer or - node instanceof PropertyPrecenseSanitizer + node instanceof PropertyPresenceSanitizer } } } diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll index 6cadd049aad..0da1f81beb9 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll @@ -73,9 +73,9 @@ module UnsafeJQueryPlugin { } /** - * Gets an function that is registered as a jQuery plugin method at `def`. + * Gets a node that is registered as a jQuery plugin method at `def`. */ - private DataFlow::FunctionNode getAJQueryPluginMethod( + private DataFlow::SourceNode getAJQueryPluginMethod( DataFlow::TypeBackTracker t, DataFlow::Node def ) { t.start() and @@ -85,6 +85,13 @@ module UnsafeJQueryPlugin { exists(DataFlow::TypeBackTracker t2 | result = getAJQueryPluginMethod(t2, def).backtrack(t2, t)) } + /** + * Gets a function that is registered as a jQuery plugin method at `def`. + */ + private DataFlow::FunctionNode getAJQueryPluginMethod(DataFlow::Node def) { + result = getAJQueryPluginMethod(DataFlow::TypeBackTracker::end(), def) + } + /** * Gets an operand to `extend`. */ @@ -95,6 +102,13 @@ module UnsafeJQueryPlugin { exists(DataFlow::TypeBackTracker t2 | result = getAnExtendOperand(t2, extend).backtrack(t2, t)) } + /** + * Gets an operand to `extend`. + */ + private DataFlow::SourceNode getAnExtendOperand(ExtendCall extend) { + result = getAnExtendOperand(DataFlow::TypeBackTracker::end(), extend) + } + /** * A function that is registered as a jQuery plugin method. */ @@ -104,7 +118,7 @@ module UnsafeJQueryPlugin { JQueryPluginMethod() { exists(DataFlow::Node def | jQueryPluginDefinition(pluginName, def) and - this = getAJQueryPluginMethod(DataFlow::TypeBackTracker::end(), def) + this = getAJQueryPluginMethod(def) ) } @@ -120,8 +134,8 @@ module UnsafeJQueryPlugin { private predicate hasDefaultOption(JQueryPluginMethod plugin, DataFlow::PropWrite def) { exists(ExtendCall extend, JQueryPluginOptions options, DataFlow::SourceNode default | options.getPlugin() = plugin and - options = getAnExtendOperand(DataFlow::TypeBackTracker::end(), extend) and - default = getAnExtendOperand(DataFlow::TypeBackTracker::end(), extend) and + options = getAnExtendOperand(extend) and + default = getAnExtendOperand(extend) and default.getAPropertyWrite() = def ) } @@ -173,11 +187,11 @@ module UnsafeJQueryPlugin { /** * Expression like `typeof x. !== "undefined"` or `x.`, which sanitizes `x`, as it is unlikely to be a string afterwards. */ - class PropertyPrecenseSanitizer extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode { + class PropertyPresenceSanitizer extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode { DataFlow::Node input; boolean polarity; - PropertyPrecenseSanitizer() { + PropertyPresenceSanitizer() { exists(DataFlow::PropRead read, string name | not name = "length" and read.accesses(input, name) | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.expected b/javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.expected index 773bd71d85f..bc46d640340 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/UnsafeJQueryPlugin.expected @@ -115,6 +115,11 @@ nodes | unsafe-jquery-plugin.js:165:16:165:29 | options.target | | unsafe-jquery-plugin.js:170:6:170:11 | target | | unsafe-jquery-plugin.js:170:6:170:11 | target | +| unsafe-jquery-plugin.js:178:27:178:33 | options | +| unsafe-jquery-plugin.js:178:27:178:33 | options | +| unsafe-jquery-plugin.js:179:5:179:11 | options | +| unsafe-jquery-plugin.js:179:5:179:18 | options.target | +| unsafe-jquery-plugin.js:179:5:179:18 | options.target | edges | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:3:5:3:11 | options | | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:3:5:3:11 | options | @@ -228,6 +233,10 @@ edges | unsafe-jquery-plugin.js:165:7:165:29 | target | unsafe-jquery-plugin.js:170:6:170:11 | target | | unsafe-jquery-plugin.js:165:16:165:22 | options | unsafe-jquery-plugin.js:165:16:165:29 | options.target | | unsafe-jquery-plugin.js:165:16:165:29 | options.target | unsafe-jquery-plugin.js:165:7:165:29 | target | +| unsafe-jquery-plugin.js:178:27:178:33 | options | unsafe-jquery-plugin.js:179:5:179:11 | options | +| unsafe-jquery-plugin.js:178:27:178:33 | options | unsafe-jquery-plugin.js:179:5:179:11 | options | +| unsafe-jquery-plugin.js:179:5:179:11 | options | unsafe-jquery-plugin.js:179:5:179:18 | options.target | +| unsafe-jquery-plugin.js:179:5:179:11 | options | unsafe-jquery-plugin.js:179:5:179:18 | options.target | #select | unsafe-jquery-plugin.js:3:5:3:11 | options | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:3:5:3:11 | options | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:2:19:63:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | | unsafe-jquery-plugin.js:5:5:5:18 | options.target | unsafe-jquery-plugin.js:2:38:2:44 | options | unsafe-jquery-plugin.js:5:5:5:18 | options.target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:2:19:63:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | @@ -251,3 +260,4 @@ edges | unsafe-jquery-plugin.js:156:41:156:54 | options.target | unsafe-jquery-plugin.js:153:38:153:44 | options | unsafe-jquery-plugin.js:156:41:156:54 | options.target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:153:19:158:2 | functio ... gged\\n\\t} | '$.fn.my_plugin' plugin | | unsafe-jquery-plugin.js:157:44:157:59 | options.target.a | unsafe-jquery-plugin.js:153:38:153:44 | options | unsafe-jquery-plugin.js:157:44:157:59 | options.target.a | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:153:19:158:2 | functio ... gged\\n\\t} | '$.fn.my_plugin' plugin | | unsafe-jquery-plugin.js:170:6:170:11 | target | unsafe-jquery-plugin.js:160:38:160:44 | options | unsafe-jquery-plugin.js:170:6:170:11 | target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:160:19:173:2 | functio ... \\t\\t}\\n\\n\\t} | '$.fn.my_plugin' plugin | +| unsafe-jquery-plugin.js:179:5:179:18 | options.target | unsafe-jquery-plugin.js:178:27:178:33 | options | unsafe-jquery-plugin.js:179:5:179:18 | options.target | Potential XSS vulnerability in the $@. | unsafe-jquery-plugin.js:178:18:180:2 | functio ... T OK\\n\\t} | '$.fn.my_plugin' plugin | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/unsafe-jquery-plugin.js b/javascript/ql/test/query-tests/Security/CWE-079/unsafe-jquery-plugin.js index 3a74a729b59..a6eae277811 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/unsafe-jquery-plugin.js +++ b/javascript/ql/test/query-tests/Security/CWE-079/unsafe-jquery-plugin.js @@ -171,4 +171,15 @@ } } + + function setupPlugin(o) { + $.fn.my_plugin = o.f + } + setupPlugin({f: function(options) { + $(options.target); // NOT OK + }}); + setupPlugin({f:function(options) { + $(document).find(options.target); // OK + }}); + }); From 7f25c1bf476423b08b3c25be4ffaead6a3b49576 Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen Date: Thu, 30 Jan 2020 13:41:51 +0100 Subject: [PATCH 08/10] JS: address doc-review comments --- change-notes/1.24/analysis-javascript.md | 2 +- .../Security/CWE-079/UnsafeJQueryPlugin.qhelp | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/change-notes/1.24/analysis-javascript.md b/change-notes/1.24/analysis-javascript.md index 17d1fdd7f7a..758e10eeee1 100644 --- a/change-notes/1.24/analysis-javascript.md +++ b/change-notes/1.24/analysis-javascript.md @@ -28,7 +28,7 @@ | Regular expression always matches (`js/regex/always-matches`) | correctness, regular-expressions | Highlights regular expression checks that trivially succeed by matching an empty substring. Results are shown on LGTM by default. | | Missing await (`js/missing-await`) | correctness | Highlights expressions that operate directly on a promise object in a nonsensical way, instead of awaiting its result. Results are shown on LGTM by default. | | Prototype pollution in utility function (`js/prototype-pollution-utility`) | security, external/cwe/cwe-400, external/cwe/cwe-471 | Highlights recursive copying operations that are susceptible to prototype pollution. Results are shown on LGTM by default. | -| Unsafe jQuery plugin (`js/unsafe-jquery-plugin`) | Highlights potential XSS vulnerabilities in unsafely designed jQuery plugins. | +| Unsafe jQuery plugin (`js/unsafe-jquery-plugin`) | Highlights potential XSS vulnerabilities in unsafely designed jQuery plugins. Results are shown on LGTM by default. | ## Changes to existing queries diff --git a/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.qhelp b/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.qhelp index d128454b63b..7920c7ee891 100644 --- a/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.qhelp +++ b/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.qhelp @@ -10,13 +10,14 @@ configurable through options provided by the clients of the plugin. - Clients, however, do not know the implementation details of the - plugin, so it is important to document the capabilities of each - option. Of particular importance is the documentation for the plugin - options that the client is responsible for sanitizing. + + Clients, however, do not know the implementation details + of the plugin, so it is important to document the capabilities of each + option. The documentation for the plugin options that the client is + responsible for sanitizing is of particular importance. Otherwise, the plugin may write user input (for example, a URL query - parameter) to a web page without properly sanitizing the input first, + parameter) to a web page without properly sanitizing it first, which allows for a cross-site scripting vulnerability in the client application through dynamic HTML construction. @@ -36,8 +37,8 @@

    - The following example shows a jQuery plugin that selects a DOM - element, and copies its text content another DOM element. The + The following example shows a jQuery plugin that selects a + DOM element, and copies its text content to another DOM element. The selection is performed by using the plugin option sourceSelector as a CSS selector. @@ -47,7 +48,7 @@

    - This is however not a safe plugin, since the call to + This is, however, not a safe plugin, since the call to jQuery interprets sourceSelector as HTML if it is a string that starts with <. From e1180495f58fda3794ec4c7a21649f9e316c2eb9 Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen Date: Mon, 3 Feb 2020 08:39:20 +0100 Subject: [PATCH 09/10] JS: optimize a prefix-check --- .../semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll index 591e7f21737..cbd20154380 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll @@ -36,7 +36,7 @@ module UnsafeJQueryPlugin { // prefixing prevents forced html/css confusion: // prefixing through concatenation: - StringConcatenation::getFirstOperand(succ) != pred + StringConcatenation::getOperand(succ, [1..StringConcatenation::getNumOperand(succ) - 1]) = pred or // prefixing through a poor-mans templating system: exists(DataFlow::MethodCallNode replace | From 1ec8fa24b389bbaa304aa1c0a8a4dc52c006b54f Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen Date: Tue, 4 Feb 2020 10:52:38 +0100 Subject: [PATCH 10/10] JS: reformulate optimization --- .../semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll index cbd20154380..b08cbb2f5f8 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll @@ -36,7 +36,7 @@ module UnsafeJQueryPlugin { // prefixing prevents forced html/css confusion: // prefixing through concatenation: - StringConcatenation::getOperand(succ, [1..StringConcatenation::getNumOperand(succ) - 1]) = pred + StringConcatenation::taintStep(pred, succ, _, any(int i | i >= 1)) or // prefixing through a poor-mans templating system: exists(DataFlow::MethodCallNode replace |