Skip to content

Commit

Permalink
dummyAnchor href check
Browse files Browse the repository at this point in the history
  • Loading branch information
archmoj committed Jul 6, 2021
1 parent bae378a commit d84e9c3
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 12 deletions.
39 changes: 27 additions & 12 deletions src/lib/svg_text_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -604,14 +604,9 @@ function buildSVGText(containerNode, str) {
var href = getQuotedMatch(extra, HREFMATCH);

if(href) {
// check safe protocols
var dummyAnchor = document.createElement('a');
dummyAnchor.href = href;
if(PROTOCOLS.indexOf(dummyAnchor.protocol) !== -1) {
// Decode href to allow both already encoded and not encoded
// URIs. Without decoding prior encoding, an already encoded
// URI would be encoded twice producing a semantically different URI.
nodeSpec.href = encodeURI(decodeURI(href));
var safeHref = sanitizeHref(href);
if(safeHref) {
nodeSpec.href = safeHref;
nodeSpec.target = getQuotedMatch(extra, TARGETMATCH) || '_blank';
nodeSpec.popup = getQuotedMatch(extra, POPUPMATCH);
}
Expand All @@ -626,6 +621,27 @@ function buildSVGText(containerNode, str) {
return hasLink;
}

function sanitizeHref(href) {
var decodedHref = encodeURI(decodeURI(href));
var dummyAnchor1 = document.createElement('a');
var dummyAnchor2 = document.createElement('a');
dummyAnchor1.href = href;
dummyAnchor2.href = decodedHref;

var p1 = dummyAnchor1.protocol;
var p2 = dummyAnchor2.protocol;

// check safe protocols
if(
PROTOCOLS.indexOf(p1) !== -1 &&
PROTOCOLS.indexOf(p2) !== -1
) {
return decodedHref;
} else {
return '';
}
}

/*
* sanitizeHTML: port of buildSVGText aimed at providing a clean subset of HTML
* @param {string} str: the html string to clean
Expand Down Expand Up @@ -660,10 +676,9 @@ exports.sanitizeHTML = function sanitizeHTML(str) {
var href = getQuotedMatch(extra, HREFMATCH);

if(href) {
var dummyAnchor = document.createElement('a');
dummyAnchor.href = href;
if(PROTOCOLS.indexOf(dummyAnchor.protocol) !== -1) {
nodeAttrs.href = encodeURI(decodeURI(href));
var safeHref = sanitizeHref(href);
if(safeHref) {
nodeAttrs.href = safeHref;
var target = getQuotedMatch(extra, TARGETMATCH);
if(target) {
nodeAttrs.target = target;
Expand Down
18 changes: 18 additions & 0 deletions test/jasmine/tests/svg_text_utils_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,16 @@ describe('svg+text utils', function() {
d3.selectAll('.text-tester').remove();
});

it('checks for XSS attack in href protocol', function() {
var node = mockTextSVGElement(
'<a href="j%61vascript:alert(\'attack\')">XSS</a>'
);

expect(node.text()).toEqual('XSS');
assertAnchorAttrs(node);
assertAnchorLink(node, null);
});

it('checks for XSS attack in href', function() {
var node = mockTextSVGElement(
'<a href="javascript:alert(\'attack\')">XSS</a>'
Expand Down Expand Up @@ -534,6 +544,14 @@ describe('sanitizeHTML', function() {
d3.selectAll('.text-tester').remove();
});

it('checks for XSS attack in href protocol', function() {
var innerHTML = mockHTML(
'<a href="j%61vascript:alert(\'attack\')">XSS</a>'
);

expect(innerHTML).toEqual('<a>XSS</a>');
});

it('checks for XSS attack in href', function() {
var innerHTML = mockHTML(
'<a href="javascript:alert(\'attack\')">XSS</a>'
Expand Down

0 comments on commit d84e9c3

Please sign in to comment.