T09 · Insecure Skill Coding Practices
Warning
- Location
- workflows/01-daily-summary.json:56
- Finding
- HTML Email Injection Through Daily Summary Spreadsheet Data<![CDATA[ ## Vulnerability Details **File Location**: `workflows/01-daily-summary.json:56-72` **Vulnerability Type**: Unescaped HTML content injection **Risk Level**: Medium ### Vulnerable Code ```javascript // Build summary HTML table let summaryHtml = '<table border="1" cellpadding="8" cellspacing="0"><tr><th>Column</th><th>Count</th><th>Sum</th><th>Average</th><th>Min</th><th>Max</th></tr>'; for (const [col, s] of Object.entries(stats)) { summaryHtml += `<tr><td><strong>${col}</strong></td><td>${s.count}</td><td>${s.sum}</td><td>${s.avg}</td><td>${s.min}</td><td>${s.max}</td></tr>`; } summaryHtml += '</table>'; // Count unique values for first text column let categorySummary = ''; if (textCols.length > 0) { const firstTextCol = textCols[0]; const valueCounts = {}; for (const r of rows) { const v = (r[firstTextCol] || 'empty').toString(); valueCounts[v] = (valueCounts[v] || 0) + 1; } categorySummary = Object.entries(valueCounts) .sort((a, b) => b[1] - a[1]) .slice(0, 10) .map(([v, c]) => `${v}: ${c}`) .join(', '); } ``` The generated values are subsequently inserted into the HTML email: ```json "message": "=<h2>Daily Data Summary</h2><p><strong>Date:</strong> {{ $json.report_date }}</p><p><strong>Total Rows:</strong> {{ $json.total_rows }}</p><p><strong>Numeric Columns:</strong> {{ $json.numeric_columns }}</p><h3>Column Statistics</h3>{{ $json.summary_html }}<h3>Top Categories ({{ $json.category_column }})</h3><p>{{ $json.category_summary }}</p>" ``` ### Technical Analysis The workflow constructs an HTML email by directly interpolating Google Sheets column names and cell values. The variables `col`, `v`, `category_column`, and `category_summary` can contain spreadsheet-controlled content, but no HTML encoding or sanitization is applied before the resulting strings are passed to the email node. An attacker with write access to the monitored sheet can place HTML markup in a column header or category value. That marku ...[truncated 1239 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Apply contextual HTML encoding to every spreadsheet-derived value before interpolation, including column names, category names, and category values. 2. Encode at least `&`, `<`, `>`, `"`, and `'`. 3. Prefer an email template system that escapes values by default rather than manually constructing HTML strings. 4. If rich formatting is unnecessary, send the report as plain text. 5. Do not sanitize the finished HTML with simple regular expressions; encode individual untrusted values at their insertion points. 6. Add tests using spreadsheet values containing HTML tags, links, quotes, ampersands, and image elements. 7. Consider disabling remote content in organizational email clients as defense in depth. ]]>
