Plot.ly MathJax LaTeX Stored XSS
Summary
Plot.ly allowed user-controlled LaTeX content to be rendered through MathJax with JavaScript-capable hyperlink behavior enabled. A malicious plot author could create stored interactive content that executed JavaScript when another user interacted with a plot title or annotation.
Affected Surface
- Product: Plot.ly
- Component: Plot rendering with LaTeX/MathJax support
- Input locations: plot titles and plot annotations/points
- Vulnerability class: stored cross-site scripting
Impact
An attacker could publish or share a plot containing a malicious LaTeX hyperlink. When another authenticated user interacted with that rendered plot content, attacker-controlled JavaScript could execute in the victim’s Plot.ly browser context.
Potential outcomes included session exposure, actions as the victim, phishing inside a trusted Plot.ly page, and broader abuse of Plot.ly’s social sharing model.
Root Cause
Plot.ly relied on MathJax to render LaTeX inside SVG plot content, but MathJax’s JavaScript-capable link behavior was available by default. Plot.ly’s existing sanitization focused on HTML-like tag characters and did not account for this library-specific LaTeX rendering path.
Evidence
A proof of concept used a LaTeX \href{javascript:...}{...} payload in plot-controlled text. The payload rendered as an interactive plot element and executed JavaScript on user interaction.
Remediation
- Disable JavaScript-capable MathJax behavior for user-controlled content.
- Enable MathJax Safe Mode or equivalent restrictions.
- Treat third-party renderer features as part of the trusted boundary.
- Add regression tests for renderer-specific markup paths, not only raw HTML paths.
Timeline
- 2016-08-08: Reported to Plot.ly
- 2016-08-12: Fixed
- 2016-08-16: Publicly disclosed
Notes
This issue demonstrated the operational lesson behind the original article: imported dependencies expand the application’s attack surface. Renderer defaults, parser features, and library-specific markup paths need the same threat modeling as first-party code.