From 5ea2b7830f6cca092c0c9339cf3aba5f029c321f Mon Sep 17 00:00:00 2001 From: Christopher Morriss Date: Mon, 22 Jun 2026 10:02:38 +0100 Subject: [PATCH 1/4] removed inline styles, added prod only CSP, reviewed CSP --- SAPSec.Web/AssetSrc/scss/main.scss | 12 +++++ SAPSec.Web/Helpers/CspHelper.cs | 45 +++++++++++++++++-- .../Middleware/SecurityHeadersMiddleware.cs | 4 +- SAPSec.Web/Program.cs | 2 +- SAPSec.Web/Views/Shared/_Layout.cshtml | 2 +- .../SchoolDetails.cshtml | 6 +-- .../Similarity.cshtml | 6 +-- 7 files changed, 62 insertions(+), 15 deletions(-) diff --git a/SAPSec.Web/AssetSrc/scss/main.scss b/SAPSec.Web/AssetSrc/scss/main.scss index 093a3d04..5c4a7bc5 100644 --- a/SAPSec.Web/AssetSrc/scss/main.scss +++ b/SAPSec.Web/AssetSrc/scss/main.scss @@ -212,6 +212,18 @@ } } +.app-similar-schools-contact { + border: 1px solid #b1b4b6; +} + +.app-similar-schools-contact-content { + background: #f3f2f1; +} + +.app-similar-schools-tag { + white-space: nowrap; +} + .app-similar-schools-sort { display: flex; align-items: center; diff --git a/SAPSec.Web/Helpers/CspHelper.cs b/SAPSec.Web/Helpers/CspHelper.cs index 0fcc8a19..b6c1960a 100644 --- a/SAPSec.Web/Helpers/CspHelper.cs +++ b/SAPSec.Web/Helpers/CspHelper.cs @@ -14,18 +14,55 @@ public static string GenerateNonce() return Convert.ToBase64String(byteArray); } - public static string BuildPolicy(string nonce) + public static string BuildPolicy(string nonce, IWebHostEnvironment environment) { + if (environment.IsProduction()) + { return string.Join(" ", "base-uri 'self';", "object-src 'none';", "default-src 'self';", "frame-ancestors 'none';", - "form-action 'self' https://test-oidc.signin.education.gov.uk https://pp-oidc.signin.education.gov.uk https://oidc.signin.education.gov.uk;", - "connect-src 'self' *.google-analytics.com *.analytics.google.com https://www.compare-school-performance.service.gov.uk https://api.postcodes.io https://*.doubleclick.net https://*.clarity.ms https://c.bing.com https://*.applicationinsights.azure.com/ https://*.visualstudio.com/ wss://localhost:*;", + "form-action 'self' https://oidc.signin.education.gov.uk;", + "connect-src 'self' *.google-analytics.com *.analytics.google.com https://*.clarity.ms", "img-src 'self' data: https://www.googletagmanager.com/ https://*.google-analytics.com https://atlas.microsoft.com https://*.clarity.ms https://c.bing.com https://js.monitor.azure.com/ https://*.tile.openstreetmap.org;", - "style-src 'self' 'unsafe-inline';", + "style-src 'self';", "font-src 'self' data:;", $"script-src 'self' 'nonce-{nonce}' https://www.googletagmanager.com *.google-analytics.com https://*.clarity.ms https://c.bing.com https://js.monitor.azure.com/;"); + } + else + { + return string.Join(" ", + "base-uri 'self';", + "object-src 'none';", + "default-src 'self';", + "frame-ancestors 'none';", + "form-action 'self' https://test-oidc.signin.education.gov.uk https://pp-oidc.signin.education.gov.uk;", + "connect-src 'self' *.google-analytics.com *.analytics.google.com https://*.clarity.ms https://*.visualstudio.com/ https://localhost:*;", + "img-src 'self' data: https://www.googletagmanager.com/ https://*.google-analytics.com https://atlas.microsoft.com https://*.clarity.ms https://c.bing.com https://js.monitor.azure.com/ https://*.tile.openstreetmap.org;", + "style-src 'self';", + "font-src 'self' data:;", + $"script-src 'self' 'nonce-{nonce}' https://www.googletagmanager.com *.google-analytics.com https://*.clarity.ms https://c.bing.com https://js.monitor.azure.com/;"); + } + + //Notes: + //https://c.bing.com is required by Clarity + //https://*.visualstudio.com/ used for live share in Visual Studio + //wss://localhost:* used by browsersync } + + //public static string BuildPolicy(string nonce) + //{ + // return string.Join(" ", + // "base-uri 'self';", + // "object-src 'none';", + // "default-src 'self';", + // "frame-ancestors 'none';", + // "form-action 'self' https://test-oidc.signin.education.gov.uk https://pp-oidc.signin.education.gov.uk https://oidc.signin.education.gov.uk;", + // "connect-src 'self' *.google-analytics.com *.analytics.google.com https://www.compare-school-performance.service.gov.uk https://api.postcodes.io https://*.doubleclick.net https://*.clarity.ms https://c.bing.com https://*.applicationinsights.azure.com/ https://*.visualstudio.com/ wss://localhost:*;", + // "img-src 'self' data: https://www.googletagmanager.com/ https://*.google-analytics.com https://atlas.microsoft.com https://*.clarity.ms https://c.bing.com https://js.monitor.azure.com/ https://*.tile.openstreetmap.org;", + // "style-src 'self' 'unsafe-inline';", + // "font-src 'self' data:;", + // $"script-src 'self' 'nonce-{nonce}' https://www.googletagmanager.com *.google-analytics.com https://*.clarity.ms https://c.bing.com https://js.monitor.azure.com/;"); + //} } diff --git a/SAPSec.Web/Middleware/SecurityHeadersMiddleware.cs b/SAPSec.Web/Middleware/SecurityHeadersMiddleware.cs index 36a53999..3d3a92a0 100644 --- a/SAPSec.Web/Middleware/SecurityHeadersMiddleware.cs +++ b/SAPSec.Web/Middleware/SecurityHeadersMiddleware.cs @@ -4,7 +4,7 @@ namespace SAPSec.Web.Middleware; [ExcludeFromCodeCoverage] -public class SecurityHeadersMiddleware(RequestDelegate next) +public class SecurityHeadersMiddleware(RequestDelegate next, IWebHostEnvironment environment) { public async Task InvokeAsync(HttpContext context) { @@ -32,7 +32,7 @@ public async Task InvokeAsync(HttpContext context) context.Response.Headers.Append("X-Permitted-Cross-Domain-Policies", "none"); context.Response.Headers.Append("X-XSS-Protection", "0"); context.Response.Headers.Append("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload"); - context.Response.Headers.Append("Content-Security-Policy", CspHelper.BuildPolicy(nonce)); + context.Response.Headers.Append("Content-Security-Policy", CspHelper.BuildPolicy(nonce, environment)); await next(context); } diff --git a/SAPSec.Web/Program.cs b/SAPSec.Web/Program.cs index 33138e6b..9b16ca79 100644 --- a/SAPSec.Web/Program.cs +++ b/SAPSec.Web/Program.cs @@ -201,7 +201,7 @@ public static void Main(string[] args) app.UseHsts(); } app.UseForwardedHeaders(); - app.UseMiddleware(); + app.UseMiddleware(app.Environment); app.UseHttpsRedirection(); var provider = new FileExtensionContentTypeProvider diff --git a/SAPSec.Web/Views/Shared/_Layout.cshtml b/SAPSec.Web/Views/Shared/_Layout.cshtml index 96a17277..f5fceff0 100644 --- a/SAPSec.Web/Views/Shared/_Layout.cshtml +++ b/SAPSec.Web/Views/Shared/_Layout.cshtml @@ -71,7 +71,7 @@ n&&j.setAttribute('nonce',n.nonce||n.getAttribute('nonce'));f.parentNode.insertB @if (loadAnalytics && !string.IsNullOrWhiteSpace(gtmId)) { - + }