Skip to content
Merged
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
1 change: 0 additions & 1 deletion src/Umbraco.Core/Constants-HealthChecks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ public static class Security
public const string ClickJackingCheck = "https://umbra.co/healthchecks-click-jacking";
public const string HstsCheck = "https://umbra.co/healthchecks-hsts";
public const string NoSniffCheck = "https://umbra.co/healthchecks-no-sniff";
public const string XssProtectionCheck = "https://umbra.co/healthchecks-xss-protection";
public const string ExcessiveHeadersCheck = "https://umbra.co/healthchecks-excessive-headers";

public static class HttpsCheck
Expand Down
8 changes: 6 additions & 2 deletions src/Umbraco.Core/EmbeddedResources/Lang/en.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2358,9 +2358,13 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
<key alias="hSTSCheckHeaderNotFoundOnLocalhost">
<![CDATA[The header <strong>Strict-Transport-Security</strong> was not found. This header should not be present on localhost.]]>
</key>
<key alias="xssProtectionCheckHeaderFound"><![CDATA[The header <strong>X-XSS-Protection</strong> was found.]]></key>
<key alias="xssProtectionCheckHeaderFound">
<![CDATA[The header <strong>X-XSS-Protection</strong> was found. <strong>It is recommended not to add this header to your website</strong>.<br />
You can read about this on the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection" target="_blank" rel="noopener" class="btn-link -underline">Mozilla</a> website ]]>
</key>
<key alias="xssProtectionCheckHeaderNotFound">
<![CDATA[The header <strong>X-XSS-Protection</strong> was not found.]]></key>
<![CDATA[The header <strong>X-XSS-Protection</strong> was not found.]]>
</key>
<!-- The following key get these tokens passed in:
0: Comma delimitted list of headers found
-->
Expand Down
4 changes: 3 additions & 1 deletion src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2461,7 +2461,9 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
<key alias="hSTSCheckHeaderNotFoundOnLocalhost">
<![CDATA[The header <strong>Strict-Transport-Security</strong> was not found. This header should not be present on localhost.]]>
</key>
<key alias="xssProtectionCheckHeaderFound"><![CDATA[The header <strong>X-XSS-Protection</strong> was found.]]></key>
<key alias="xssProtectionCheckHeaderFound">
<![CDATA[The header <strong>X-XSS-Protection</strong> was found. <strong>It is recommended not to add this header to your website</strong>.<br />
You can read about this on the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection" target="_blank" rel="noopener" class="btn-link -underline">Mozilla</a> website ]]></key>
<key alias="xssProtectionCheckHeaderNotFound">
<![CDATA[The header <strong>X-XSS-Protection</strong> was not found.]]></key>
<!-- The following key get these tokens passed in:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public abstract class BaseHttpHeaderCheck : HealthCheck
private readonly IHostingEnvironment _hostingEnvironment;
private readonly string _localizedTextPrefix;
private readonly bool _metaTagOptionAvailable;
private readonly bool _shouldNotExist;

/// <summary>
/// Initializes a new instance of the <see cref="BaseHttpHeaderCheck" /> class.
Expand All @@ -27,13 +28,15 @@ protected BaseHttpHeaderCheck(
ILocalizedTextService textService,
string header,
string localizedTextPrefix,
bool metaTagOptionAvailable)
bool metaTagOptionAvailable,
bool shouldNotExist = false)
{
LocalizedTextService = textService ?? throw new ArgumentNullException(nameof(textService));
_hostingEnvironment = hostingEnvironment;
_header = header;
_localizedTextPrefix = localizedTextPrefix;
_metaTagOptionAvailable = metaTagOptionAvailable;
_shouldNotExist = shouldNotExist;
}

[Obsolete("Save ILocalizedTextService in a field on the super class instead of using this")]
Expand All @@ -42,7 +45,7 @@ protected BaseHttpHeaderCheck(
/// <summary>
/// Gets a link to an external read more page.
/// </summary>
protected abstract string ReadMoreLink { get; }
protected abstract string? ReadMoreLink { get; }

private static HttpClient HttpClient => httpClient ??= new HttpClient();

Expand All @@ -66,6 +69,7 @@ protected async Task<HealthCheckStatus> CheckForHeader()
{
string message;
var success = false;
StatusResultType resultType = StatusResultType.Warning;

// Access the site home page and check for the click-jack protection header or meta tag
var url = _hostingEnvironment.ApplicationMainUrl?.GetLeftPart(UriPartial.Authority);
Expand All @@ -86,6 +90,16 @@ protected async Task<HealthCheckStatus> CheckForHeader()
message = success
? LocalizedTextService.Localize("healthcheck", $"{_localizedTextPrefix}CheckHeaderFound")
: LocalizedTextService.Localize("healthcheck", $"{_localizedTextPrefix}CheckHeaderNotFound");

if (_shouldNotExist)
{

resultType = success ? StatusResultType.Error : StatusResultType.Success;
}
else
{
resultType = success ? StatusResultType.Success : StatusResultType.Error;
}
}
catch (Exception ex)
{
Expand All @@ -95,8 +109,8 @@ protected async Task<HealthCheckStatus> CheckForHeader()
return
new HealthCheckStatus(message)
{
ResultType = success ? StatusResultType.Success : StatusResultType.Error,
ReadMoreLink = success ? null : ReadMoreLink,
ResultType = resultType,
ReadMoreLink = success && !string.IsNullOrEmpty(ReadMoreLink) ? null : ReadMoreLink,
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,22 @@ namespace Umbraco.Cms.Core.HealthChecks.Checks.Security;
[HealthCheck(
"F4D2B02E-28C5-4999-8463-05759FA15C3A",
"Cross-site scripting Protection (X-XSS-Protection header)",
Description = "This header enables the Cross-site scripting (XSS) filter in your browser. It checks for the presence of the X-XSS-Protection-header.",
Description = "This checks for the presence of the X-XSS-Protection-header.",
Group = "Security")]
public class XssProtectionCheck : BaseHttpHeaderCheck
{
/// <summary>
/// Initializes a new instance of the <see cref="XssProtectionCheck" /> class.
/// </summary>
/// <remarks>
/// The check is mostly based on the instructions in the OWASP CheatSheet
/// (https://www.owasp.org/index.php/HTTP_Strict_Transport_Security_Cheat_Sheet)
/// and the blog post of Troy Hunt (https://www.troyhunt.com/understanding-http-strict-transport/)
/// If you want do to it perfectly, you have to submit it https://hstspreload.appspot.com/,
/// but then you should include subdomains and I wouldn't suggest to do that for Umbraco-sites.
/// This check should not find the header in newer browsers as this can cause security vulnerabilities
/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection
/// </remarks>
public XssProtectionCheck(IHostingEnvironment hostingEnvironment, ILocalizedTextService textService)
: base(hostingEnvironment, textService, "X-XSS-Protection", "xssProtection", true)
: base(hostingEnvironment, textService, "X-XSS-Protection", "xssProtection", true, true)
{
}

/// <inheritdoc />
protected override string ReadMoreLink => Constants.HealthChecks.DocumentationLinks.Security.XssProtectionCheck;
protected override string? ReadMoreLink => null;
}