-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix ReDoS when parsing colors #3382
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @matias-la, Thanks for your PR!
## Description The regular expression used to parse numbers could be abused to cause a denial of service if the color to be parsed is controlled by an attacker. For information about this vulnerability, see https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS. ## Changes Changed the code so the new regex isn't vulnerable, since there's always only one possible path to take given any input. Here is a proof-of-concept of how I made the existing regular expression cause a 100% CPU usage for several seconds, after being interrupted: ``` Welcome to Node.js v14.19.3. Type ".help" for more information. > (new RegExp('^[-+]?\\d*\\.?\\d+$')).test(`${'1'.repeat(1e6)}z`) ^CUncaught Error: Script execution was interrupted by `SIGINT` at Script.runInThisContext (vm.js:134:12) at REPLServer.defaultEval (repl.js:566:29) at bound (domain.js:421:15) at REPLServer.runBound [as eval] (domain.js:432:12) at REPLServer.onLine (repl.js:909:10) at REPLServer.emit (events.js:412:35) at REPLServer.emit (domain.js:475:12) at REPLServer.Interface._onLine (readline.js:434:10) at REPLServer.Interface._line (readline.js:791:8) at REPLServer.Interface._ttyWrite (readline.js:1136:14) { code: 'ERR_SCRIPT_EXECUTION_INTERRUPTED' } > (new RegExp('^[-+]?\\d*(?:\\.\\d*)?$')).test(`${'1'.repeat(1e6)}z`) // the new regex works fine false > ``` ## Checklist - [X] Included code example that can be used to test this change - [ ] Updated TS types - [ ] Added TS types tests - [ ] Added unit / integration tests - [ ] Updated documentation - [ ] Ensured that CI passes
@matias-la @piaskowyk ... just to be sure, is it OK that the new regex accepts empty string and returns true? OLD > (new RegExp('^[-+]?\\d*\\.?\\d+$')).test('')
false NEW > (new RegExp('^[-+]?\\d*(?:\\.\\d*)?$')).test(``)
true |
Oops, nice catch! I hadn't notice that. The change in #3419 look good, as it prevents empty strings from matching while also not being vulnerable to ReDoS. |
## Description PR based on issue requested in comment: #3382 (comment) I updated the regex to prevent empty string matches. The new regex `[-+]?(?:\d+(?:\.\d*)?|\.\d+)` - https://regex101.com/r/aHhlXG/1 is equivalent with the old version `[-+]?\d*\.?\d+` - https://regex101.com/r/Z0xMqR/1 I also tested ReDoS, and the new regex is safe. ``` (new RegExp('^[-+]?(?:\d+(?:\.\d*)?|\.\d+)$')).test(`${'1'.repeat(1e6)}z`) ```
## Description PR based on issue requested in comment: #3382 (comment) I updated the regex to prevent empty string matches. The new regex `[-+]?(?:\d+(?:\.\d*)?|\.\d+)` - https://regex101.com/r/aHhlXG/1 is equivalent with the old version `[-+]?\d*\.?\d+` - https://regex101.com/r/Z0xMqR/1 I also tested ReDoS, and the new regex is safe. ``` (new RegExp('^[-+]?(?:\d+(?:\.\d*)?|\.\d+)$')).test(`${'1'.repeat(1e6)}z`) ```
## Description The regular expression used to parse numbers could be abused to cause a denial of service if the color to be parsed is controlled by an attacker. For information about this vulnerability, see https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS. ## Changes Changed the code so the new regex isn't vulnerable, since there's always only one possible path to take given any input. Here is a proof-of-concept of how I made the existing regular expression cause a 100% CPU usage for several seconds, after being interrupted: ``` Welcome to Node.js v14.19.3. Type ".help" for more information. > (new RegExp('^[-+]?\\d*\\.?\\d+$')).test(`${'1'.repeat(1e6)}z`) ^CUncaught Error: Script execution was interrupted by `SIGINT` at Script.runInThisContext (vm.js:134:12) at REPLServer.defaultEval (repl.js:566:29) at bound (domain.js:421:15) at REPLServer.runBound [as eval] (domain.js:432:12) at REPLServer.onLine (repl.js:909:10) at REPLServer.emit (events.js:412:35) at REPLServer.emit (domain.js:475:12) at REPLServer.Interface._onLine (readline.js:434:10) at REPLServer.Interface._line (readline.js:791:8) at REPLServer.Interface._ttyWrite (readline.js:1136:14) { code: 'ERR_SCRIPT_EXECUTION_INTERRUPTED' } > (new RegExp('^[-+]?\\d*(?:\\.\\d*)?$')).test(`${'1'.repeat(1e6)}z`) // the new regex works fine false > ``` ## Checklist - [X] Included code example that can be used to test this change - [ ] Updated TS types - [ ] Added TS types tests - [ ] Added unit / integration tests - [ ] Updated documentation - [ ] Ensured that CI passes
## Description PR based on issue requested in comment: software-mansion#3382 (comment) I updated the regex to prevent empty string matches. The new regex `[-+]?(?:\d+(?:\.\d*)?|\.\d+)` - https://regex101.com/r/aHhlXG/1 is equivalent with the old version `[-+]?\d*\.?\d+` - https://regex101.com/r/Z0xMqR/1 I also tested ReDoS, and the new regex is safe. ``` (new RegExp('^[-+]?(?:\d+(?:\.\d*)?|\.\d+)$')).test(`${'1'.repeat(1e6)}z`) ```
Description
The regular expression used to parse numbers could be abused to cause a denial of service if the color to be parsed is controlled by an attacker.
For information about this vulnerability, see https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS.
Changes
Changed the code so the new regex isn't vulnerable, since there's always only one possible path to take given any input.
Here is a proof-of-concept of how I made the existing regular expression cause a 100% CPU usage for several seconds, after being interrupted:
Checklist