Local File Reading via ECharts Formatter: A Penetration Test Case
Sanitize ECharts formatter input, restrict file:// access in Puppeteer, and remove public XHProf to prevent local file read via file:// SSRF.
Sanitize ECharts formatter input, restrict file:// access in Puppeteer, and remove public XHProf.
Summary
A penetration tester discovered a local file reading vulnerability in a custom web application that used a Node.js service to generate charts via ECharts and Puppeteer. The service accepted arbitrary JavaScript functions in the ECharts label.formatter field, which Puppeteer executed without restricting the file:// protocol. An attacker could embed a function that performs an XMLHttpRequest to file:///etc/passwd, read the response, and return it as part of the chart label. The PNG output of the chart was then served over HTTP, exposing the file contents to anyone who could download the image. The vulnerability also allowed path traversal and combined with an exposed XHProf interface that leaked internal class names and directory paths. The proof‑of‑concept involved sending a POST request to /api/generate-chart with a crafted formatter that reads /etc/passwd and returns the first 500 characters. The response included the image path, which could be fetched to retrieve the file contents. This chain demonstrates how a seemingly innocuous chart‑generation API can become a local file read vector when sandboxing is insufficient.
The case study highlights the importance of sanitizing ECharts input, restricting file:// access in Puppeteer, and removing public profiling tools like XHProf from production. By limiting the execution context and validating the formatter code, the risk of local file read can be mitigated.
The vulnerability was discovered during a routine penetration test of a single Linux host with multiple services exposed on ports 80, 443, 3001, and 8999. The Node service on port 3001 was the primary vector, while the exposed XHProf on port 8999 provided additional internal information that facilitated the attack.
Key changes
- Node service accepts arbitrary JS in ECharts label.formatter
- Puppeteer executes without file:// restriction, enabling local file read
- JavaScript can read /etc/passwd via XMLHttpRequest
- PNG output exposes file contents over HTTP
- Exploit leads to local file read and path traversal
- XHProf exposed provides internal class names and paths
- Attack chain from chart‑generation API to local file read
- Requires sanitizing input and restricting file protocol