diff --git a/package-lock.json b/package-lock.json index 64bc6f21d..af9692386 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index 41d850e15..95a3a5d53 100644 --- a/package.json +++ b/package.json @@ -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)", diff --git a/src/shared/uriTemplate.ts b/src/shared/uriTemplate.ts index 1dd57f56f..a47a64c97 100644 --- a/src/shared/uriTemplate.ts +++ b/src/shared/uriTemplate.ts @@ -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 = '([^/]+)'; diff --git a/test/shared/uriTemplate.test.ts b/test/shared/uriTemplate.test.ts index ec913c0db..5bd54d2cf 100644 --- a/test/shared/uriTemplate.test.ts +++ b/test/shared/uriTemplate.test.ts @@ -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); + }); }); });