diff --git a/docs/news.rst b/docs/news.rst index 4c4110306..aba35aa46 100644 --- a/docs/news.rst +++ b/docs/news.rst @@ -6,6 +6,20 @@ Release notes .. note:: Scrapy 1.x is the last series supporting Python 2. Scrapy 2.x supports **Python 3 only**. +.. _release-1.8.4: + +Scrapy 1.8.4 (unreleased) +------------------------- + +**Security bug fix:** + +- Fixed regular expressions susceptible to a `ReDoS attack`_ affecting the + ``iternodes`` node iterator of :class:`~scrapy.spiders.XMLFeedSpider`. + Please, see the `cc65-xxvf-f7r9 security advisory`_ for more information. + + .. _ReDoS attack: https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS + .. _cc65-xxvf-f7r9 security advisory: https://github.com/scrapy/scrapy/security/advisories/GHSA-cc65-xxvf-f7r9 + .. _release-1.8.3: Scrapy 1.8.3 (2022-07-25) diff --git a/scrapy/utils/iterators.py b/scrapy/utils/iterators.py index a12e14005..feaf4812e 100644 --- a/scrapy/utils/iterators.py +++ b/scrapy/utils/iterators.py @@ -26,7 +26,7 @@ def xmliter(obj, nodename): """ nodename_patt = re.escape(nodename) - HEADER_START_RE = re.compile(r'^(.*?)<\s*%s(?:\s|>)' % nodename_patt, re.S) + HEADER_START_RE = re.compile(r'^(.{,1024}?)<\s*%s(?:\s|>)' % nodename_patt, re.S) HEADER_END_RE = re.compile(r'<\s*/%s\s*>' % nodename_patt, re.S) text = _body_or_str(obj) @@ -35,7 +35,7 @@ def xmliter(obj, nodename): header_end = re_rsearch(HEADER_END_RE, text) header_end = text[header_end[1]:].strip() if header_end else '' - r = re.compile(r'<%(np)s[\s>].*?' % {'np': nodename_patt}, re.DOTALL) + r = re.compile(r'<%(np)s[\s>].{,1024}?' % {'np': nodename_patt}, re.DOTALL) for match in r.finditer(text): nodetext = header_start + match.group() + header_end yield Selector(text=nodetext, type='xml').xpath('//' + nodename)[0]