Skip to content

Commit 01f8a08

Browse files
committed
Fix ReDoS vulnerability
1 parent 3c99615 commit 01f8a08

File tree

3 files changed

+24
-2
lines changed

3 files changed

+24
-2
lines changed

index.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,17 @@ const cleanEntities = svg => {
2121
return svg.replace(entityRegex, '');
2222
};
2323

24-
const regex = /^\s*(?:<\?xml[^>]*>\s*)?(?:<!doctype svg[^>]*\s*(?:\[?(?:\s*<![^>]*>\s*)*\]?)*[^>]*>\s*)?(?:<svg[^>]*>[^]*<\/svg>|<svg[^/>]*\/\s*>)\s*$/i;
24+
const removeDtdMarkupDeclarations = svg => svg.replace(/\[?(?:\s*<![A-Z]+[^>]*>\s*)*\]?/g, '');
2525

26-
const isSvg = input => Boolean(input) && !isBinary(input) && regex.test(cleanEntities(input.toString()).replace(htmlCommentRegex, ''));
26+
const clean = svg => {
27+
svg = cleanEntities(svg);
28+
svg = removeDtdMarkupDeclarations(svg);
29+
return svg;
30+
};
31+
32+
const regex = /^\s*(?:<\?xml[^>]*>\s*)?(?:<!doctype svg[^>]*>\s*)?(?:<svg[^>]*>[^]*<\/svg>|<svg[^/>]*\/\s*>)\s*$/i;
33+
34+
const isSvg = input => Boolean(input) && !isBinary(input) && regex.test(clean(input.toString()).replace(htmlCommentRegex, ''));
2735

2836
module.exports = isSvg;
2937
// TODO: Remove this for the next major release

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"devDependencies": {
4343
"@types/node": "^11.13.0",
4444
"ava": "^1.4.1",
45+
"time-span": "^4.0.0",
4546
"tsd": "^0.7.2",
4647
"xo": "^0.24.0"
4748
}

test.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import fs from 'fs';
22
import test from 'ava';
3+
import timeSpan from 'time-span';
34
import isSvg from '.';
45

56
test('valid SVGs', t => {
@@ -70,3 +71,15 @@ test('support markup inside Entity tags', t => {
7071
</g>
7172
</svg>`));
7273
});
74+
75+
test('regex should not be quadratic', t => {
76+
const end = timeSpan();
77+
78+
isSvg(`<!doctype svg ${' '.repeat(34560)}`);
79+
80+
if (end.seconds() < 10) {
81+
t.pass();
82+
} else {
83+
t.fail();
84+
}
85+
});

0 commit comments

Comments
 (0)