]> git.ipfire.org Git - thirdparty/starlette.git/commitdiff
More debugger improvements (#825)
authorretnikt <_@retnikt.uk>
Tue, 11 Feb 2020 09:36:29 +0000 (09:36 +0000)
committerGitHub <noreply@github.com>
Tue, 11 Feb 2020 09:36:29 +0000 (09:36 +0000)
* HTML-escape everything in the debugger

There isn't much of an attack surface here given the debugger should never be
exposed in production and most of these things are not user-controllable (in
fact you'd have to try hard to get `<script>` in a Python identifier), but
escaping them is still important in case they mess up debugger output (see #599,
#601), and it's also just good practice.

* monospace debugger content and clean up styles

starlette/middleware/errors.py

index 29c56e56306e6241c7c86ba419f67e1ec17fd204..f1f8bd3d8c25bc6286ea48fbd4bbeec2bfb5f997 100644 (file)
@@ -25,6 +25,10 @@ p {
 }
 .frame-line {
     padding-left: 10px;
+    font-family: monospace;
+}
+.frame-filename {
+    font-family: monospace;
 }
 .center-line {
     background-color: #038BB8;
@@ -34,12 +38,11 @@ p {
 .lineno {
     margin-right: 5px;
 }
-.frame-filename {
+.frame-title {
     font-weight: unset;
-    padding: 10px 10px 10px 0px;
+    padding: 10px 10px 10px 10px;
     background-color: #E4F4FD;
     margin-right: 10px;
-    font: #394D54;
     color: #191f21;
     font-size: 17px;
     border: 1px solid #c7dce8;
@@ -99,7 +102,7 @@ TEMPLATE = """
 
 FRAME_TEMPLATE = """
 <div>
-    <p class="frame-filename"><span class="debug-filename frame-line">File {frame_filename}</span>,
+    <p class="frame-title">File <span class="frame-filename">{frame_filename}</span>,
     line <i>{frame_lineno}</i>,
     in <b>{frame_name}</b>
     <span class="collapse-btn" data-frame-id="{frame_filename}-{frame_lineno}" onclick="collapse(this)">{collapse_button}</span>
@@ -181,7 +184,8 @@ class ServerErrorMiddleware:
         self, index: int, line: str, frame_lineno: int, frame_index: int
     ) -> str:
         values = {
-            "line": line.replace(" ", "&nbsp"),
+            # HTML escape - line could contain < or >
+            "line": html.escape(line).replace(" ", "&nbsp"),
             "lineno": (frame_lineno - frame_index) + index,
         }
 
@@ -196,9 +200,11 @@ class ServerErrorMiddleware:
         )
 
         values = {
-            "frame_filename": frame.filename,
+            # HTML escape - filename could contain < or >, especially if it's a virtual file e.g. <stdin> in the REPL
+            "frame_filename": html.escape(frame.filename),
             "frame_lineno": frame.lineno,
-            "frame_name": frame.function,
+            # HTML escape - if you try very hard it's possible to name a function with < or >
+            "frame_name": html.escape(frame.function),
             "code_context": code_context,
             "collapsed": "collapsed" if is_collapsed else "",
             "collapse_button": "+" if is_collapsed else "&#8210;",
@@ -219,7 +225,8 @@ class ServerErrorMiddleware:
             exc_html += self.generate_frame_html(frame, is_collapsed)
             is_collapsed = True
 
-        error = f"{traceback_obj.exc_type.__name__}: {html.escape(str(traceback_obj))}"
+        # escape error class and text
+        error = f"{html.escape(traceback_obj.exc_type.__name__)}: {html.escape(str(traceback_obj))}"
 
         return TEMPLATE.format(styles=STYLES, js=JS, error=error, exc_html=exc_html)