From 6cb53fd703ac7a66922c2d19c5118a3263c522af Mon Sep 17 00:00:00 2001 From: Jason Elkin Date: Tue, 11 Oct 2022 01:41:50 +0100 Subject: [PATCH] Swap HSTS healthcheck status on localhost --- .../EmbeddedResources/Lang/en.xml | 6 +++ .../EmbeddedResources/Lang/en_us.xml | 6 +++ .../HealthChecks/Checks/Security/HstsCheck.cs | 54 ++++++++++++++++++- 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Core/EmbeddedResources/Lang/en.xml b/src/Umbraco.Core/EmbeddedResources/Lang/en.xml index 5c2e4dc9a2..38ad5d4917 100644 --- a/src/Umbraco.Core/EmbeddedResources/Lang/en.xml +++ b/src/Umbraco.Core/EmbeddedResources/Lang/en.xml @@ -2347,6 +2347,12 @@ To manage your website, simply open the Umbraco backoffice and start adding cont Strict-Transport-Security, also known as the HSTS-header, was found.]]> Strict-Transport-Security was not found.]]> + + Strict-Transport-Security, also known as the HSTS-header, was found. This header should not be present on localhost.]]> + + + Strict-Transport-Security was not found. This header should not be present on localhost.]]> + X-XSS-Protection was found.]]> X-XSS-Protection was not found.]]> diff --git a/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml b/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml index 1aae2efb56..50fa9d6d59 100644 --- a/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml +++ b/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml @@ -2450,6 +2450,12 @@ To manage your website, simply open the Umbraco backoffice and start adding cont Strict-Transport-Security, also known as the HSTS-header, was found.]]> Strict-Transport-Security was not found.]]> + + Strict-Transport-Security, also known as the HSTS-header, was found. This header should not be present on localhost.]]> + + + Strict-Transport-Security was not found. This header should not be present on localhost.]]> + X-XSS-Protection was found.]]> X-XSS-Protection was not found.]]> diff --git a/src/Umbraco.Core/HealthChecks/Checks/Security/HstsCheck.cs b/src/Umbraco.Core/HealthChecks/Checks/Security/HstsCheck.cs index 229999472e..0637404045 100644 --- a/src/Umbraco.Core/HealthChecks/Checks/Security/HstsCheck.cs +++ b/src/Umbraco.Core/HealthChecks/Checks/Security/HstsCheck.cs @@ -3,6 +3,7 @@ using Umbraco.Cms.Core.Hosting; using Umbraco.Cms.Core.Services; +using Umbraco.Extensions; namespace Umbraco.Cms.Core.HealthChecks.Checks.Security; @@ -16,6 +17,11 @@ namespace Umbraco.Cms.Core.HealthChecks.Checks.Security; Group = "Security")] public class HstsCheck : BaseHttpHeaderCheck { + private const string LocalizationPrefix = "hSTS"; + + private readonly IHostingEnvironment _hostingEnvironment; + private readonly ILocalizedTextService _textService; + /// /// Initializes a new instance of the class. /// @@ -27,10 +33,56 @@ public class HstsCheck : BaseHttpHeaderCheck /// but then you should include subdomains and I wouldn't suggest to do that for Umbraco-sites. /// public HstsCheck(IHostingEnvironment hostingEnvironment, ILocalizedTextService textService) - : base(hostingEnvironment, textService, "Strict-Transport-Security", "hSTS", true) + : base(hostingEnvironment, textService, "Strict-Transport-Security", LocalizationPrefix, true) { + _hostingEnvironment = hostingEnvironment; + _textService = textService; } /// protected override string ReadMoreLink => Constants.HealthChecks.DocumentationLinks.Security.HstsCheck; + + /// + public override async Task> GetStatus() => + new HealthCheckStatus[] { await CheckForHeader() }; + + /// + /// The health check task. + /// + /// A with the result type reversed on localhost. + protected new async Task CheckForHeader() + { + HealthCheckStatus checkHeaderResult = await base.CheckForHeader(); + + var isLocalhost = _hostingEnvironment.ApplicationMainUrl?.Host.ToLowerInvariant() == "localhost"; + + // when not on localhost, the header should exist. + if (!isLocalhost) + { + return checkHeaderResult; + } + + string message; + StatusResultType statusResultType; + + // on localhost the header should not exist, so invert the status. + if (checkHeaderResult.ResultType == StatusResultType.Success) + { + statusResultType = StatusResultType.Error; + + message = _textService.Localize("healthcheck", $"{LocalizationPrefix}CheckHeaderFoundOnLocalhost"); + } + else + { + statusResultType = StatusResultType.Success; + + message = _textService.Localize("healthcheck", $"{LocalizationPrefix}CheckHeaderNotFoundOnLocalhost"); + } + + return new HealthCheckStatus(message) + { + ResultType = statusResultType, + ReadMoreLink = ReadMoreLink, + }; + } }