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.

Supporting Links