Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .jules/sentinel.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,8 @@
**Vulnerability:** CRLF Injection (CWE-93) / Email Content Injection
**Learning:** Interpolating untrusted data (like IP addresses, block reasons, or actor names) directly into email headers or the `Subject` line without sanitization allows an attacker to inject CR/LF characters. This can be used to terminate headers prematurely and inject additional headers (e.g., `Bcc`, `Reply-To`) or even replace the entire email body.
**Prevention:** Always sanitize any input destined for a network header or a delimited protocol. Using a `strings.NewReplacer("\r", "", "\n", "")` to strip line-break characters ensures that untrusted content remains confined to its intended field and cannot "break out" to inject new headers.

## 2026-06-13 - [DOM-based XSS in Toast Notifications]
**Vulnerability:** DOM-based Cross-Site Scripting (XSS) (CWE-79)
**Learning:** Using `innerHTML` with string interpolation to dynamically construct HTML elements using untrusted data allows the browser to execute embedded `<script>` tags or malicious event handlers. The application was rendering `toast.innerHTML = \`<span>${message}</span>\`;` where `message` could contain data from server error responses.
**Prevention:** Avoid `innerHTML` for any content that includes user-supplied or untrusted strings. Instead, use DOM methods like `document.createElement()` and set data using safe properties like `textContent` or `innerText`, which automatically escape HTML entities.
2 changes: 1 addition & 1 deletion cmd/server/templates/admin_management.html
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ <h3 style="margin-top: 0;">Change Password</h3>
const container = document.getElementById('toast-container');
const toast = document.createElement('div');
toast.className = `toast ${type}`;
toast.innerHTML = `<span>${message}</span>`;
const span = document.createElement("span"); span.textContent = message; toast.appendChild(span);
container.appendChild(toast);
setTimeout(() => {
toast.style.opacity = '0';
Expand Down
2 changes: 1 addition & 1 deletion cmd/server/templates/excluded.html
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ <h3 style="margin: 0; color: #fff;">External Dynamic Sources</h3>
const container = document.getElementById('toast-container');
const toast = document.createElement('div');
toast.className = `toast ${type}`;
toast.innerHTML = `<span>${message}</span>`;
const span = document.createElement("span"); span.textContent = message; toast.appendChild(span);
container.appendChild(toast);
setTimeout(() => {
toast.style.opacity = '0';
Expand Down
2 changes: 1 addition & 1 deletion cmd/server/templates/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,7 @@ <h4 style="color: var(--vibrant-red); margin-top: 2rem; margin-bottom: 0.5rem;">
const container = document.getElementById('toast-container');
const toast = document.createElement('div');
toast.className = `toast ${type}`;
toast.innerHTML = `<span>${message}</span>`;
const span = document.createElement("span"); span.textContent = message; toast.appendChild(span);
container.appendChild(toast);
setTimeout(() => {
toast.style.opacity = '0';
Expand Down
2 changes: 1 addition & 1 deletion cmd/server/templates/whitelist.html
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ <h2>IP Whitelist</h2>
function showToast(message, type = 'success') {
const container = document.getElementById('toast-container'); const toast = document.createElement('div');
toast.className = `toast ${type}`;
toast.innerHTML = `<span>${message}</span>`;
const span = document.createElement("span"); span.textContent = message; toast.appendChild(span);
container.appendChild(toast);
setTimeout(() => {
toast.style.opacity = '0';
Expand Down
Loading