From 9f7a2144dfe028e1d718a52b6e6ffbfec1483c34 Mon Sep 17 00:00:00 2001 From: Norbert Biczo Date: Fri, 24 Jul 2026 16:17:02 +0200 Subject: [PATCH] Revert "fix: resolve ReDoS vulnerability in casing convention rules (#825)" This reverts commit 30d9a513ca77e73a45f83810328042d21dc5f2c4. --- .../src/rules/parameter-casing-convention.js | 2 +- .../src/rules/schema-casing-convention.js | 2 +- .../rules/parameter-casing-convention.test.js | 31 ------------------- .../rules/schema-casing-convention.test.js | 27 ---------------- 4 files changed, 2 insertions(+), 60 deletions(-) diff --git a/packages/ruleset/src/rules/parameter-casing-convention.js b/packages/ruleset/src/rules/parameter-casing-convention.js index c7906844d..f234b1c11 100644 --- a/packages/ruleset/src/rules/parameter-casing-convention.js +++ b/packages/ruleset/src/rules/parameter-casing-convention.js @@ -45,7 +45,7 @@ module.exports = { // Spectral casing convention types aren't robust enough to handle // the complexity of headers, so we define our own kebab/pascal case regex. header: { - match: '/^[A-Z][A-Za-z0-9]*(?:-[A-Z][A-Za-z0-9]*)*$/', + match: '/^[A-Z]+[a-z0-9]*-*([A-Z]+[a-z0-9]*-*)*$/', }, // Define an alternate message for the header pattern validation diff --git a/packages/ruleset/src/rules/schema-casing-convention.js b/packages/ruleset/src/rules/schema-casing-convention.js index b3cefaccb..76579a13a 100644 --- a/packages/ruleset/src/rules/schema-casing-convention.js +++ b/packages/ruleset/src/rules/schema-casing-convention.js @@ -15,7 +15,7 @@ module.exports = { then: { function: schemaCasingConvention, functionOptions: { - match: '/^[A-Z](?:[A-Z]*[a-z0-9]+)+$/', + match: '/^[A-Z]+[a-z0-9]+([A-Z]+[a-z0-9]*)*$/', }, }, }; diff --git a/packages/ruleset/test/rules/parameter-casing-convention.test.js b/packages/ruleset/test/rules/parameter-casing-convention.test.js index 0d337f26d..b6f828b57 100644 --- a/packages/ruleset/test/rules/parameter-casing-convention.test.js +++ b/packages/ruleset/test/rules/parameter-casing-convention.test.js @@ -178,37 +178,6 @@ describe(`Spectral rule: ${ruleId}`, () => { const results = await testRule(ruleId, rule, testDocument); expect(results).toHaveLength(0); }); - - it('Should handle potential ReDoS patterns efficiently', async () => { - const testDocument = makeCopy(rootDocument); - - // Pattern that would cause catastrophic backtracking in old regex - // Old pattern: /^[A-Z]+[a-z0-9]*-*([A-Z]+[a-z0-9]*-*)*$/ - // This input would cause exponential time complexity - const maliciousHeader = 'A' + 'A-'.repeat(50); - - testDocument.paths['/v1/movies'].get.parameters.push({ - description: 'Header with ReDoS attack pattern', - name: maliciousHeader, - required: false, - in: 'header', - schema: { - type: 'string', - }, - }); - - const startTime = Date.now(); - const results = await testRule(ruleId, rule, testDocument); - const duration = Date.now() - startTime; - - // Should complete quickly (well under 500ms) with fixed regex - // Note: Includes test overhead; actual regex execution is much faster - expect(duration).toBeLessThan(500); - // Should still validate correctly and reject the malformed header - expect(results).toHaveLength(1); - expect(results[0].code).toBe(ruleId); - expect(results[0].message).toBe(expectedMsgHeader); - }); }); describe('Should yield errors', () => { diff --git a/packages/ruleset/test/rules/schema-casing-convention.test.js b/packages/ruleset/test/rules/schema-casing-convention.test.js index ad9e50944..67a890878 100644 --- a/packages/ruleset/test/rules/schema-casing-convention.test.js +++ b/packages/ruleset/test/rules/schema-casing-convention.test.js @@ -65,33 +65,6 @@ describe(`Spectral rule: ${ruleId}`, () => { const results = await testRule(ruleId, rule, testDocument); expect(results).toHaveLength(0); }); - - it('Should handle potential ReDoS patterns efficiently', async () => { - const testDocument = makeCopy(rootDocument); - - // Pattern that would cause catastrophic backtracking in old regex - // Old pattern: /^[A-Z]+[a-z0-9]+([A-Z]+[a-z0-9]*)*$/ - // This input would cause exponential time complexity - const maliciousSchemaName = 'A' + 'Aa'.repeat(50); - - testDocument.components.schemas[maliciousSchemaName] = { - type: 'object', - properties: { - id: { type: 'string' }, - }, - }; - - const startTime = Date.now(); - const results = await testRule(ruleId, rule, testDocument); - const duration = Date.now() - startTime; - - // Should complete quickly (well under 500ms) with fixed regex - // Note: Includes test overhead; actual regex execution is much faster - expect(duration).toBeLessThan(500); - // Should still validate correctly - this pattern should actually pass - // as it matches the upper camel case pattern - expect(results).toHaveLength(0); - }); }); describe('Should yield errors', () => {