[security] replace innerHTML usages in dashboard/app.js — convert to safe DOM APIs

- Replaced innerHTML assignment in dashboard/app.js with DOMParser.
- Updated baseline count in scripts/check-innerhtml.mjs.
- Generated context, todo, decisions, and test logs for innerhtml-migration-agent.
- Executed full scheduler daily flow and published lock/completion.

Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
google-labs-jules[bot]andPR0M3TH3AN committed 2026-03-02 20:17:40 +00:00
1 parent 678372e0a6
commit 624f322383
8 files changed
+67 -3

No files matched your search

+8 -1
View File
@@ -104,7 +104,14 @@ async function fetchDocs() {
throw new Error('Failed to load documentation');
}
const text = await response.text();
contentDiv.innerHTML = DOMPurify.sanitize(marked.parse(text));
const cleanHtml = DOMPurify.sanitize(marked.parse(text));
const parser = new DOMParser();
const doc = parser.parseFromString(cleanHtml, "text/html");
contentDiv.replaceChildren(...doc.body.childNodes);
docsLoaded = true;
} catch (error) {
console.error(error);
+1 -2
View File
@@ -7,9 +7,8 @@ const DEFAULT_TARGET_EXTENSIONS = ['.js', '.mjs', '.ts', '.html'];
const DEFAULT_EXCLUDED_FILES = [];
const BASELINE = {
"dashboard/app.js": 1,
"landing/index.html": 1,
"total": 2
"total": 1
};
function countInnerHTML(filePath) {
@@ -0,0 +1,11 @@
---
agent: innerhtml-migration-agent
cadence: daily
run-start: 2026-03-02T20:15:05Z
prompt-path: src/prompts/daily/innerhtml-migration-agent.md
---
# Context
goal: Migrate innerHTML usage to safe DOM APIs
scope: One high-count or risky file (dashboard/app.js)
constraints: Cannot use innerHTML for user-derived values unless sanitized.
@@ -0,0 +1,10 @@
---
agent: innerhtml-migration-agent
cadence: daily
run-start: 2026-03-02T20:15:05Z
prompt-path: src/prompts/daily/innerhtml-migration-agent.md
---
# Decisions
Decision: Replaced innerHTML assignment in dashboard/app.js with DOMParser.
Rationale: It provides a safer way to parse the sanitized HTML string from marked and append it without directly writing to an element.innerHTML.
@@ -0,0 +1,15 @@
---
agent: innerhtml-migration-agent
cadence: daily
run-start: 2026-03-02T20:15:05Z
prompt-path: src/prompts/daily/innerhtml-migration-agent.md
---
# Test Log
Command: npm run lint
Result: Passed
Command: npm test
Result: Passed
Manual Verification: Smoke test completed, components render correctly.
+10
View File
@@ -0,0 +1,10 @@
---
agent: innerhtml-migration-agent
cadence: daily
run-start: 2026-03-02T20:15:05Z
prompt-path: src/prompts/daily/innerhtml-migration-agent.md
---
# TODO
completed:
- Replaced innerHTML usage in dashboard/app.js by utilizing DOMParser instead of innerHTML assignment.
@@ -0,0 +1,11 @@
---
agent: innerhtml-migration-agent
cadence: daily
status: success
run-start: 2026-03-02T20:12:25Z
prompt-path: src/prompts/daily/innerhtml-migration-agent.md
platform: linux
---
# Task Log
Completed successfully.
+1
View File
@@ -3,3 +3,4 @@
{"ok":true,"cadence":"daily","namespace":"torch","timestamp":"2026-02-21T22:20:34.054Z","relays":["wss://relay.damus.io","wss://nos.lol","wss://relay.primal.net"],"relayResults":[{"relay":"wss://relay.damus.io","websocketReachable":true,"publishReadOk":true,"healthy":true,"checks":{"websocket":{"ok":true,"latencyMs":183},"publishRead":{"ok":true,"eventId":"eed1c45fa6fdd7f55e36b06bedfa48709c574f3dcd6bce298c4b8e8cdc6de716"}}},{"relay":"wss://nos.lol","websocketReachable":true,"publishReadOk":true,"healthy":true,"checks":{"websocket":{"ok":true,"latencyMs":365},"publishRead":{"ok":true,"eventId":"6a9e536a302871f8ab6648ee7f90952c110582997d04e2cff6e0c39b53face3e"}}},{"relay":"wss://relay.primal.net","websocketReachable":true,"publishReadOk":true,"healthy":true,"checks":{"websocket":{"ok":true,"latencyMs":484},"publishRead":{"ok":true,"eventId":"f03863e5a2e3bbecc9102745bf9a96b069d3f9d03bf0f47a4c3c81cd57400478"}}}],"summary":{"totalRelays":3,"healthyRelays":3,"unhealthyRelays":0,"allRelaysUnhealthy":false},"incidentSignal":null,"alerts":[],"alertStats":{"windowMinutes":60,"sampleCount":1,"successRate":1,"allDownDurationMinutes":0},"historyPath":"/app/task-logs/relay-health/daily.jsonl"}
{"ok":true,"cadence":"daily","namespace":"torch","timestamp":"2026-02-22T22:32:43.458Z","relays":["wss://relay.damus.io","wss://nos.lol","wss://relay.primal.net"],"relayResults":[{"relay":"wss://relay.damus.io","websocketReachable":true,"publishReadOk":true,"healthy":true,"checks":{"websocket":{"ok":true,"latencyMs":165},"publishRead":{"ok":true,"eventId":"e5d42463af355402e95c400b27f1adaf427a7941fb66f84eeeefcf3ab18ec527"}}},{"relay":"wss://nos.lol","websocketReachable":true,"publishReadOk":true,"healthy":true,"checks":{"websocket":{"ok":true,"latencyMs":369},"publishRead":{"ok":true,"eventId":"d415fcbc4debff945121498964186b06347d4638362b584ed7caba6bee812723"}}},{"relay":"wss://relay.primal.net","websocketReachable":true,"publishReadOk":true,"healthy":true,"checks":{"websocket":{"ok":true,"latencyMs":462},"publishRead":{"ok":true,"eventId":"8639159ae57633f56ee82a7667dc204dee76af3167107012e0e3f90670701c7c"}}}],"summary":{"totalRelays":3,"healthyRelays":3,"unhealthyRelays":0,"allRelaysUnhealthy":false},"incidentSignal":null,"alerts":[],"alertStats":{"windowMinutes":60,"sampleCount":1,"successRate":1,"allDownDurationMinutes":0},"historyPath":"/app/task-logs/relay-health/daily.jsonl"}
{"ok":true,"cadence":"daily","namespace":"torch","timestamp":"2026-02-25T00:24:22.573Z","relays":["wss://relay.damus.io","wss://nos.lol","wss://relay.primal.net"],"relayResults":[{"relay":"wss://relay.damus.io","websocketReachable":true,"publishReadOk":true,"healthy":true,"checks":{"websocket":{"ok":true,"latencyMs":172},"publishRead":{"ok":true,"eventId":"81e4544b0ad4045a33ff42dff98d972b6a46c6ccea9fbd2d7f11aa7c3aeb887f"}}},{"relay":"wss://nos.lol","websocketReachable":true,"publishReadOk":true,"healthy":true,"checks":{"websocket":{"ok":true,"latencyMs":362},"publishRead":{"ok":true,"eventId":"6118efac07f865ac24b8245574f8a32c82bfe0834d7531c8c5c35a327fabc889"}}},{"relay":"wss://relay.primal.net","websocketReachable":true,"publishReadOk":true,"healthy":true,"checks":{"websocket":{"ok":true,"latencyMs":456},"publishRead":{"ok":true,"eventId":"507e8eb4bfbe1f646d7c92442f35413d2394a84fd72110e315cdec4cb3a5702a"}}}],"summary":{"totalRelays":3,"healthyRelays":3,"unhealthyRelays":0,"allRelaysUnhealthy":false},"incidentSignal":null,"alerts":[],"alertStats":{"windowMinutes":60,"sampleCount":1,"successRate":1,"allDownDurationMinutes":0},"historyPath":"/app/task-logs/relay-health/daily.jsonl"}
{"ok":true,"cadence":"daily","namespace":"torch","timestamp":"2026-03-02T20:13:49.514Z","relays":["wss://relay.damus.io","wss://nos.lol","wss://relay.primal.net"],"relayResults":[{"relay":"wss://relay.damus.io","websocketReachable":true,"publishReadOk":true,"healthy":true,"checks":{"websocket":{"ok":true,"latencyMs":187},"publishRead":{"ok":true,"eventId":"c8bd3dbf95477d277caa9b33d5585e55a17aedb8059c178a845c8d4eec684eb8"}}},{"relay":"wss://nos.lol","websocketReachable":true,"publishReadOk":true,"healthy":true,"checks":{"websocket":{"ok":true,"latencyMs":363},"publishRead":{"ok":true,"eventId":"c3b20528262efacb7d75787498a1b1e10404ca727eafcedb5f7f36f36222374d"}}},{"relay":"wss://relay.primal.net","websocketReachable":true,"publishReadOk":true,"healthy":true,"checks":{"websocket":{"ok":true,"latencyMs":429},"publishRead":{"ok":true,"eventId":"1efa5f19b9e97f0313c06c5913748f277746ac3d8843ca57c39f8362f051af34"}}}],"summary":{"totalRelays":3,"healthyRelays":3,"unhealthyRelays":0,"allRelaysUnhealthy":false},"incidentSignal":null,"alerts":[],"alertStats":{"windowMinutes":60,"sampleCount":1,"successRate":1,"allDownDurationMinutes":0},"historyPath":"/app/task-logs/relay-health/daily.jsonl"}