A sink can be described as a function or method that is potentially dangerous when it's (unexpectedly) called or if one of its arguments, coming from an untrusted input, is not correctly escaped according to the layer the function is going to communicate to.
The jQuery Sink
Suppose we have the following code:
var aVar=location.hash;
jQuery(aVar);
By looking at the DOMinator output, you'll see something like the following:
That means the jQuery, or its alias '$', method is trying to understand if hash contains some tags. In particular part of the JavaScript stack trace will be similar to the following:
4 14:44:40.306 :[ http://host/jQueryTest.html#aaaaa ]
Target: [ exec(^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)) CallCount: 1 ]
Data:
+ #aaaaaahttp://host/jquery-1.4.3
,Line:19
,1: function (selector, context) {
2: var match, elem, ret, doc;
3: if (!selector) {
4: return this;
5: }
6: if (selector.nodeType) {
7: this.context = this[0] = selector;
8: this.length = 1;
9: return this;
10: }
11: if (selector === "body" && !context && document.body) {
12: this.context = document;
13: this[0] = document.body;
14: this.selector = "body";
15: this.length = 1;
16: return this;
17: }
18: if (typeof selector === "string") {
19: match = quickExpr.exec(selector);
20: if (match && (match[1] || !context)) {
21: if (match[1])
...
So, by trying to put #<img/src/onerror=alert(1)> in the hash part, we'll see the following alert on DOMinator:
12 14:44:40.364 :[ http://host/jQueryTest.html ]
Target: [ DIV.innerHTML CallCount: 1 ]
Data:+ <img src="" onerror="alert(1)" />+ Stack Tracehttp://host/jquery-1.4.3
,Line:20
,1: function (elems, context, fragment, scripts) {
2: context = context || document;
3: if (typeof context.createElement === "undefined") {
4: context = context.ownerDocument ||
5: context[0] && context[0].ownerDocument || document;
6: }
7: var ret = [];
8: for (var i = 0, elem; (elem = elems[i]) != null; i++) {
9: if (typeof elem === "number") {
10: elem += "";
11: }
12: if (!elem) {
13: continue;
14: }
15: if (typeof elem === "string" && !rhtml.test(elem)) {
16: elem = context.createTextNode(elem);
17: } else if (typeof elem === "string") {
18: elem = elem.replace(rxhtmlTag, "<$1>");
19: var tag = (rtagName.exec(elem) || ["", ""])[1].toLowerCase(), wrap = wrapMap[tag] || wrapMap._default, depth = wrap[0], div = context.createElement("div");
20: div.innerHTML = wrap[1] + elem + wrap[2];
21: while (depth--) {
22: div = div.lastChild;
23: }
.....
Which means that if the arguments of jQuery contains some kind of tag it'll be rendered using innerHTML, resulting in a potential DOM Based Xss.
Countermeasures
If you have to use some untrusted input, Data Validation and Output encoding should be performed before using it as a jQuery argument.