From a745873f542c7f5903123c87933ad439c2faa667 Mon Sep 17 00:00:00 2001 From: Karl Czajkowski Date: Tue, 19 Sep 2023 10:54:31 -0700 Subject: [PATCH] add html.escape() to content-negotiated HTML responses since error responses and namespace listings can be formulated into HTML, we should be applying HTML escaping to the raw hatrac object URL paths which we embed in the responses. --- hatrac/model/directory/pgsql.py | 8 ++++++-- hatrac/rest/core.py | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/hatrac/model/directory/pgsql.py b/hatrac/model/directory/pgsql.py index 7210e23..3f417cb 100644 --- a/hatrac/model/directory/pgsql.py +++ b/hatrac/model/directory/pgsql.py @@ -42,6 +42,7 @@ import sys import json import urllib +import html import binascii import base64 import random @@ -134,8 +135,11 @@ def negotiated_uri_list(parent, resources, metadata={}): body = '\n'.join(uris) + '\n' elif metadata['content-type'] == 'text/html': body = "\n\n

Index of {parent}

\n{children}\n".format( - parent=parent.asurl(), - children='
\n'.join([' %s' % (uri, os.path.basename(uri)) for uri in uris]) + parent=html.escape(parent.asurl()), + children='
\n'.join([ + ' %s' % (html.escape(uri), html.escape(os.path.basename(uri))) + for uri in uris + ]) ) else: body = jsonWriter(uris) + b'\n' diff --git a/hatrac/rest/core.py b/hatrac/rest/core.py index baa8c7a..5173350 100644 --- a/hatrac/rest/core.py +++ b/hatrac/rest/core.py @@ -19,6 +19,7 @@ from datetime import timezone import struct import urllib +import html import sys import traceback import hashlib @@ -146,12 +147,15 @@ def get_description(self, environ=None, scope=None): def get_body(self, environ=None, scope=None): template = self.response_templates[self.content_type] description = self.get_description() - return (template + '\n') % { - "code": self.code, + parts = { + "code": str(self.code), "description": description, "message": description, # for existing hatrac_config template feature "title": self.title, # for our new generic templates } + if self.content_type == 'text/html': + parts = { k: html.escape(v) for k, v in parts.items() } + return (template + '\n') % parts def get_headers(self, environ=None, scope=None): return self.headers