Skip to content

Commit

Permalink
fix(rate-limit): update regex to remove email alias
Browse files Browse the repository at this point in the history
Fixes: https://github.com/guardian/gateway/security/code-scanning/23

The old regex is possibly vulnerable to ReDoS attacks when removing email aliases. Where the old regex may run slow on strings starting with '+' and with many repetitions of '+'.

Although it is unlikely an attacker could use this to perform a DoS attack, as emails are already validated in Identity/Okta, we should still prevent the possibility of this occuring.

This PR fixes the regex to make it safe.

```
- const removalRegex = /\+.*@/g;
+ const removalRegex = /\+[^@]*@/g;
```

The fix uses `[^@]*` instead of `.*` to explicitly match non-`@` characters, which prevents backtracking as the new regex stops at the first `@`.

For example with the old behaviour:

```
Input: "[email protected]"

1. Matches '+'
2. '.*' greedily consumes all characters
3. Fails to match '@' at end
4. Backtracks one character at a time until '@' is found
```

With the worst case scenario being with time complexity `O(2^n)`.

```
Input: "test+aaaaaaaaaaaaaaaaaaaaaaX" (no @ symbol)

1. '+' matches
2. '.*' greedily consumes all 'a's
3. Fails to find '@'
4. Backtracks for each 'a'
5. Try all possible combinations
```

Now with the new regex for both examples:

```
Input: "[email protected]"

1. Matches '+'
2. [^@]* matches any non-@ character deterministically
3. Stops immediately when '@' is found
4. No backtracking needed
```

and for the worst case scenario

```
Input: "test+aaaaaaaaaaaaaaaaaaaaaaX" (no @ symbol)

1. '+' matches
2. [^@]* matches all non-@ chars in one pass
3. Fails to find '@', moves on
4. No backtracking
```

which now has timecomplexity `O(n)` regarless of input, reducing the chance of a ReDoS attack.
  • Loading branch information
coldlink committed Feb 4, 2025
1 parent 59d891f commit 2d11c59
Showing 1 changed file with 1 addition and 1 deletion.
2 changes: 1 addition & 1 deletion src/server/lib/rate-limit/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const getRateLimitKey = (
) => `gw-rl-${route}-${bucketName}${value ? '-' + sha256(value) : ''}`;

const removeEmailAlias = (email?: string) => {
const removalRegex = /\+.*@/g;
const removalRegex = /\+[^@]*@/g;
return email?.replace(removalRegex, '@');

Check failure

Code scanning / CodeQL

Polynomial regular expression used on uncontrolled data High

This
regular expression
that depends on
a user-provided value
may run slow on strings starting with '+' and with many repetitions of '+'.
};

Expand Down

0 comments on commit 2d11c59

Please sign in to comment.