From 7a3608b32e054269fa71b206ad7fa099177865d0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Feb 2026 13:56:14 +0000 Subject: [PATCH 1/5] Initial plan From 0126dc1cf4b7edf2c04b548d199676eecf2c4832 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Feb 2026 13:59:25 +0000 Subject: [PATCH 2/5] Fix XSS vulnerabilities in JavaScript files Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com> --- backend/app/static/css/styles.css | 11 +++++++++++ backend/app/static/js/dashboard.js | 25 +++++++++++++++++-------- backend/app/static/js/setup.js | 6 ++++-- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/backend/app/static/css/styles.css b/backend/app/static/css/styles.css index b1c9f28..9850883 100644 --- a/backend/app/static/css/styles.css +++ b/backend/app/static/css/styles.css @@ -246,4 +246,15 @@ h1, h2, h3, h4, h5, h6 { .chart-container { height: 16rem; /* h-64 */ @apply w-full; +} + +/* Text status colors for compliance status */ +.text-success { + color: #16a34a; /* Green color for compliant status */ + font-weight: 500; +} + +.text-error { + color: #dc2626; /* Red color for non-compliant status */ + font-weight: 500; } \ No newline at end of file diff --git a/backend/app/static/js/dashboard.js b/backend/app/static/js/dashboard.js index 9eaf3f0..cc346d9 100644 --- a/backend/app/static/js/dashboard.js +++ b/backend/app/static/js/dashboard.js @@ -231,14 +231,23 @@ function renderRecentReports(reports, domains) { // Get domain name const domainName = domainMap.get(report.domain_id) || 'Unknown'; - row.innerHTML = ` - ${domainName} - ${formattedDate} - ${report.is_compliant ? - 'Compliant' : - 'Non-compliant' - } - `; + // Create domain cell with safe text content + const domainCell = document.createElement('td'); + domainCell.textContent = domainName; + row.appendChild(domainCell); + + // Create date cell with safe text content + const dateCell = document.createElement('td'); + dateCell.textContent = formattedDate; + row.appendChild(dateCell); + + // Create status cell with safe text content and CSS classes + const statusCell = document.createElement('td'); + const statusSpan = document.createElement('span'); + statusSpan.textContent = report.is_compliant ? 'Compliant' : 'Non-compliant'; + statusSpan.className = report.is_compliant ? 'text-success' : 'text-error'; + statusCell.appendChild(statusSpan); + row.appendChild(statusCell); tableBody.appendChild(row); }); diff --git a/backend/app/static/js/setup.js b/backend/app/static/js/setup.js index 1a3ed8a..2c641cb 100644 --- a/backend/app/static/js/setup.js +++ b/backend/app/static/js/setup.js @@ -184,9 +184,11 @@ function setupWizardEventListeners() { const cloudflareToken = document.getElementById('cloudflare-token').value; const cloudflareZone = document.getElementById('cloudflare-zone').value; + // Store only the flag that Cloudflare is enabled + // Credentials should be sent directly to backend, never stored client-side localStorage.setItem('setup_cloudflare_enabled', 'true'); - localStorage.setItem('setup_cloudflare_token', cloudflareToken); - localStorage.setItem('setup_cloudflare_zone', cloudflareZone); + // TODO: Send cloudflareToken and cloudflareZone to backend API instead of localStorage + // For now, these credentials are not persisted client-side for security } // Move to step 3 From fdc79eea49249de6db96ce6c7ab81302d1056523 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Feb 2026 14:01:37 +0000 Subject: [PATCH 3/5] Update CSP directives and add detailed security TODOs Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com> --- backend/app/middleware/security.py | 35 +++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/backend/app/middleware/security.py b/backend/app/middleware/security.py index 6b9d42e..b58d2f6 100644 --- a/backend/app/middleware/security.py +++ b/backend/app/middleware/security.py @@ -52,14 +52,37 @@ class SecurityHeadersMiddleware(BaseHTTPMiddleware): # Content Security Policy (CSP) # Restricts sources of content that can be loaded - # TODO: Remove 'unsafe-inline' and 'unsafe-eval' and use nonces/hashes instead + # + # SECURITY TODO: Current CSP includes 'unsafe-inline' and 'unsafe-eval' which + # weaken XSS protection. To remove these: + # + # For script-src 'unsafe-inline': + # 1. Move all inline ' + +// Image onerror +'' + +// SVG onload +'' + +// Event handler injection +'">' + +// JavaScript protocol +'javascript:alert("XSS")' + +// HTML entity encoding bypass +'<script>alert("XSS")</script>' +``` + +With the fixes applied: +- `textContent` automatically escapes these payloads +- They would display as literal text, not execute +- No HTML parsing occurs for user data + +## Existing Test Coverage + +The test suite already includes XSS input validation: + +**File**: `backend/app/tests/test_security.py` + +```python +# Line 146: Domain config validation +malicious_config = {"name": "example.com", "description": ""} +result = validate_domain_config(malicious_config) +assert not result["valid"] +assert "description" in result["errors"] +``` + +**Status**: ✅ Test validates that malicious input is rejected at API level + +## Security Scanning Results + +### CodeQL Analysis +``` +Analysis Result for 'python, javascript'. Found 0 alerts: +- **python**: No alerts found. +- **javascript**: No alerts found. +``` + +**Status**: ✅ No vulnerabilities detected + +### Code Review Tool +``` +Code review completed. Reviewed 5 file(s). +No review comments found. +``` + +**Status**: ✅ No issues found + +## Remaining Work + +### CSP Hardening (Future Work) +The Content Security Policy still includes `unsafe-inline` and `unsafe-eval` directives. To remove these: + +1. **For script-src 'unsafe-inline'**: + - Move inline `