Skip to content

Commit 433cbb7

Browse files
authored
Merge pull request #86 from miguelcrpinto/feature/issue-76-Cross-Origin-Resource-Policy_not_supported
Implemented Cross-Origin-Resource-Policy response header
2 parents 19474cc + ddc58ca commit 433cbb7

10 files changed

+137
-2
lines changed

changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ This changelog represents all of the major (i.e. breaking) changes made to the O
1212
| 2 | Uses `secureHeaderSettings.json` and default config loader to create instances of `SecureHeadersMiddlewareConfiguration` class <br /> also uses .NET Core 2.0 |
1313
| 1 | Uses `secureHeaderSettings.json` and default config loader to create instances of `SecureHeadersMiddlewareConfiguration` class <br /> also uses .NET Standard 1.4 |
1414

15+
### Version 7
16+
17+
This version adds the Cross-Origin-Resource-Policy header with the OWASP recommended value "same-origin" to the list of default headers in the `BuildDefaultConfiguration()` extension method. This was requested via [issue #76](https://github.com/GaProgMan/OwaspHeaders.Core/issues/76).
18+
1519
### Version 6
1620

1721
This version removes Expect-CT Header from the list of default headers in the `BuildDefaultConfiguration()` extension method. This is related to [issue #72](https://github.com/GaProgMan/OwaspHeaders.Core/issues/72).

src/Constants.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,7 @@ public static class Constants
2727
public static readonly string PoweredByHeaderName = "X-Powered-By";
2828

2929
public static readonly string ServerHeaderName = "Server";
30+
31+
public static readonly string CrossOriginResourcePolicyHeaderName = "Cross-Origin-Resource-Policy";
3032
}
3133
}

src/Extensions/SecureHeadersMiddlewareBuilder.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using OwaspHeaders.Core.Enums;
1313
using OwaspHeaders.Core.Helpers;
1414
using OwaspHeaders.Core.Models;
15+
using static OwaspHeaders.Core.Models.CrossOriginResourcePolicy;
1516

1617
namespace OwaspHeaders.Core.Extensions
1718
{
@@ -319,7 +320,23 @@ public static SecureHeadersMiddlewareConfiguration RemovePoweredByHeader
319320
(this SecureHeadersMiddlewareConfiguration config)
320321
{
321322
config.RemoveXPoweredByHeader = true;
323+
return config;
324+
}
322325

326+
/// <summary>
327+
/// The HTTP Cross-Origin-Resource-Policy response header conveys a desire that the browser
328+
/// blocks no-cors cross-origin/cross-site requests to the given resource.
329+
/// </summary>
330+
/// <param name="value">
331+
/// The HTTP Cross-Origin-Resource-Policy response header value.
332+
/// </param>
333+
/// <remarks>
334+
/// Defaults to "same-origin" (<see cref="CrossOriginResourceOptions.SameOrigin"/>) which means that "Only requests from the same Origin (i.e. scheme + host + port) can read the resource."
335+
///</remarks>
336+
public static SecureHeadersMiddlewareConfiguration UseCrossOriginResourcePolicy(this SecureHeadersMiddlewareConfiguration config, CrossOriginResourceOptions value = CrossOriginResourceOptions.SameOrigin)
337+
{
338+
config.UseCrossOriginResourcePolicy = true;
339+
config.CrossOriginResourcePolicy = new CrossOriginResourcePolicy(value);
323340
return config;
324341
}
325342

src/Extensions/SecureHeadersMiddlewareExtensions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public static SecureHeadersMiddlewareConfiguration BuildDefaultConfiguration()
3333
.UseCacheControl()
3434
.RemovePoweredByHeader()
3535
.UseXssProtection()
36+
.UseCrossOriginResourcePolicy()
3637
.Build();
3738
}
3839

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
namespace OwaspHeaders.Core.Models
2+
{
3+
/// <summary>
4+
/// Cross-Origin-Resource-Policy
5+
/// This response header(also named CORP) allows to define a policy that lets web sites and applications opt in to protection
6+
/// against certain requests from other origins(such as those issued with elements like<script> and <img>), to mitigate speculative
7+
/// side-channel attacks, like Spectre, as well as Cross-Site Script Inclusion(XSSI) attacks(source Mozilla MDN).
8+
/// </summary>
9+
public class CrossOriginResourcePolicy : IConfigurationBase
10+
{
11+
/// <summary>
12+
/// Only requests from the same Origin (i.e. scheme + host + port) can read the resource.
13+
/// </summary>
14+
public const string SameOriginValue = "same-origin";
15+
/// <summary>
16+
/// Only requests from the same Site can read the resource.
17+
/// </summary>
18+
public const string SameSiteValue = "same-site";
19+
/// <summary>
20+
/// Requests from any Origin (both same-site and cross-site) can read the resource.
21+
/// Browsers are using this policy when an CORP header is not specified.
22+
/// </summary>
23+
public const string CrossOriginValue = "cross-origin";
24+
25+
public enum CrossOriginResourceOptions
26+
{
27+
/// <summary>
28+
/// <see cref="SameOriginValue"/>
29+
/// </summary>
30+
SameOrigin,
31+
/// <summary>
32+
/// <see cref="SameSiteValue"/>
33+
/// </summary>
34+
SameSite,
35+
/// <summary>
36+
/// <see cref="CrossOriginValue"/>
37+
/// </summary>
38+
CrossOrigin
39+
};
40+
41+
public CrossOriginResourceOptions OptionValue { get; set; }
42+
43+
public CrossOriginResourcePolicy(CrossOriginResourceOptions value = CrossOriginResourceOptions.SameOrigin)
44+
{
45+
OptionValue = value;
46+
}
47+
48+
/// <summary>
49+
/// Builds the HTTP header value
50+
/// </summary>
51+
/// <returns>A string representing the HTTP header value</returns>
52+
public string BuildHeaderValue()
53+
{
54+
switch (OptionValue)
55+
{
56+
case CrossOriginResourceOptions.CrossOrigin:
57+
return CrossOriginValue;
58+
case CrossOriginResourceOptions.SameSite:
59+
return SameSiteValue;
60+
case CrossOriginResourceOptions.SameOrigin:
61+
default:
62+
return SameOriginValue;
63+
}
64+
}
65+
66+
}
67+
}

src/Models/SecureHeadersMiddlewareConfiguration.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ public class SecureHeadersMiddlewareConfiguration
6363

6464
public bool RemoveXPoweredByHeader { get; set; }
6565

66+
/// <summary>
67+
/// Indicates whether the response should use Cross-Origin-Resource-Policy
68+
/// </summary>
69+
public bool UseCrossOriginResourcePolicy { get; set; }
70+
6671
/// <summary>
6772
/// The HTTP Strict Transport Security configuration to use
6873
/// </summary>
@@ -107,5 +112,7 @@ public class SecureHeadersMiddlewareConfiguration
107112
/// The Expect-CT configuration to use
108113
/// </summary>
109114
public ExpectCt ExpectCt { get; set; }
115+
116+
public CrossOriginResourcePolicy CrossOriginResourcePolicy { get; set; }
110117
}
111118
}

src/OwaspHeaders.Core.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<Description>An ASP.NET Core Middleware which adds the OWASP recommended HTTP headers for enhanced security.</Description>
4-
<VersionPrefix>6.1.0</VersionPrefix>
4+
<VersionPrefix>7.0.0</VersionPrefix>
55
<Authors>Jamie Taylor</Authors>
66
<AssemblyName>OwaspHeaders.Core</AssemblyName>
77
<TargetFramework>netstandard2.0</TargetFramework>

src/OwaspHeadersCore.nuspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<package xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
33
<metadata xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
44
<id>OwaspHeaders.Core</id>
5-
<version>6.1.0</version>
5+
<version>7.0.0</version>
66
<authors>GaProgMan</authors>
77
<owners>GaProgMan</owners>
88
<readme>docs\README-NuGet.md</readme>

src/SecureHeadersMiddleware.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,12 @@ public async Task InvokeAsync(HttpContext httpContext)
113113
httpContext.TryRemoveHeader(Constants.ServerHeaderName);
114114
}
115115

116+
if(_config.UseCrossOriginResourcePolicy)
117+
{
118+
httpContext.TryAddHeader(Constants.CrossOriginResourcePolicyHeaderName,
119+
_config.CrossOriginResourcePolicy.BuildHeaderValue());
120+
}
121+
116122
// Call the next middleware in the chain
117123
await _next(httpContext);
118124
}

tests/SecureHeadersInjectedTest.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,4 +475,35 @@ public async Task Invoke_CacheControl_HeaderIsNotPresent()
475475
Assert.False(headerNotPresentConfig.UseCacheControl);
476476
Assert.False(_context.Response.Headers.ContainsKey(Constants.CacheControlHeaderName));
477477
}
478+
479+
[Fact]
480+
public async Task Invoke_CrossOriginResourcePolicyHeaderName_HeaderIsPresent()
481+
{
482+
// arrange
483+
var headerPresentConfig = SecureHeadersMiddlewareBuilder.CreateBuilder().UseCrossOriginResourcePolicy().Build();
484+
var secureHeadersMiddleware = new SecureHeadersMiddleware(_onNext, headerPresentConfig);
485+
486+
// act
487+
await secureHeadersMiddleware.InvokeAsync(_context);
488+
489+
// assert
490+
Assert.True(headerPresentConfig.UseCrossOriginResourcePolicy);
491+
Assert.True(_context.Response.Headers.ContainsKey(Constants.CrossOriginResourcePolicyHeaderName));
492+
Assert.Equal(CrossOriginResourcePolicy.SameOriginValue, _context.Response.Headers[Constants.CrossOriginResourcePolicyHeaderName]);
493+
}
494+
495+
[Fact]
496+
public async Task Invoke_CrossOriginResourcePolicyHeaderName_HeaderIsNotPresent()
497+
{
498+
// arrange
499+
var headerNotPresentConfig = SecureHeadersMiddlewareBuilder.CreateBuilder().Build();
500+
var secureHeadersMiddleware = new SecureHeadersMiddleware(_onNext, headerNotPresentConfig);
501+
502+
// act
503+
await secureHeadersMiddleware.InvokeAsync(_context);
504+
505+
// assert
506+
Assert.False(headerNotPresentConfig.UseCrossOriginResourcePolicy);
507+
Assert.False(_context.Response.Headers.ContainsKey(Constants.CrossOriginResourcePolicyHeaderName));
508+
}
478509
}

0 commit comments

Comments
 (0)