T09 · Insecure Skill Coding Practices
- Location
scripts/bubble_chart_example.js:104- Finding
DOM-based cross-site scripting in bubble chart tooltips
- Content
View full analysis
{ // Parse numbers data.forEach(d => { d.value = d.marketCap ? +d.marketCap : null; d.ticker = d.ticker; d.sector = d.sector; }); createBubbleChart(data); }); ``` ```javascript function showTooltip(event, d) { const tooltip = d3.select('#tooltip'); tooltip .classed('visible', true) .html(` ${d.ticker}
${d.name || 'N/A'}
Sector: ${d.sector} `) .style('left', (event.pageX + 10) + 'px') .style('top', (event.pageY - 10) + 'px'); } ``` ### Technical Analysis The chart loads records from `/data/stocks.csv` and places the `ticker`, `name`, and `sector` fields into an HTML template without escaping or sanitization. D3's `.html()` method ultimately assigns the supplied value as HTML rather than plain text. Consequently, a data field containing active HTML, such as an image with an error event handler, will be parsed by the browser. This crosses the security boundary between visualization data and executable document content. The conditional tooltip check only excludes records whose sector is exactly `ETF`; it does not validate or sanitize any displayed field and therefore does not mitigate this issue. ### Attack Path 1. An attacker obtains the ability to add or modify a record in `/data/stocks.csv`, or supplies a data file that is later used by the example. 2. The attacker places an HTML payload in a displayed field, for example: ```html``` 3. The page loads the malicious record through `d3.csv()`. 4. The record is bound to a bubble without sanitization. 5. A us ...[truncated 965 chars]
- Remediation
View remediation
