From 5f530a28b324fa5c9d3743ba331262500c922845 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 29 May 2026 03:02:29 +0000 Subject: [PATCH] Fix DOM-based XSS in upload.js by sanitizing file.name This commit resolves a DOM-based Cross-Site Scripting (XSS) vulnerability in `frontend/static/js/upload.js`. Previously, the user-controlled `file.name` was directly interpolated into the DOM using `innerHTML` without any HTML entity escaping. A maliciously crafted filename could lead to script execution. A local `_escapeHtml` function has been introduced to safely escape characters like `<`, `>`, `&`, `"`, and `'` before rendering. Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com> --- .jules/sentinel.md | 4 ++++ frontend/static/js/upload.js | 13 ++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/.jules/sentinel.md b/.jules/sentinel.md index af243c59..6bf44773 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -28,3 +28,7 @@ **Vulnerability:** The `/process-url` endpoint used `httpx.AsyncClient(follow_redirects=True)` after validating the initial user-provided URL against SSRF protections. However, it did not validate the target URLs of any subsequent HTTP redirects, allowing an attacker to provide a safe URL that redirects to an internal/private IP, bypassing the security check. **Learning:** Initial URL validation is insufficient when the HTTP client is configured to follow redirects automatically. The client must be explicitly configured to validate every redirect target. **Prevention:** When using `httpx.AsyncClient(follow_redirects=True)` for user-provided URLs, always implement a redirect validator hook function (e.g., using `event_hooks={'response': [validate_redirect]}`) that resolves the `Location` header and passes it through the same SSRF validation logic before the redirect is followed. +## 2026-05-29 - DOM-based XSS in Upload UI +**Vulnerability:** In `frontend/static/js/upload.js`, user-controlled file names (`file.name`) were directly injected into the DOM via `innerHTML` without sanitization, leading to a potential DOM-based Cross-Site Scripting (XSS) vulnerability. +**Learning:** Any user-controlled input, including file names, that is dynamically inserted into HTML (specifically via `innerHTML` or similar sinks) must be treated as untrusted and sanitized. +**Prevention:** Always define and use a local `_escapeHtml` function to sanitize user-controlled strings (replacing `&`, `<`, `>`, `"`, `'`) before interpolating them into HTML strings that will be rendered via `innerHTML`. diff --git a/frontend/static/js/upload.js b/frontend/static/js/upload.js index b8ecd62a..f94eb2d3 100644 --- a/frontend/static/js/upload.js +++ b/frontend/static/js/upload.js @@ -293,13 +293,24 @@ function processFiles(files, progressContainer, statusMessage) { updateStatus(); } + function _escapeHtml(str) { + if (!str) return ''; + return String(str) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + } + // Pre-create one progress row per file. const queueItems = fileArray.map((file) => { const row = document.createElement('div'); row.className = 'flex flex-col mb-2'; + const escapedName = _escapeHtml(file.name); row.innerHTML = `