Skip to content

Commit b392f02

Browse files
authored
fix: prevent ReDoS in UriTemplate regex patterns (v1.x backport) (#1365)
1 parent a0c9b13 commit b392f02

File tree

4 files changed

+32
-5
lines changed

4 files changed

+32
-5
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@modelcontextprotocol/sdk",
3-
"version": "1.25.1",
3+
"version": "1.25.2",
44
"description": "Model Context Protocol implementation for TypeScript",
55
"license": "MIT",
66
"author": "Anthropic, PBC (https://anthropic.com)",

src/shared/uriTemplate.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ export class UriTemplate {
225225

226226
switch (part.operator) {
227227
case '':
228-
pattern = part.exploded ? '([^/]+(?:,[^/]+)*)' : '([^/,]+)';
228+
pattern = part.exploded ? '([^/,]+(?:,[^/,]+)*)' : '([^/,]+)';
229229
break;
230230
case '+':
231231
case '#':
@@ -235,7 +235,7 @@ export class UriTemplate {
235235
pattern = '\\.([^/,]+)';
236236
break;
237237
case '/':
238-
pattern = '/' + (part.exploded ? '([^/]+(?:,[^/]+)*)' : '([^/,]+)');
238+
pattern = '/' + (part.exploded ? '([^/,]+(?:,[^/,]+)*)' : '([^/,]+)');
239239
break;
240240
default:
241241
pattern = '([^/]+)';

test/shared/uriTemplate.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,5 +284,32 @@ describe('UriTemplate', () => {
284284
vars[longName] = 'value';
285285
expect(() => template.expand(vars)).not.toThrow();
286286
});
287+
288+
it('should not be vulnerable to ReDoS with exploded path patterns', () => {
289+
// Test for ReDoS vulnerability (CVE-2026-0621)
290+
// See: https://github.com/modelcontextprotocol/typescript-sdk/issues/965
291+
const template = new UriTemplate('{/id*}');
292+
const maliciousPayload = '/' + ','.repeat(50);
293+
294+
const startTime = Date.now();
295+
template.match(maliciousPayload);
296+
const elapsed = Date.now() - startTime;
297+
298+
// Should complete in under 100ms, not hang for seconds
299+
expect(elapsed).toBeLessThan(100);
300+
});
301+
302+
it('should not be vulnerable to ReDoS with exploded simple patterns', () => {
303+
// Test for ReDoS vulnerability with simple exploded operator
304+
const template = new UriTemplate('{id*}');
305+
const maliciousPayload = ','.repeat(50);
306+
307+
const startTime = Date.now();
308+
template.match(maliciousPayload);
309+
const elapsed = Date.now() - startTime;
310+
311+
// Should complete in under 100ms, not hang for seconds
312+
expect(elapsed).toBeLessThan(100);
313+
});
287314
});
288315
});

0 commit comments

Comments
 (0)