fix: prevent ReDoS vulnerability in UriTemplate regex patterns (#1363)
Co-authored-by: Paul Carleton <paulc@anthropic.com>
This commit is contained in:
parent
6b4d99f10b
commit
0a75810b26
3 changed files with 35 additions and 2 deletions
6
.changeset/busy-weeks-hang.md
Normal file
6
.changeset/busy-weeks-hang.md
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
'@modelcontextprotocol/core': patch
|
||||
'@modelcontextprotocol/server': patch
|
||||
---
|
||||
|
||||
Fix ReDoS vulnerability in UriTemplate regex patterns (CVE-2026-0621)
|
||||
|
|
@ -225,7 +225,7 @@ export class UriTemplate {
|
|||
|
||||
switch (part.operator) {
|
||||
case '':
|
||||
pattern = part.exploded ? '([^/]+(?:,[^/]+)*)' : '([^/,]+)';
|
||||
pattern = part.exploded ? '([^/,]+(?:,[^/,]+)*)' : '([^/,]+)';
|
||||
break;
|
||||
case '+':
|
||||
case '#':
|
||||
|
|
@ -235,7 +235,7 @@ export class UriTemplate {
|
|||
pattern = '\\.([^/,]+)';
|
||||
break;
|
||||
case '/':
|
||||
pattern = '/' + (part.exploded ? '([^/]+(?:,[^/]+)*)' : '([^/,]+)');
|
||||
pattern = '/' + (part.exploded ? '([^/,]+(?:,[^/,]+)*)' : '([^/,]+)');
|
||||
break;
|
||||
default:
|
||||
pattern = '([^/]+)';
|
||||
|
|
|
|||
|
|
@ -284,5 +284,32 @@ describe('UriTemplate', () => {
|
|||
vars[longName] = 'value';
|
||||
expect(() => template.expand(vars)).not.toThrow();
|
||||
});
|
||||
|
||||
it('should not be vulnerable to ReDoS with exploded path patterns', () => {
|
||||
// Test for ReDoS vulnerability (CVE-2026-0621)
|
||||
// See: https://github.com/modelcontextprotocol/typescript-sdk/issues/965
|
||||
const template = new UriTemplate('{/id*}');
|
||||
const maliciousPayload = '/' + ','.repeat(50);
|
||||
|
||||
const startTime = Date.now();
|
||||
template.match(maliciousPayload);
|
||||
const elapsed = Date.now() - startTime;
|
||||
|
||||
// Should complete in under 100ms, not hang for seconds
|
||||
expect(elapsed).toBeLessThan(100);
|
||||
});
|
||||
|
||||
it('should not be vulnerable to ReDoS with exploded simple patterns', () => {
|
||||
// Test for ReDoS vulnerability with simple exploded operator
|
||||
const template = new UriTemplate('{id*}');
|
||||
const maliciousPayload = ','.repeat(50);
|
||||
|
||||
const startTime = Date.now();
|
||||
template.match(maliciousPayload);
|
||||
const elapsed = Date.now() - startTime;
|
||||
|
||||
// Should complete in under 100ms, not hang for seconds
|
||||
expect(elapsed).toBeLessThan(100);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue