Permalink
Browse files

XSS vulnerability fix - thank you to Jordan Milne (/u/largenocream) f…

…or the responsible discovery and contribution of a patch.
  • Loading branch information...
honestbleeps committed Apr 2, 2014
1 parent 12ecbd3 commit de3f84cac524c473e08d72517dc1d75f26906507
Showing with 90 additions and 72 deletions.
  1. +90 −72 lib/snuownd.js
View
@@ -1375,89 +1375,107 @@
// rndr_html_tag(struct buf *ob, const struct buf *text, void *opaque, char* tagname, char** whitelist, int tagtype)
//NOT A CALLBACK!
function rndr_html_tag(out, text, options, tagname, whitelist, tagtype) {
var x, z, in_str = 0, seen_equals = 0, done, reset;
var attr = new Buffer()
var i, x, z, in_str = 0, seen_equals = 0, done = 0, done_attr = 0, reset = 0;
var attr;
var value;
var c;
out.s += '<';
var i = 1 + tagname.length;
if(tagtype == HTML_TAG_CLOSE) {
out.s += '/';
i += 1;
out.s += '/';
out.s += tagname;
out.s += '>';
return;
}
out.s += tagname;
if(tagtype != HTML_TAG_CLOSE) {
for(;i < text.s.length; i++) {
c = text.s[i];
done = 0;
reset = 0;
switch(c) {
case '>':
if(seen_equals && !in_str) {
done = 1;
reset = 1;
} else {
reset = 1;
}
break;
case '\'':
case '"':
if(!in_str)
in_str = c;
else if(in_str == c)
in_str = !in_str;
i = 1 + tagname.length;
attr = new Buffer();
value = new Buffer();
for(; i < text.s.length && !done; i++) {
c = text.s[i];
done = 0;
reset = 0;
done_attr = 0;
switch(c) {
case '>':
done = 1;
break;
case '\'':
case '"':
if(!seen_equals) {
reset = 1;
} else if(!in_str) {
in_str = c;
} else if(in_str == c) {
in_str = 0;
done_attr = 1;
} else {
value.s += c;
}
break;
case ' ':
if (in_str) {
value.s += ' ';
} else {
reset = 1;
}
break;
case '=':
if(seen_equals) {
reset = 1;
break;
default:
if(!in_str) {
switch(c) {
case ' ':
if(seen_equals) {
done = 1;
reset = 1;
} else
reset = 1;
break;
case '=':
if(seen_equals) {
reset = 1;
} else {
for(z=0; z < whitelist.length; z++) {
if(whitelist[z].length != attr.s.length)
continue;
for(x=0;x < attr.s.length; x++) {
if(whitelist[z][x].toLowerCase() != attr.s[x].toLowerCase())
break;
}
if(x == attr.s.length)
seen_equals = 1;
}
if(!seen_equals)
reset = 1;
}
break;
}
}
seen_equals = 1;
break;
default:
if(seen_equals && in_str || !seen_equals) {
if(seen_equals)
value.s += c;
else
attr.s += c;
}
break;
}
if(done_attr) {
var valid = 0;
for(z = 0; z < whitelist.length; z++) {
if(whitelist[z].length != attr.s.length) {
continue;
}
for(x = 0; x < attr.s.length; x++) {
if(whitelist[z][x].toLowerCase() != attr.s[x].toLowerCase()) {
break;
}
}
if(x == attr.s.length) {
valid = 1;
break;
}
}
if(done) {
out.s += ' ' + attr.s;
}
if(reset) {
seen_equals = 0;
in_str = 0;
attr.s = '';
} else {
attr.s += c;
if(valid && value.s.length && attr.s.length) {
out.s += ' ';
escape_html(out, attr.s, true);
out.s += "=\"";
escape_html(out, value.s, true);
out.s += '"';
}
reset = 1;
}
if(reset) {
seen_equals = 0;
in_str = 0;
attr.s = '';
value.s = '';
}
}
// bufrelease(attr);
out.s += '>';
}