Skip to content
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: remove catastrophic backtracking vulnerability #10019

Merged
merged 1 commit into from Feb 27, 2018

Conversation

davisjam
Copy link
Contributor

What is the purpose of this pull request? (put an "X" next to item)

[ ] Documentation update
[X] Bug fix (template)
[ ] New rule (template)
[ ] Changes an existing rule (template)
[ ] Add autofixing to a rule
[ ] Add a CLI option
[ ] Add something to the core
[ ] Other, please explain:

What changes did you make? (Give an overview)

Change template substitution regex to exclude fields with whitespace.
This addresses possible O(n^2) catastrophic backtracking behavior.
The function behavior is unchanged.

Very unlikely to be exploited. For #10002.

Is there anything you'd like reviewers to focus on?

No.

@jsf-clabot
Copy link

jsf-clabot commented Feb 24, 2018

CLA assistant check
All committers have signed the CLA.

@eslint-deprecated eslint-deprecated bot added the triage An ESLint team member will look at this issue soon label Feb 24, 2018
@davisjam davisjam changed the title security: fix catastrophic backtracking vulnerability Fix: remove catastrophic backtracking vulnerability Feb 24, 2018
Copy link
Sponsor Contributor

@ljharb ljharb left a comment

Choose a reason for hiding this comment

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

So it's just the \s* that's problematic here?

return text.replace(/\{\{([^{}]+?)\}\}/g, (fullMatch, term) => {

// Strip leading and trailing whitespace.
term = term.replace(/^\s+|\s+$/g, "");
Copy link
Sponsor Contributor

Choose a reason for hiding this comment

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

term.trim()?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Haha! I knew there had to be a function for that.

Change template substitution regex to exclude fields with whitespace.
This addresses possible O(n^2) catastrophic backtracking behavior.

Very unlikely to be exploited. For eslint#10002.
@davisjam
Copy link
Contributor Author

davisjam commented Feb 24, 2018

So it's just the \s* that's problematic here?

A bit more complex than that. The original pattern contains a sub-sequence like this:

\s*[^{}]+\s*

Because the middle group's character class includes whitespace, it will match a superset of this pattern, which is easier to reason about:

\s*\s+\s*

If the input contains a long sequence of whitespace, the regex engine has to decide when to move from one \s to the next.
If the input doesn't match the pattern, the regex engine tries every subdivision of the whitespace looking for a match. It lays breadcrumbs each time it makes a decision to resolve ambiguity, and revisiting each breadcrumb is called backtracking. If there is a long sequence of whitespace, it has a lot of breadcrumbs to visit, and will get "stuck". This behavior is called catastrophic backtracking.

The blow-up in this case is O(n^2). In the worst case catastrophic backtracking can be O(2^n).

@davisjam
Copy link
Contributor Author

davisjam commented Feb 24, 2018

It would be helpful if a developer can comment on whether this is a very low-risk security problem or just a potential problem if someone else were to copy/paste later.

If a real problem, I will follow up with Snyk.io to get a low-severity vulnerability ID assigned.

@ljharb
Copy link
Sponsor Contributor

ljharb commented Feb 24, 2018

It's an eslint rule config; imo it's the lowest nonzero risk you can get :-)

@not-an-aardvark
Copy link
Member

I don't think this is realistically exploitable, because only an ESLint rule can provide a string to that regex, and an ESLint rule already can execute arbitrary code. So I'm fine with removing it for performance reasons, but I don't consider this to be a security issue in its current location.

@not-an-aardvark not-an-aardvark added bug ESLint is working incorrectly core Relates to ESLint's core APIs and features accepted There is consensus among the team that this change meets the criteria for inclusion and removed triage An ESLint team member will look at this issue soon labels Feb 24, 2018
Copy link
Member

@not-an-aardvark not-an-aardvark left a comment

Choose a reason for hiding this comment

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

Looks good to me, thanks!

Copy link
Member

@platinumazure platinumazure left a comment

Choose a reason for hiding this comment

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

LGTM, this seems reasonable and doesn't make things much harder to read. Thanks for the PR!

This was referenced Mar 22, 2018
@eslint-deprecated eslint-deprecated bot locked and limited conversation to collaborators Aug 28, 2018
@eslint-deprecated eslint-deprecated bot added the archived due to age This issue has been archived; please open a new issue for any further discussion label Aug 28, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
accepted There is consensus among the team that this change meets the criteria for inclusion archived due to age This issue has been archived; please open a new issue for any further discussion bug ESLint is working incorrectly core Relates to ESLint's core APIs and features
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants