Skip to content

Bound the author-email match to avoid quadratic parsing on hostile feeds - #580

Open
arpitjain099 wants to merge 1 commit into
kurtmckee:mainfrom
arpitjain099:chore/bound-author-email-redos
Open

Bound the author-email match to avoid quadratic parsing on hostile feeds#580
arpitjain099 wants to merge 1 commit into
kurtmckee:mainfrom
arpitjain099:chore/bound-author-email-redos

Conversation

@arpitjain099

Copy link
Copy Markdown

Feeds are untrusted input, so any regex run over feed-controlled text needs to stay linear. The author-email pattern in mixin.py does not: its domain alternative (([a-zA-Z0-9-]+\.)+) overlaps the trailing label group, so on a long, almost-matching value it backtracks quadratically. _sync_author_detail runs email_pattern.search(author) directly on the text from an <author> or dc:creator element, with no length bound.

I reproduced it on the current main. A single item whose author is "a@" + "a."*N + "!" gives, measuring CPU time on one core:

  • N=8000 (author ~16 KB): 1.14 s
  • N=16000 (author ~32 KB): 4.54 s

Doubling the input roughly quadruples the time, so a ~64 KB author field is around 19 s. That is enough for one crafted feed to tie up an ingester.

The fix is a length guard: only feed author to the pattern when it is short enough to plausibly hold an address. RFC 5321 caps an address at 254 octets, and I left generous room for a display name alongside it, so no real author string is affected. Longer values just skip the email match and keep their name verbatim. After the change the 32 KB case parses in a few milliseconds, and I confirmed the usual forms (Name (me@example.com), a bare me@example.com, and Name <me@example.com>) still split out the email exactly as before.

Added tests/test_author_email_bound.py covering the normal extraction plus an oversized author that must parse without pulling an email out of it. I kept the timing out of the assertions to avoid a flaky test and put the numbers here instead. Full suite passes (4300 passed, 8 skipped) and mypy is clean. There is a Security changelog fragment as well.

The author-email pattern's domain part backtracks quadratically on long,
almost-matching strings, and feeds are untrusted input. A crafted <author>
or dc:creator value around 32 KB makes feedparser.parse() burn several
seconds of CPU, and it scales O(N^2), so a larger value is worse.

Guard the length before running the search: values longer than a name plus
an RFC 5321 sized address are not real author strings, so skip the match for
them. Normal author and email parsing is unchanged.

Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
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