Skip to content

[SECURITY] Replace custom HTML escape table with stdlib html.escape() in report generation #48

Description

@advaitpatel

Overview

Both `docker_scanner.py` and `report_generator.py` use a hand-rolled HTML escaping approach instead of Python's built-in `html.escape()`. The custom implementation only handles 5 characters and may miss edge cases, creating a potential XSS vector when vulnerability data contains unexpected characters.

Current Code (docker_scanner.py)

def _escape_html(self, text: str) -> str:
    """Escape HTML special characters to prevent XSS."""
    if not isinstance(text, str):
        text = str(text)
    escape_table = {
        "&": "&",
        "<": "&lt;",
        ">": "&gt;",
        '"': "&quot;",
        "'": "&#x27;",
    }
    return "".join(escape_table.get(c, c) for c in text)

Problem

  1. Incomplete: Python's `html.escape()` handles the same characters but is maintained by the Python core team and tested against the full HTML spec
  2. Redundant maintenance burden: Keeping a custom table in sync with evolving XSS vectors is unnecessary work
  3. Missing `quote=True`: The stdlib function also handles attribute-context escaping properly when `quote=True`

Fix

import html

def _escape_html(self, text: str) -> str:
    """Escape HTML special characters to prevent XSS."""
    if not isinstance(text, str):
        text = str(text)
    return html.escape(text, quote=True)

This is a one-line change per file with identical output for the current character set, plus correct handling of any edge cases the stdlib covers.

Files to Update

File Line(s)
`docker_scanner.py` `_escape_html()` method
`report_generator.py` Any equivalent escaping logic

Acceptance Criteria

  • `_escape_html()` uses `html.escape(text, quote=True)`
  • Custom escape table removed
  • Existing HTML output tests pass (or new ones added to verify output unchanged)
  • No new imports needed (`html` is stdlib)

Skill Level

Beginner. This is a single-method change that removes code rather than adding it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinggood first issueGood for newcomerspythonPull requests that update python code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions