Skip to content

Fix JavaScript ReDoS#6020

Open
AZborovskyyEpam wants to merge 1 commit intodatacommonsorg:masterfrom
AZborovskyyEpam:fix_js_redos
Open

Fix JavaScript ReDoS#6020
AZborovskyyEpam wants to merge 1 commit intodatacommonsorg:masterfrom
AZborovskyyEpam:fix_js_redos

Conversation

@AZborovskyyEpam
Copy link
Copy Markdown

Fix for complex regular expressions with potential for catastrophic backtracking when processing user input.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @AZborovskyyEpam, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a critical security concern by mitigating Regular Expression Denial of Service (ReDoS) attacks. It introduces a standardized approach to handling regular expressions by validating patterns for safety and escaping user-provided input, thereby preventing malicious or overly complex regexes from consuming excessive server resources and causing application slowdowns or crashes. The changes ensure that all regex operations involving dynamic input are secure and performant.

Highlights

  • ReDoS Vulnerability Fix: Implemented a comprehensive fix for potential Regular Expression Denial of Service (ReDoS) vulnerabilities by introducing a new utility module for safe regex handling.
  • New Regex Utility Module: Added a new utility file, static/js/utils/regex_utils.ts, which centralizes functions for escaping special regex characters, checking regex safety using the safe-regex library, and creating safe RegExp objects.
  • Widespread Integration of Regex Safety Checks: Integrated the new regex safety functions across various parts of the application, including search input processing, place ID lookups, JSX highlighting, tile formatting, and server-side query handling, to sanitize user-provided input before regex operations.
  • Dependency Update: Added safe-regex and its TypeScript type definitions (@types/safe-regex) to the project dependencies to enable robust regex pattern validation.
Changelog
  • static/js/search/search_input.tsx
    • Imported escapeRegexSpecialChars and isSafeRegexPattern from regex_utils.
    • Modified the matches array creation to filter out unsafe regex patterns from user input before further processing.
  • static/js/utils/place_utils.ts
    • Imported escapeRegexSpecialChars and isSafeRegexPattern from regex_utils.
    • Applied regex safety checks to the query parameter in getPlaceId to ensure only safe queries are used for Google Places API requests.
  • static/js/utils/regex_utils.ts
    • Added a new file containing escapeRegexSpecialChars to escape special characters in a string for regex use.
    • Added isSafeRegexPattern to check if a given regex pattern is safe from catastrophic backtracking using the safe-regex library.
    • Added getSafeRegExp to create a RegExp object only if the pattern is deemed safe.
  • static/js/utils/search_utils.tsx
    • Imported getSafeRegExp from regex_utils.
    • Replaced direct new RegExp calls with getSafeRegExp in getHighlightedJSX to ensure only safe regex patterns are used for highlighting, removing the previous try-catch block.
  • static/js/utils/tile_utils.tsx
    • Imported escapeRegexSpecialChars, getSafeRegExp, and isSafeRegexPattern from regex_utils.
    • Modified formatString to use escapeRegexSpecialChars and getSafeRegExp when constructing regex patterns for string replacement.
    • Applied isSafeRegexPattern to validate regex patterns used in getProcessedUnit and getStatFormat before execution.
  • static/nodejs_server/query.ts
    • Imported escapeRegexSpecialChars and isSafeRegexPattern from regex_utils.
    • Applied regex safety checks to the query parameter in getQueryResult before using it in API calls and URL encoding.
  • static/package.json
    • Added @types/safe-regex to devDependencies.
    • Added safe-regex to dependencies.
  • static/src/server.ts
    • Imported escapeRegexSpecialChars and isSafeRegexPattern from regex_utils.
    • Applied regex safety checks to the incoming req.query.q parameter in the /nodejs/query endpoint to sanitize user input.
Activity
  • No human activity recorded for this pull request.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The pull request effectively addresses potential Regular Expression Denial of Service (ReDoS) vulnerabilities by introducing a regex_utils.ts file with functions to escape special characters and validate regex patterns using the safe-regex library. The changes are applied consistently across search_input.tsx, place_utils.ts, search_utils.tsx, tile_utils.tsx, and query.ts to sanitize user input before creating regular expressions or using it in API calls. The package.json file is updated to include the safe-regex dependency. This is a critical security improvement. Comments regarding redundant safety checks for hardcoded regex patterns have been noted.

Comment on lines +317 to +319
const safeQuery = isSafeRegexPattern(escapeRegexSpecialChars(query))
? query
: "";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The safeQuery variable is introduced to sanitize the query parameter from the request. This is a critical security improvement to prevent ReDoS attacks by ensuring that only safe regex patterns are processed. If the rawQuery is deemed unsafe, it defaults to an empty string, which is a reasonable defensive measure.

Comment thread static/src/server.ts
Comment on lines +302 to +305
const rawQuery = (req.query.q as string) || "";
const query = isSafeRegexPattern(escapeRegexSpecialChars(rawQuery))
? rawQuery
: "";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The rawQuery from the request is now sanitized using escapeRegexSpecialChars and validated with isSafeRegexPattern before being assigned to query. This is a critical security measure to prevent ReDoS attacks from user-supplied input. If the rawQuery is unsafe, it defaults to an empty string, which is a robust way to handle malicious input.

// TODO: only generate related things when we need to generate related question
let nlResp = null;
let url = `${apiRoot}/api/explore/detect-and-fulfill?q=${query}&detector=${
let url = `${apiRoot}/api/explore/detect-and-fulfill?q=${safeQuery}&detector=${
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The url construction now uses safeQuery instead of the original query. This ensures that the query parameter passed to the /api/explore/detect-and-fulfill endpoint is sanitized, mitigating potential ReDoS vulnerabilities in downstream services if they process this query as a regex.

.filter((result) => result !== null);
processedResults.forEach((result) => {
result.dcUrl = DC_URL_ROOT + encodeURIComponent(query as string);
result.dcUrl = DC_URL_ROOT + encodeURIComponent(safeQuery as string);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The dcUrl now uses safeQuery when encoding the URL. This is important for consistency and to ensure that any potentially malicious or malformed regex patterns in the original query do not propagate to the generated Data Commons URL.

Comment on lines +23 to +28
export function isSafeRegexPattern(pattern: string | RegExp): boolean {
try {
return Boolean(safeRegex(pattern));
} catch {
return false;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The isSafeRegexPattern function uses a try-catch block around safeRegex(pattern). While this handles potential errors from safe-regex, it might mask issues if safeRegex throws an unexpected error. It's good practice to log the error in the catch block to aid debugging.

Comment on lines +63 to +67
const matches = inputText
.split(" ")
.filter((match) =>
isSafeRegexPattern(`(${escapeRegexSpecialChars(match.toLowerCase())})`)
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The filter operation here ensures that only safe regex patterns are used. This is a good step to prevent ReDoS attacks. However, if isSafeRegexPattern returns false, the match is filtered out, which might lead to unexpected behavior for legitimate user inputs that are deemed unsafe. Consider logging or handling such cases to provide a better user experience or to understand why certain inputs are being dropped.

Comment on lines +1 to +15
/**
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The copyright year is set to 2026. This seems like a typo and should be updated to the current year.

Comment thread static/package.json
"@types/react-table": "^7.7.12",
"@types/reactstrap": "^8.7.1",
"@types/resize-observer-browser": "^0.1.6",
"@types/safe-regex": "^1.1.6",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Adding @types/safe-regex as a dev dependency is good for type safety when using the safe-regex library.

Comment thread static/package.json
"rehype-raw": "^7.0.0",
"remark-gfm": "^3.0.1",
"resize-observer-polyfill": "^1.5.1",
"safe-regex": "^2.1.1",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Adding safe-regex as a dependency is crucial for implementing the ReDoS protection. This library helps in identifying potentially vulnerable regular expressions.

Comment on lines +327 to +329
const safeQuery = isSafeRegexPattern(escapeRegexSpecialChars(query))
? query
: "";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The safeQuery variable is correctly introduced to sanitize the query before it's used in the request object. This prevents potential injection vulnerabilities. However, if the query is deemed unsafe, it's replaced with an empty string. This might lead to an empty search result without clear indication to the user. Consider adding a warning or a more robust fallback mechanism.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant