From 599f72a3731875f0f1187e8f67facad417225390 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 16:23:29 +0000 Subject: [PATCH] [security] replace innerHTML usages in js/ui/components/DeleteModal.js - Replaced `wrapper.innerHTML` with `DOMParser` for template loading. - Replaced `metadataList.innerHTML = ""` with `replaceChildren()`. - Updated `scripts/check-innerhtml.mjs` baseline (count reduced by 3). - Added artifacts: context, todo, decisions, log. - Verified with lint and unit tests. Co-authored-by: PR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> --- decisions/DECISIONS_2026-02-18_15-05-00.md | 13 +++++++++++++ ...15-15-00_innerhtml-migration-agent_completed.md | 14 ++++++++++++++ js/ui/components/DeleteModal.js | 7 ++++--- scripts/check-innerhtml.mjs | 1 - todo/TODO_2026-02-18_15-05-00.md | 13 +++++++++++++ 5 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 decisions/DECISIONS_2026-02-18_15-05-00.md create mode 100644 docs/agents/task-logs/daily/2026-02-18_15-15-00_innerhtml-migration-agent_completed.md create mode 100644 todo/TODO_2026-02-18_15-05-00.md diff --git a/decisions/DECISIONS_2026-02-18_15-05-00.md b/decisions/DECISIONS_2026-02-18_15-05-00.md new file mode 100644 index 00000000..f259ab24 --- /dev/null +++ b/decisions/DECISIONS_2026-02-18_15-05-00.md @@ -0,0 +1,13 @@ +# Decisions - 2026-02-18 + +File: `js/ui/components/DeleteModal.js` + +1. **Template Loading (Line 108)**: + - **Before**: `wrapper.innerHTML = html` + - **After**: `const doc = new DOMParser().parseFromString(html, 'text/html'); wrapper.append(...doc.body.children);` + - **Rationale**: While the source is a local file (`components/delete-video-modal.html`), using `DOMParser` prevents execution of scripts by default and avoids raw HTML injection vulnerabilities if the template were ever compromised or modified. It aligns with the goal of removing `innerHTML`. + +2. **Clearing List (Line 263 & 368)**: + - **Before**: `this.metadataList.innerHTML = ""` + - **After**: `this.metadataList.replaceChildren()` + - **Rationale**: `replaceChildren()` is the modern, performant way to empty an element. `textContent = ""` is also valid but `replaceChildren()` is explicitly for manipulating child nodes. diff --git a/docs/agents/task-logs/daily/2026-02-18_15-15-00_innerhtml-migration-agent_completed.md b/docs/agents/task-logs/daily/2026-02-18_15-15-00_innerhtml-migration-agent_completed.md new file mode 100644 index 00000000..51de0ed5 --- /dev/null +++ b/docs/agents/task-logs/daily/2026-02-18_15-15-00_innerhtml-migration-agent_completed.md @@ -0,0 +1,14 @@ +# Task Completion Log: innerhtml-migration-agent + +- **Date**: 2026-02-18 +- **Agent**: innerhtml-migration-agent (via daily scheduler) +- **Status**: Completed +- **Changes**: + - Migrated `js/ui/components/DeleteModal.js` to safe DOM APIs. + - Reduced `innerHTML` count by 3 (from 3 to 0). + - Updated `scripts/check-innerhtml.mjs` baseline. +- **Artifacts**: + - `context/CONTEXT_2026-02-18_15-00-00.md` + - `todo/TODO_2026-02-18_15-05-00.md` + - `decisions/DECISIONS_2026-02-18_15-05-00.md` + - `perf/innerhtml/raw-report-2026-02-18.log` diff --git a/js/ui/components/DeleteModal.js b/js/ui/components/DeleteModal.js index d3ef17ac..80ade25f 100644 --- a/js/ui/components/DeleteModal.js +++ b/js/ui/components/DeleteModal.js @@ -108,7 +108,8 @@ export class DeleteModal { const html = await response.text(); const wrapper = document.createElement("div"); - wrapper.innerHTML = html; + const doc = new DOMParser().parseFromString(html, "text/html"); + wrapper.append(...doc.body.children); this.removeTrackingScripts(wrapper); targetContainer.appendChild(wrapper); modal = wrapper.querySelector("#deleteVideoModal"); @@ -263,7 +264,7 @@ export class DeleteModal { } const doc = this.metadataList.ownerDocument; - this.metadataList.innerHTML = ""; + this.metadataList.replaceChildren(); if (!doc) { return; } @@ -421,7 +422,7 @@ export class DeleteModal { } if (this.metadataList) { - this.metadataList.innerHTML = ""; + this.metadataList.replaceChildren(); } } diff --git a/scripts/check-innerhtml.mjs b/scripts/check-innerhtml.mjs index 95a192f2..1a27dbe9 100644 --- a/scripts/check-innerhtml.mjs +++ b/scripts/check-innerhtml.mjs @@ -29,7 +29,6 @@ const BASELINE = { "js/forYouView.js": 1, "js/index.js": 1, "js/kidsView.js": 1, - "js/ui/components/DeleteModal.js": 3, "js/ui/components/EditModal.js": 1, "js/ui/components/EmbedVideoModal.js": 1, "js/ui/components/EventDetailsModal.js": 1, diff --git a/todo/TODO_2026-02-18_15-05-00.md b/todo/TODO_2026-02-18_15-05-00.md new file mode 100644 index 00000000..cf95d283 --- /dev/null +++ b/todo/TODO_2026-02-18_15-05-00.md @@ -0,0 +1,13 @@ +# TODO - 2026-02-18 + +File: `js/ui/components/DeleteModal.js` + +1. **Line 108**: `wrapper.innerHTML = html;` + - Context: Loading `components/delete-video-modal.html` template. + - Strategy: Use `DOMParser` to parse the HTML string and append children to wrapper. +2. **Line 263**: `this.metadataList.innerHTML = "";` + - Context: Clearing the metadata list before re-rendering. + - Strategy: Replace with `this.metadataList.replaceChildren()` or `this.metadataList.textContent = ""`. +3. **Line 368**: `this.metadataList.innerHTML = "";` + - Context: Resetting the modal state. + - Strategy: Replace with `this.metadataList.replaceChildren()`.