feat(security): migrate dashboard innerHTML to safe DOM APIs

- Replace innerHTML with document.createElement and replaceChildren in dashboard/index.html
- Add dashboard/domUtils.js for safe HTML escaping and element creation
- Add context, decisions, and test logs
- Update daily task logs

Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
google-labs-jules[bot]andPR0M3TH3AN committed 2026-02-14 23:05:24 +00:00
1 parent 45194e7282
commit b92f0efd38
13 files changed
+261 -76

No files matched your search

@@ -0,0 +1,12 @@
# Context: innerHTML Migration for dashboard/index.html
- **Date:** 2026-02-14
- **Agent:** innerhtml-migration-agent
- **Target File:** `dashboard/index.html`
- **Reason:** High-count file (4 assignments) identified by `check-innerhtml.mjs`.
- **Node Version:** v22.22.0
- **Plan:**
1. Migrate `summaryBar` and `lockGrid` rendering to use `document.createElement`.
2. Use `replaceChildren()` for clearing containers.
3. Create `dashboard/domUtils.js` for `escapeHtml` helper.
4. Verify with linting and manual code review (smoke test logic).
@@ -0,0 +1,22 @@
# Decisions: dashboard/index.html innerHTML Migration
## Strategy
We are migrating `innerHTML` to safe DOM APIs (`textContent`, `createElement`, `appendChild`, `replaceChildren`).
## Decisions
1. **Helper Function**: Created `dashboard/domUtils.js` to host `escapeHtml`. Although we are moving to `createElement` which inherently escapes text in `textContent`, `escapeHtml` is useful if we ever need to set attributes that might be sensitive (though less critical there) or if we fallback to `innerHTML` (which we are trying to avoid).
* *Update*: Actually, for `lockGrid`, reconstructing the entire card with `createElement` is verbose but safer. We will do that. `escapeHtml` might not be needed if we strictly use `textContent`, but it's good to have available.
2. **`summaryBar`**:
* **Before**: Template literal with `innerHTML`.
* **After**: `document.createElement('div')`, loop through cards, create elements, set classes and `textContent`.
3. **`lockGrid`**:
* **Before**: Complex template literal with `innerHTML`.
* **After**: `createLockCard(lock)` function that builds the DOM tree for a card. This ensures no unescaped user data (agent name, cadence, etc.) can be injected.
* **Risk**: CSS classes must be copied exactly.
4. **Clearing Content**:
* **Before**: `el.innerHTML = ''`.
* **After**: `el.replaceChildren()`. This is faster and safer.
@@ -0,0 +1,27 @@
# Test Log: dashboard/index.html innerHTML Migration
- **Date:** 2026-02-14
- **Agent:** innerhtml-migration-agent
- **Test Command:** `node scripts/check-innerhtml.mjs --report`
## Results
### Before
`dashboard/index.html`: 4 assignments
### After
`dashboard/index.html`: 0 assignments (not listed in report)
### Linting
`npm run lint` passed (warnings unrelated to changes).
### Verification
- `dashboard/domUtils.js` created and verified.
- `dashboard/index.html` modified to use `createElement` and `replaceChildren`.
- `innerHTML` usage removed from `dashboard/index.html`.
- **Note**: The `check-innerhtml.mjs` script does not support `--update` or `BASELINE` tracking, so the baseline update step was skipped.
## Manual Verification Simulation
- Verified that `createElement` correctly mimics the structure of the original `innerHTML` templates.
- Ensured `escapeHtml` is available (though `createElement` + `textContent` handles escaping naturally for text nodes).
- Checked for potential regressions: None found in static analysis.
+10
View File
@@ -0,0 +1,10 @@
# TODO: dashboard/index.html innerHTML Migration
- [ ] `summaryBar.innerHTML = cards.map(...).join('')` (Line ~436)
- Strategy: Replace with `document.createElement` loop and `replaceChildren`.
- [ ] `lockGrid.innerHTML = ''` (Line ~448)
- Strategy: `lockGrid.replaceChildren()` + `appendChild(emptyState)`.
- [ ] `lockGrid.innerHTML = locks.map(...).join('')` (Line ~455)
- Strategy: Create `createLockCard` function using `document.createElement`, then `lockGrid.replaceChildren(...cards)`.
- [ ] `rawLog.innerHTML = ''` (Line ~534)
- Strategy: `rawLog.replaceChildren()`.