Skip to content

Commit 55ee8ee

Browse files
authored
Merge pull request #18 from davisjam/FixREDOS
security: Fix REDOS vulnerability
2 parents 1498b0d + 1495509 commit 55ee8ee

File tree

2 files changed

+34
-3
lines changed

2 files changed

+34
-3
lines changed

index.js

+23-3
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,15 @@
66
module.exports = isUrl;
77

88
/**
9-
* Matcher.
9+
* RegExps.
10+
* A URL must match #1 and then at least one of #2/#3.
11+
* Use two levels of REs to avoid REDOS.
1012
*/
1113

12-
var matcher = /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/;
14+
var protocolAndDomainRE = /^(?:\w+:)?\/\/(\S+)$/;
15+
16+
var localhostDomainRE = /^localhost[\:?\d]*(?:[^\:?\d]\S*)?$/
17+
var nonLocalhostDomainRE = /^[^\s\.]+\.\S{2,}$/;
1318

1419
/**
1520
* Loosely validate a URL `string`.
@@ -19,5 +24,20 @@ var matcher = /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/;
1924
*/
2025

2126
function isUrl(string){
22-
return matcher.test(string);
27+
var match = string.match(protocolAndDomainRE);
28+
if (!match) {
29+
return false;
30+
}
31+
32+
var everythingAfterProtocol = match[1];
33+
if (!everythingAfterProtocol) {
34+
return false;
35+
}
36+
37+
if (localhostDomainRE.test(everythingAfterProtocol) ||
38+
nonLocalhostDomainRE.test(everythingAfterProtocol)) {
39+
return true;
40+
}
41+
42+
return false;
2343
}

test/index.js

+11
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,15 @@ describe('is-url', function () {
119119
assert(!url('google.com'));
120120
});
121121
});
122+
123+
describe('redos', function () {
124+
it('redos exploit', function () {
125+
// Invalid. This should be discovered in under 1 second.
126+
var attackString = 'a://localhost' + '9'.repeat(100000) + '\t';
127+
var before = process.hrtime();
128+
assert(!url(attackString), 'attackString was valid');
129+
var elapsed = process.hrtime(before);
130+
assert(elapsed[0] < 1, 'attackString took ' + elapsed[0] + ' > 1 seconds');
131+
});
132+
});
122133
});

0 commit comments

Comments
 (0)