[IMP] core: set CSP header on some non-HTML resources
Core client remains incompatible with CSP, however it can't hurt to CSP the sub-resources. Current scheme is simplistic, however if useful of necessary it could be made more flexible e.g. there could be a map of mimetypes to CSP configuration, that sort of things.
This commit is contained in:
@@ -426,7 +426,7 @@ class IrHttp(models.AbstractModel):
|
||||
return status, content, filename, mimetype, filehash
|
||||
|
||||
def _binary_set_headers(self, status, content, filename, mimetype, unique, filehash=None, download=False):
|
||||
headers = [('Content-Type', mimetype), ('X-Content-Type-Options', 'nosniff')]
|
||||
headers = [('Content-Type', mimetype), ('X-Content-Type-Options', 'nosniff'), ('Content-Security-Policy', "default-src 'none'")]
|
||||
# cache
|
||||
etag = bool(request) and request.httprequest.headers.get('If-None-Match')
|
||||
status = status or 200
|
||||
|
||||
+28
-28
@@ -3,6 +3,7 @@
|
||||
# OpenERP HTTP layer
|
||||
#----------------------------------------------------------
|
||||
import ast
|
||||
import cgi
|
||||
import collections
|
||||
import contextlib
|
||||
import copy
|
||||
@@ -1393,6 +1394,7 @@ class Root(object):
|
||||
response = Response(result, mimetype='text/html')
|
||||
else:
|
||||
response = result
|
||||
self.set_csp(response)
|
||||
|
||||
save_session = (not request.endpoint) or request.endpoint.routing.get('save_session', True)
|
||||
if not save_session:
|
||||
@@ -1418,6 +1420,23 @@ class Root(object):
|
||||
|
||||
return response
|
||||
|
||||
|
||||
def set_csp(self, response):
|
||||
# ignore HTTP errors
|
||||
if not isinstance(response, werkzeug.wrappers.BaseResponse):
|
||||
return
|
||||
|
||||
headers = response.headers
|
||||
if 'Content-Security-Policy' in headers:
|
||||
return
|
||||
|
||||
mime, _params = cgi.parse_header(headers.get('Content-Type', ''))
|
||||
if not mime.startswith('image/'):
|
||||
return
|
||||
|
||||
headers['Content-Security-Policy'] = "default-src 'none'"
|
||||
|
||||
|
||||
def dispatch(self, environ, start_response):
|
||||
"""
|
||||
Performs the actual WSGI dispatching for the application.
|
||||
@@ -1675,35 +1694,16 @@ def set_safe_image_headers(headers, content):
|
||||
`Content-Type` set appropriately depending on the given `content` only if it
|
||||
is safe to do, as well as `X-Content-Type-Options: nosniff` so that if the
|
||||
file is of an unsafe type, it is not interpreted as that type if the
|
||||
`Content-type` header was already set to a different mimetype"""
|
||||
content_type = guess_mimetype(content)
|
||||
safe_types = ['image/jpeg', 'image/png', 'image/gif', 'image/x-icon']
|
||||
if content_type in safe_types:
|
||||
headers = set_header_field(headers, 'Content-Type', content_type)
|
||||
headers = set_header_field(headers, 'X-Content-Type-Options', 'nosniff')
|
||||
set_header_field(headers, 'Content-Length', len(content))
|
||||
return headers
|
||||
|
||||
|
||||
def set_header_field(headers, name, value):
|
||||
""" Return new headers based on `headers` but with `value` set for the
|
||||
header field `name`.
|
||||
|
||||
:param headers: the existing headers
|
||||
:type headers: list of tuples (name, value)
|
||||
|
||||
:param name: the header field name
|
||||
:type name: string
|
||||
|
||||
:param value: the value to set for the `name` header
|
||||
:type value: string
|
||||
|
||||
:return: the updated headers
|
||||
:rtype: list of tuples (name, value)
|
||||
`Content-type` header was already set to a different mimetype
|
||||
"""
|
||||
dictheaders = dict(headers)
|
||||
dictheaders[name] = value
|
||||
return list(dictheaders.items())
|
||||
headers = werkzeug.datastructures.Headers(headers)
|
||||
safe_types = {'image/jpeg', 'image/png', 'image/gif', 'image/x-icon'}
|
||||
content_type = guess_mimetype(content)
|
||||
if content_type in safe_types:
|
||||
headers['Content-Type'] = content_type
|
||||
headers['X-Content-Type-Options'] = 'nosniff'
|
||||
headers['Content-Length'] = len(content)
|
||||
return list(headers)
|
||||
|
||||
|
||||
# main wsgi handler
|
||||
|
||||
Reference in New Issue
Block a user