[FIX] core: restrict httprequest attributes
The version of werkzeug installed can vary from one deployment to another, as we recommend to use the operating system package, and the version can therefore change according to the operating system version. e.g. the werkzeug version installed using `apt install python3-werkzeug` varies between Ubuntu 18.04, 20.04, 22.04, 23.10, ... We want to keep under control the attributes developers use on werkzeug.wrappers.Request, to avoid compatibility issues from one version to another. Therefore, this revision aims to subclass werkzeug.wrappers.Request to limit the attributes which can be used. task-3734305 Part-of: odoo/odoo#78857 Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
This commit is contained in:
+44
-5
@@ -1165,6 +1165,49 @@ def borrow_request():
|
||||
_request_stack.push(req)
|
||||
|
||||
|
||||
def make_request_wrap_methods(attr):
|
||||
def getter(self):
|
||||
return getattr(self._HTTPRequest__wrapped, attr)
|
||||
|
||||
def setter(self, value):
|
||||
return setattr(self._HTTPRequest__wrapped, attr, value)
|
||||
|
||||
return getter, setter
|
||||
|
||||
|
||||
class HTTPRequest:
|
||||
def __init__(self, environ):
|
||||
httprequest = werkzeug.wrappers.Request(environ)
|
||||
httprequest.user_agent_class = UserAgent # use vendored userAgent since it will be removed in 2.1
|
||||
httprequest.parameter_storage_class = werkzeug.datastructures.ImmutableOrderedMultiDict
|
||||
httprequest.max_content_length = DEFAULT_MAX_CONTENT_LENGTH
|
||||
|
||||
self.__wrapped = httprequest
|
||||
self.__environ = self.__wrapped.environ
|
||||
self.environ = {
|
||||
key: value
|
||||
for key, value in self.__environ.items()
|
||||
if (not key.startswith(('werkzeug.', 'wsgi.', 'socket')) or key in ['wsgi.url_scheme'])
|
||||
}
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
|
||||
HTTPREQUEST_ATTRIBUTES = [
|
||||
'__str__', '__repr__', '__exit__',
|
||||
'accept_charsets', 'accept_languages', 'accept_mimetypes', 'access_route', 'args', 'authorization', 'base_url',
|
||||
'charset', 'content_encoding', 'content_length', 'content_md5', 'content_type', 'cookies', 'data', 'date',
|
||||
'encoding_errors', 'files', 'form', 'full_path', 'get_data', 'get_json', 'headers', 'host', 'host_url', 'if_match',
|
||||
'if_modified_since', 'if_none_match', 'if_range', 'if_unmodified_since', 'is_json', 'is_secure', 'json',
|
||||
'max_content_length', 'method', 'mimetype', 'mimetype_params', 'origin', 'path', 'pragma', 'query_string', 'range',
|
||||
'referrer', 'remote_addr', 'remote_user', 'root_path', 'root_url', 'scheme', 'script_root', 'server', 'session',
|
||||
'trusted_hosts', 'url', 'url_charset', 'url_root', 'user_agent', 'values',
|
||||
]
|
||||
for attr in HTTPREQUEST_ATTRIBUTES:
|
||||
setattr(HTTPRequest, attr, property(*make_request_wrap_methods(attr)))
|
||||
|
||||
|
||||
class Response(werkzeug.wrappers.Response):
|
||||
"""
|
||||
Outgoing HTTP response with body, status, headers and qweb support.
|
||||
@@ -2132,11 +2175,7 @@ class Application:
|
||||
return
|
||||
ProxyFix(fake_app)(environ, fake_start_response)
|
||||
|
||||
with werkzeug.wrappers.Request(environ) as httprequest:
|
||||
httprequest.user_agent_class = UserAgent # use vendored userAgent since it will be removed in 2.1
|
||||
httprequest.parameter_storage_class = (
|
||||
werkzeug.datastructures.ImmutableOrderedMultiDict)
|
||||
httprequest.max_content_length = DEFAULT_MAX_CONTENT_LENGTH
|
||||
with HTTPRequest(environ) as httprequest:
|
||||
request = Request(httprequest)
|
||||
_request_stack.push(request)
|
||||
request._post_init()
|
||||
|
||||
Reference in New Issue
Block a user