diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 0000000000..b6927e6e31 --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,4 @@ +## 2024-05-24 - Cross-Site Scripting (XSS) in UI Modals +**Vulnerability:** The confirm dialog component used `innerHTML` with string interpolation for dynamic arguments like `title`, `message`, `confirmText`, and `cancelText`, introducing a Cross-Site Scripting (XSS) vulnerability. +**Learning:** Reusable UI components that accept arbitrary text arguments are prone to XSS if they construct DOM elements using template literals and `innerHTML` instead of dynamically setting properties like `textContent` after DOM construction. +**Prevention:** Avoid `innerHTML` when rendering user-provided or dynamically constructed text variables in frontend modules. Render the skeleton HTML first, select the nodes, and populate their content using `textContent`. diff --git a/webui/js/confirmDialog.js b/webui/js/confirmDialog.js index 6289af608b..a7864de8fb 100644 --- a/webui/js/confirmDialog.js +++ b/webui/js/confirmDialog.js @@ -31,12 +31,12 @@ export function showConfirmDialog(options) { dialog.innerHTML = `
${typeConfig.icon} - ${title} +
-
${message}
+
`; @@ -48,6 +48,11 @@ export function showConfirmDialog(options) { const footerElement = dialog.querySelector('.confirm-dialog-footer'); const cancelButton = dialog.querySelector('.confirm-dialog-cancel'); const confirmButton = dialog.querySelector('.confirm-dialog-confirm'); + + titleElement.textContent = title; + bodyElement.textContent = message; + cancelButton.textContent = cancelText; + confirmButton.textContent = confirmText; let isClosed = false; // Show with animation