Skip to content

Commit

Permalink
fix: add missing single quote escaping when quotedAttributeValueSynta…
Browse files Browse the repository at this point in the history
…x is enabled
  • Loading branch information
mdk000 committed Sep 30, 2024
1 parent 66df7c4 commit 5b8bd1f
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 3 deletions.
24 changes: 24 additions & 0 deletions lib/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,8 @@ var REGEXP_LT = /</g;
var REGEXP_GT = />/g;
var REGEXP_QUOTE = /"/g;
var REGEXP_QUOTE_2 = /&quot;/g;
var REGEXP_SINGLE_QUOTE = /'/g;
var REGEXP_SINGLE_QUOTE_2 = /&apos;/g;
var REGEXP_ATTR_VALUE_1 = /&#([a-zA-Z0-9]*);?/gim;
var REGEXP_ATTR_VALUE_COLON = /&colon;?/gim;
var REGEXP_ATTR_VALUE_NEWLINE = /&newline;?/gim;
Expand All @@ -253,6 +255,16 @@ function escapeQuote(str) {
return str.replace(REGEXP_QUOTE, "&quot;");
}

/**
* escape single quote
*
* @param {String} str
* @return {String} str
*/
function escapeSingleQuote(str) {
return str.replace(REGEXP_SINGLE_QUOTE, "&apos;");
}

/**
* unescape double quote
*
Expand All @@ -263,6 +275,16 @@ function unescapeQuote(str) {
return str.replace(REGEXP_QUOTE_2, '"');
}

/**
* unescape single quote
*
* @param {String} str
* @return {String} str
*/
function unescapeSingleQuote(str) {
return str.replace(REGEXP_SINGLE_QUOTE_2, "'");
}

/**
* escape html entities
*
Expand Down Expand Up @@ -311,6 +333,7 @@ function clearNonPrintableCharacter(str) {
*/
function friendlyAttrValue(str) {
str = unescapeQuote(str);
str = unescapeSingleQuote(str);
str = escapeHtmlEntities(str);
str = escapeDangerHtml5Entities(str);
str = clearNonPrintableCharacter(str);
Expand All @@ -325,6 +348,7 @@ function friendlyAttrValue(str) {
*/
function escapeAttrValue(str) {
str = escapeQuote(str);
str = escapeSingleQuote(str);
str = escapeHtml(str);
return str;
}
Expand Down
10 changes: 7 additions & 3 deletions test/test_xss.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ describe("test XSS", function() {
assert.equal(xss('<a t="">'), "<a>");

// 属性内的特殊字符
assert.equal(xss('<a title="\'<<>>">'), '<a title="\'&lt;&lt;&gt;&gt;">');
assert.equal(xss('<a title="\'<<>>">'), '<a title="&apos;&lt;&lt;&gt;&gt;">');
assert.equal(xss('<a title=""">'), "<a title>");
assert.equal(xss('<a h=title="oo">'), "<a>");
assert.equal(xss('<a h= title="oo">'), "<a>");
Expand All @@ -80,7 +80,7 @@ describe("test XSS", function() {
// 没有双引号括起来的属性值
assert.equal(xss("<a title=home>"), '<a title="home">');
assert.equal(xss('<a title=abc("d")>'), '<a title="abc(&quot;d&quot;)">');
assert.equal(xss("<a title=abc('d')>"), "<a title=\"abc('d')\">");
assert.equal(xss("<a title=abc('d')>"), "<a title=\"abc(&apos;d&apos;)\">");

// 单个闭合标签
assert.equal(xss("<img src/>"), "<img src />");
Expand Down Expand Up @@ -131,7 +131,7 @@ describe("test XSS", function() {
xss(
'<img width = 100 height =200 title= "xxx" no=yes alt="\'yyy\'">'
),
'<img width="100" height="200" title="xxx" alt="\'yyy\'">'
'<img width="100" height="200" title="xxx" alt="&apos;yyy&apos;">'
);
assert.equal(
xss(
Expand Down Expand Up @@ -442,6 +442,10 @@ describe("test XSS", function() {
xss('<a title="xx">invalid-value</a>', { singleQuotedAttributeValue: 'invalid' }),
'<a title="xx">invalid-value</a>'
);
assert.equal(
xss(`<img src="/url' onerror='alert(1)'" />`, { singleQuotedAttributeValue: true }),
`<img src='/url&apos; onerror=&apos;alert(1)&apos;' />`
);
})

it("no options mutated", function() {
Expand Down

0 comments on commit 5b8bd1f

Please sign in to comment.