fix: prevent ReDoS in UriTemplate regex patterns (v1.x backport) (#1365)

This commit is contained in:
Paul Carleton 2026-01-07 14:37:11 +00:00 • committed by GitHub
commit b392f02ffc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 32 additions and 5 deletions

4
package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "@modelcontextprotocol/sdk",
"version": "1.25.1",
"version": "1.25.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@modelcontextprotocol/sdk",
"version": "1.25.1",
"version": "1.25.2",
"license": "MIT",
"dependencies": {
"@hono/node-server": "^1.19.7",

View file

@ -1,6 +1,6 @@
{
"name": "@modelcontextprotocol/sdk",
"version": "1.25.1",
"version": "1.25.2",
"description": "Model Context Protocol implementation for TypeScript",
"license": "MIT",
"author": "Anthropic, PBC (https://anthropic.com)",

View file

@ -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 = '([^/]+)';

View file

@ -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);
});
});
});