diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 0000000000..0844d342ef --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,4 @@ +## 2024-05-15 - XSS in Modal Loading +**Vulnerability:** XSS vulnerability in modal content loading where `error.message` and `modalPath` were injected into the DOM using `innerHTML`. +**Learning:** Error messages from failed component imports can be manipulated to inject malicious scripts, and `modalPath` is user-controllable. +**Prevention:** Always use `textContent` instead of `innerHTML` when inserting dynamic data, especially error messages or paths, into the DOM to prevent XSS vulnerabilities. diff --git a/webui/js/modals.js b/webui/js/modals.js index c4e444a801..9ce8392b48 100644 --- a/webui/js/modals.js +++ b/webui/js/modals.js @@ -171,7 +171,7 @@ export async function openModal(modalPath, beforeClose = null) { importComponent(componentPath, modal.body) .then((doc) => { // Set the title from the document - modal.title.innerHTML = doc.title || modalPath; + modal.title.textContent = doc.title || modalPath; if (doc.html && doc.html.classList) { const inner = modal.element.querySelector(".modal-inner"); if (inner) inner.classList.add(...doc.html.classList); @@ -194,7 +194,11 @@ export async function openModal(modalPath, beforeClose = null) { }) .catch((error) => { console.error("Error loading modal content:", error); - modal.body.innerHTML = `
Failed to load modal content: ${error.message}
`; + modal.body.innerHTML = ''; + const errorDiv = document.createElement('div'); + errorDiv.className = 'error'; + errorDiv.textContent = `Failed to load modal content: ${error.message}`; + modal.body.appendChild(errorDiv); }); // Add modal to stack and show it