Skip to content

Sampling profiler flamegraph HTML does not escape </script> in embedded profile data #159640

Description

@catmilk7

Bug report

profiling.sampling's flamegraph export (--flamegraph, also used by replay --flamegraph) embeds the profile data in an inline <script> block:

# Lib/profiling/sampling/stack_collector.py, _create_flamegraph_html()
data_json = json.dumps(data)
...
# flamegraph.js: const EMBEDDED_DATA = {{FLAMEGRAPH_DATA}};

json.dumps() does not escape <, > or /, so any string in the data that contains </script> closes the script element early. The strings come from the profiled program: function qualnames, filenames, and source lines read with linecache. When you replay a binary profile (.bin), all of them come from the file itself.

The result is a broken report, and the text after </script> gets parsed as HTML. For example, a function whose qualname is

</script><script>alert(1)</script><script>//

produces a flamegraph where alert(1) runs as a separate script. U+2028/U+2029 in the data can also cause trouble, because older JavaScript engines treat them as line terminators.

This is new in 3.15. 3.14 has no flamegraph exporter.

Proposed fix: after json.dumps(), replace <, >, &, U+2028 and U+2029 with their \uXXXX escapes. These characters can only appear inside JSON string values, so the change is lossless (JSON.parse/the JS literal still gives the original text).

CPython versions tested on:

3.15

Operating systems tested on:

Linux

Linked PRs

Activity

  1. eendebakpt commented on Oct 18, 2026

    @eendebakpt
    Contributor

    Duplicate of #153840 (or at least overlapping).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytopic-profilingtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions