Skip to content

Issue 1: Inline Script Injection via Unescaped User Data (XSS) #218

@garland3

Description

@garland3

Issue 1: Inline Script Injection via Unescaped User Data (XSS)

Severity: High

Summary

Toyplot currently embeds dynamic JSON-serialized data directly inside inline <script> blocks in toyplot/html.py without neutralizing the </script> sequence. A malicious data value containing </script><script>... will prematurely terminate the script element and inject arbitrary JavaScript.

Affected Component

File: toyplot/html.py, function _render_javascript() (script assembly section)

Exploit Scenario

If a user creates a table / mark containing a string:

"</script><script>alert('XSS')</script>

When rendered, the browser parses a second <script> element and executes attacker code. This affects notebook environments, documentation builds, or any web embedding that displays Toyplot output with untrusted content.

Impact

Arbitrary JavaScript execution in the origin (credential theft, session hijack, data exfiltration, lateral movement in shared Jupyter multi-user setups).

Root Cause

Inline script text is constructed via Python string concatenation with raw json.dumps() output. Browsers parse </script> as end-of-element even when inside a string literal in JS source.

Recommendation (Short-Term Patch)

Escape the closing script tag sequence in any serialized string before embedding:

safe = json_text.replace('</script>', '<\\/script>')

Apply after json.dumps and before concatenation.

Recommendation (Long-Term Hardening)

Refactor the architecture to separate data from code:

  1. Emit a <script type="application/json" id="toyplot-data-<uuid>"> element containing only JSON.
  2. Use a single static loader script that parses the JSON via textContent and initializes modules.
  3. Add (or document) a CSP-friendly path (no inline executable script).

Proposed Code Pointer

In _render_javascript(context) adjust where argument_list and module value assignments are appended.

Verification Steps

  1. Create a canvas with a text mark containing </script><script>alert(1)</script>.
  2. Render before patch: alert dialog appears.
  3. Render after patch: no alert; page source contains <\/script>.

References

  • OWASP: Cross Site Scripting (XSS) Prevention Cheat Sheet
  • HTML5 parsing rules for script end tags

Tracking

Label suggestion: security, high-priority, XSS.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions