mirror of https://github.com/scrapy/scrapy.git
Set an arbitrary upper limit on ReDoS-vulnerable regexps
This commit is contained in:
parent
5fccf370b8
commit
c947f51077
|
|
@ -3,6 +3,22 @@
|
|||
Release notes
|
||||
=============
|
||||
|
||||
.. _release-2.11.1:
|
||||
|
||||
Scrapy 2.11.1 (unreleased)
|
||||
--------------------------
|
||||
|
||||
**Security bug fix:**
|
||||
|
||||
- The regular expressions of the ``iternodes`` node iterator of
|
||||
:class:`~scrapy.spiders.XMLFeedSpider` are no longer susceptible to a
|
||||
`ReDoS attack`_. 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-2.11.0:
|
||||
|
||||
Scrapy 2.11.0 (2023-09-18)
|
||||
|
|
@ -2869,6 +2885,18 @@ affect subclasses:
|
|||
|
||||
(:issue:`3884`)
|
||||
|
||||
.. _release-1.8.4:
|
||||
|
||||
Scrapy 1.8.4 (unreleased)
|
||||
-------------------------
|
||||
|
||||
**Security bug fix:**
|
||||
|
||||
- The regular expressions of the ``iternodes`` node iterator of
|
||||
:class:`~scrapy.spiders.XMLFeedSpider` are no longer susceptible to a
|
||||
`ReDoS attack`_. Please, see the `cc65-xxvf-f7r9 security
|
||||
advisory`_ for more information.
|
||||
|
||||
|
||||
.. _release-1.8.3:
|
||||
|
||||
|
|
|
|||
|
|
@ -40,10 +40,10 @@ def xmliter(
|
|||
"""
|
||||
nodename_patt = re.escape(nodename)
|
||||
|
||||
DOCUMENT_HEADER_RE = re.compile(r"<\?xml[^>]+>\s*", re.S)
|
||||
DOCUMENT_HEADER_RE = re.compile(r"<\?xml[^>]{1,1024}>\s*", re.S)
|
||||
HEADER_END_RE = re.compile(rf"<\s*/{nodename_patt}\s*>", re.S)
|
||||
END_TAG_RE = re.compile(r"<\s*/([^\s>]+)\s*>", re.S)
|
||||
NAMESPACE_RE = re.compile(r"((xmlns[:A-Za-z]*)=[^>\s]+)", re.S)
|
||||
END_TAG_RE = re.compile(r"<\s*/([^\s>]{1,1024})\s*>", re.S)
|
||||
NAMESPACE_RE = re.compile(r"((xmlns[:A-Za-z]{,1024})=[^>\s]+)", re.S)
|
||||
text = _body_or_str(obj)
|
||||
|
||||
document_header_match = re.search(DOCUMENT_HEADER_RE, text)
|
||||
|
|
@ -57,13 +57,15 @@ def xmliter(
|
|||
for tagname in reversed(re.findall(END_TAG_RE, header_end)):
|
||||
assert header_end_idx
|
||||
tag = re.search(
|
||||
rf"<\s*{tagname}.*?xmlns[:=][^>]*>", text[: header_end_idx[1]], re.S
|
||||
rf"<\s*{tagname}.{{,1024}}?xmlns[:=][^>]{{,1024}}>",
|
||||
text[: header_end_idx[1]],
|
||||
re.S,
|
||||
)
|
||||
if tag:
|
||||
for x in re.findall(NAMESPACE_RE, tag.group()):
|
||||
namespaces[x[1]] = x[0]
|
||||
|
||||
r = re.compile(rf"<{nodename_patt}[\s>].*?</{nodename_patt}>", re.DOTALL)
|
||||
r = re.compile(rf"<{nodename_patt}[\s>].{{,1024}}?</{nodename_patt}>", re.DOTALL)
|
||||
for match in r.finditer(text):
|
||||
nodetext = (
|
||||
document_header
|
||||
|
|
|
|||
|
|
@ -91,8 +91,8 @@ def open_in_browser(
|
|||
if isinstance(response, HtmlResponse):
|
||||
if b"<base" not in body:
|
||||
repl = rf'\1<base href="{response.url}">'
|
||||
body = re.sub(b"<!--.*?-->", b"", body, flags=re.DOTALL)
|
||||
body = re.sub(rb"(<head(?:>|\s.*?>))", to_bytes(repl), body)
|
||||
body = re.sub(b"<!--.{,1024}?-->", b"", body, flags=re.DOTALL)
|
||||
body = re.sub(rb"(<head(?:>|\s.{,1024}?>))", to_bytes(repl), body)
|
||||
ext = ".html"
|
||||
elif isinstance(response, TextResponse):
|
||||
ext = ".txt"
|
||||
|
|
|
|||
Loading…
Reference in New Issue