diff --git a/swh/web/api/apiresponse.py b/swh/web/api/apiresponse.py --- a/swh/web/api/apiresponse.py +++ b/swh/web/api/apiresponse.py @@ -6,6 +6,8 @@ import json import traceback +from django.utils.html import escape + from rest_framework.response import Response from swh.storage.exc import StorageDBError, StorageAPIError @@ -177,6 +179,10 @@ 'exception': error.__class__.__name__, 'reason': str(error), } + + if request.accepted_media_type == 'text/html': + error_data['reason'] = escape(error_data['reason']) + if get_config()['debug']: error_data['traceback'] = traceback.format_exc() diff --git a/swh/web/assets/src/bundles/browse/origin-search.js b/swh/web/assets/src/bundles/browse/origin-search.js --- a/swh/web/assets/src/bundles/browse/origin-search.js +++ b/swh/web/assets/src/bundles/browse/origin-search.js @@ -37,7 +37,7 @@ let browseUrl = Urls.browse_origin(elem.url); let tableRow = ``; tableRow += `${elem.type}`; - tableRow += `${elem.url}`; + tableRow += `${encodeURI(elem.url)}`; tableRow += ``; tableRow += ''; table.append(tableRow); diff --git a/swh/web/browse/utils.py b/swh/web/browse/utils.py --- a/swh/web/browse/utils.py +++ b/swh/web/browse/utils.py @@ -12,6 +12,7 @@ from django.core.cache import cache from django.utils.safestring import mark_safe +from django.utils.html import escape from importlib import reload @@ -489,7 +490,8 @@ attrs += '%s="%s" ' % (k, v) if not link_text: link_text = url - link = '%s' % (attrs, url, link_text) + link = '%s' \ + % (attrs, escape(url), escape(link_text)) return mark_safe(link) @@ -861,7 +863,7 @@ return origin_info except Exception: pass - raise NotFoundExc('Origin with url %s not found!' % origin_url) + raise NotFoundExc('Origin with url %s not found!' % escape(origin_url)) def get_snapshot_context(snapshot_id=None, origin_type=None, origin_url=None, @@ -923,7 +925,7 @@ if not snapshot_id: raise NotFoundExc('No snapshot associated to the visit of origin ' - '%s on %s' % (origin_url, fmt_date)) + '%s on %s' % (escape(origin_url), fmt_date)) # provided timestamp is not necessarily equals to the one # of the retrieved visit, so get the exact one in order diff --git a/swh/web/browse/views/utils/snapshot_context.py b/swh/web/browse/views/utils/snapshot_context.py --- a/swh/web/browse/views/utils/snapshot_context.py +++ b/swh/web/browse/views/utils/snapshot_context.py @@ -10,6 +10,7 @@ from django.shortcuts import render from django.template.defaultfilters import filesizeformat +from django.utils.html import escape from swh.model.identifiers import snapshot_identifier @@ -117,7 +118,7 @@ ' and url %s not found!' % (branch_type, branch, timestamp, origin_info['type'], origin_info['url']) - raise NotFoundExc(msg) + raise NotFoundExc(escape(msg)) def _process_snapshot_request(request, snapshot_id=None, origin_type=None, diff --git a/swh/web/common/exc.py b/swh/web/common/exc.py --- a/swh/web/common/exc.py +++ b/swh/web/common/exc.py @@ -8,6 +8,7 @@ from django.http import HttpResponse from django.shortcuts import render from django.utils.safestring import mark_safe +from django.utils.html import escape from swh.web.config import get_config @@ -68,7 +69,7 @@ """ error_description = 'The server cannot process the request to %s due to '\ 'something that is perceived to be a client error.' %\ - request.META['PATH_INFO'] + escape(request.META['PATH_INFO']) return _generate_error_page(request, 400, error_description) @@ -77,7 +78,7 @@ Custom Django HTTP error 403 handler for swh-web. """ error_description = 'The resource %s requires an authentication.' %\ - request.META['PATH_INFO'] + escape(request.META['PATH_INFO']) return _generate_error_page(request, 403, error_description) @@ -86,7 +87,7 @@ Custom Django HTTP error 404 handler for swh-web. """ error_description = 'The resource %s could not be found on the server.' %\ - request.META['PATH_INFO'] + escape(request.META['PATH_INFO']) return _generate_error_page(request, 404, error_description) @@ -96,7 +97,7 @@ """ error_description = 'An unexpected condition was encountered when '\ 'requesting resource %s.' %\ - request.META['PATH_INFO'] + escape(request.META['PATH_INFO']) return _generate_error_page(request, 500, error_description) diff --git a/swh/web/common/origin_save.py b/swh/web/common/origin_save.py --- a/swh/web/common/origin_save.py +++ b/swh/web/common/origin_save.py @@ -9,6 +9,7 @@ from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ValidationError from django.core.validators import URLValidator +from django.utils.html import escape from swh.web import config from swh.web.common import service @@ -127,7 +128,7 @@ _validate_url(origin_url) except ValidationError: raise BadInputExc('The provided origin url (%s) is not valid!' % - origin_url) + escape(origin_url)) def _get_visit_info_for_save_request(save_request): diff --git a/swh/web/templates/includes/top-navigation.html b/swh/web/templates/includes/top-navigation.html --- a/swh/web/templates/includes/top-navigation.html +++ b/swh/web/templates/includes/top-navigation.html @@ -120,7 +120,7 @@ var branch = false; {% if snapshot_context %} snapshotContext = true; - branch = {{ snapshot_context.branch|jsonify }}; + branch = "{{ snapshot_context.branch|escape }}"; {% endif %} - swh.browse.initSnapshotNavigation(snapshotContext, branch); + swh.browse.initSnapshotNavigation(snapshotContext, branch !== "None");