From 0b701fb8470ca82aad3d2c777fef7b85aaffff24 Mon Sep 17 00:00:00 2001 From: Samir Boulahtit Date: Sun, 15 Feb 2026 22:23:15 +0100 Subject: [PATCH] docs: add proposal to fix 1600 SEC-015 x-html security info findings Co-Authored-By: Claude Opus 4.6 --- .../fix-1600-sec015-xhtml-findings.md | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 docs/proposals/fix-1600-sec015-xhtml-findings.md diff --git a/docs/proposals/fix-1600-sec015-xhtml-findings.md b/docs/proposals/fix-1600-sec015-xhtml-findings.md new file mode 100644 index 00000000..8f60c7d0 --- /dev/null +++ b/docs/proposals/fix-1600-sec015-xhtml-findings.md @@ -0,0 +1,120 @@ +# Fix 1600 SEC-015 x-html Security Info Findings + +**Date:** 2026-02-15 +**Status:** Planned +**Validator:** Security (`scripts/validate/validate_security.py`) + +## Current State + +All 3 validators are at **0 errors, 0 warnings**: + +| Validator | Errors | Warnings | Info | +|-----------|--------|----------|------| +| Architecture | 0 | 0 | 0 | +| Security | 0 | 0 | **1600** | +| Performance | 0 | 0 | 1527 | + +All 1600 security info findings are **SEC-015** — Alpine.js `x-html` directives flagged as potential XSS vectors across **162 HTML template files**. + +## Analysis + +### Breakdown by category + +| Category | Count | Pattern | Risk | +|----------|-------|---------|------| +| `$icon()` helper | ~1570 (98%) | `x-html="$icon('name', 'classes')"` | **None** — static SVG icon registry | +| App-controlled content | ~20 | `x-html="$store.upgrade.getUpgradeCardHTML()"` | **None** — internal JS methods | +| Product/CMS content | ~10 | `x-html="product.description"` | **Low** — admin-authored content | + +### Top files by finding count + +| File | Count | +|------|-------| +| `dev_tools/admin/components.html` | 150 | +| `marketplace/store/letzshop.html` | 33 | +| `dev_tools/admin/icons.html` | 27 | +| `tenancy/admin/module-info.html` | 22 | +| `marketplace/admin/partials/letzshop-orders-tab.html` | 22 | +| `orders/store/invoices.html` | 21 | +| `orders/storefront/order-detail.html` | 21 | +| `shared/macros/storefront/search-bar.html` | 20 | +| `shared/macros/storefront/star-rating.html` | 18 | +| Other 153 files | ~1266 | + +### SEC-015 rule definition (in `validate_security.py`) + +```python +# Line 242-256: Check for x-html with dynamic content +for i, line in enumerate(lines, 1): + if re.search(r'x-html="[^"]*\w', line) and "sanitized" not in line.lower(): + if self._is_noqa_suppressed(line, "SEC-015"): + continue + self._add_violation( + rule_id="SEC-015", + rule_name="XSS prevention in templates", + severity=Severity.INFO, + ... + message="x-html renders raw HTML - ensure content is safe", + suggestion="Use x-text for text content or sanitize HTML", + ) +``` + +## Plan + +### Phase 1: Teach validator to recognize safe `$icon()` patterns (~1570 findings) + +**File:** `scripts/validate/validate_security.py` (around line 242) + +Add an exception for `$icon(` calls before the `x-html` check. These render SVG icons from a static Alpine.js magic helper (`window.icons`) and never include user input. + +```python +# Before the x-html check, skip safe icon patterns +if re.search(r'x-html="\$icon\(', line): + continue +``` + +This single change eliminates ~98% of findings. + +### Phase 2: Suppress remaining ~30 with `` + +The remaining x-html usages fall into two categories: + +**A. App-controlled JS methods (~20)** — internal Alpine store methods: +- `$store.upgrade.getUpgradeCardHTML()` +- `$store.upgrade.getLimitWarningHTML()` +- `$store.upgrade.getUsageBarHTML()` +- `getNotificationIcon(notif.type)` +- `window.icons?.['{{ icon }}']` + +These are safe — the HTML is generated by our own JS, not user input. Suppress with ``. + +**B. Product/CMS content (~10)** — admin-authored rich text: +- `product.description` +- `product.short_description` +- `product.warranty` +- Demo product content + +These render content authored by store admins (trusted users). Suppress with `` and add a `` comment. + +### Phase 3: Verify + +```bash +# Should show 0 errors, 0 warnings, 0 info +python scripts/validate/validate_security.py + +# Ensure templates still render correctly +python -c "from main import app; print('OK')" + +# Run full test suite +python -m pytest tests/ app/modules/*/tests/ -q --timeout=60 +``` + +## Execution estimate + +- Phase 1: 1 edit to validator (~5 min) +- Phase 2: ~30 HTML template edits across ~15 files (~30 min) +- Phase 3: Verification (~15 min) + +## Goal + +All 3 validators at **0 errors, 0 warnings, 0 info**.