Skip to content

Commit 0d431a5

Browse files
Merge branch 'main' into chore/task-refactors-1
2 parents e5b84e8 + 0a75810 commit 0d431a5

File tree

3 files changed

+35
-2
lines changed

3 files changed

+35
-2
lines changed

.changeset/busy-weeks-hang.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@modelcontextprotocol/core': patch
3+
'@modelcontextprotocol/server': patch
4+
---
5+
6+
Fix ReDoS vulnerability in UriTemplate regex patterns (CVE-2026-0621)

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

packages/core/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)