From cbfcd1beb60b2ba2142160e49ca081008eacade5 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Mon, 9 Sep 2024 20:53:07 +0100 Subject: [PATCH] Allow adding multiple uris to CSP builder `AddFrameAncestors()` (#179) `AddFrameAncestors()` derives from `CspDirectiveBuilderBase` rather than `CspDirectiveBuilder`, so the normal extensions don't apply Fixes #178 --- .../FrameAncestorsDirectiveBuilder.cs | 20 +++++++++++++++++++ .../CspBuilderTests.cs | 4 ++-- ...piTest.PublicApiHasNotChanged.verified.txt | 1 + 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/NetEscapades.AspNetCore.SecurityHeaders/Headers/ContentSecurityPolicy/FrameAncestorsDirectiveBuilder.cs b/src/NetEscapades.AspNetCore.SecurityHeaders/Headers/ContentSecurityPolicy/FrameAncestorsDirectiveBuilder.cs index 864a611..e89878d 100644 --- a/src/NetEscapades.AspNetCore.SecurityHeaders/Headers/ContentSecurityPolicy/FrameAncestorsDirectiveBuilder.cs +++ b/src/NetEscapades.AspNetCore.SecurityHeaders/Headers/ContentSecurityPolicy/FrameAncestorsDirectiveBuilder.cs @@ -106,6 +106,26 @@ public FrameAncestorsDirectiveBuilder From(string uri) return this; } + /// + /// Allow resources from the given . May be any non-empty value. + /// + /// The URIs to allow. + /// The CSP builder for method chaining + public FrameAncestorsDirectiveBuilder From(IEnumerable uris) + { + foreach (var uri in uris) + { + if (string.IsNullOrWhiteSpace(uri)) + { + throw new System.ArgumentException("Uri may not be null or empty", nameof(uri)); + } + + Sources.Add(uri); + } + + return this; + } + /// /// Allow resources served over https /// diff --git a/test/NetEscapades.AspNetCore.SecurityHeaders.Test/CspBuilderTests.cs b/test/NetEscapades.AspNetCore.SecurityHeaders.Test/CspBuilderTests.cs index ea86b36..d67ae1b 100644 --- a/test/NetEscapades.AspNetCore.SecurityHeaders.Test/CspBuilderTests.cs +++ b/test/NetEscapades.AspNetCore.SecurityHeaders.Test/CspBuilderTests.cs @@ -356,11 +356,11 @@ public void Build_AddFrameAncestors_WhenAddsMultipleValue_ReturnsAllValues() .Self() .Blob() .Data() - .From("http://testUrl.com"); + .From(["http://testUrl.com", "https://testUrl.com"]); var result = builder.Build(); - result.ConstantValue.Should().Be("frame-ancestors 'self' blob: data: http://testUrl.com"); + result.ConstantValue.Should().Be("frame-ancestors 'self' blob: data: http://testUrl.com https://testUrl.com"); } [Fact] diff --git a/test/NetEscapades.AspNetCore.SecurityHeaders.Test/PublicApiTest.PublicApiHasNotChanged.verified.txt b/test/NetEscapades.AspNetCore.SecurityHeaders.Test/PublicApiTest.PublicApiHasNotChanged.verified.txt index 3ee0cc7..d7a2b07 100644 --- a/test/NetEscapades.AspNetCore.SecurityHeaders.Test/PublicApiTest.PublicApiHasNotChanged.verified.txt +++ b/test/NetEscapades.AspNetCore.SecurityHeaders.Test/PublicApiTest.PublicApiHasNotChanged.verified.txt @@ -301,6 +301,7 @@ namespace NetEscapades.AspNetCore.SecurityHeaders.Headers.ContentSecurityPolicy public System.Collections.Generic.List Sources { get; } public NetEscapades.AspNetCore.SecurityHeaders.Headers.ContentSecurityPolicy.FrameAncestorsDirectiveBuilder Blob() { } public NetEscapades.AspNetCore.SecurityHeaders.Headers.ContentSecurityPolicy.FrameAncestorsDirectiveBuilder Data() { } + public NetEscapades.AspNetCore.SecurityHeaders.Headers.ContentSecurityPolicy.FrameAncestorsDirectiveBuilder From(System.Collections.Generic.IEnumerable uris) { } public NetEscapades.AspNetCore.SecurityHeaders.Headers.ContentSecurityPolicy.FrameAncestorsDirectiveBuilder From(string uri) { } public NetEscapades.AspNetCore.SecurityHeaders.Headers.ContentSecurityPolicy.FrameAncestorsDirectiveBuilder None() { } public NetEscapades.AspNetCore.SecurityHeaders.Headers.ContentSecurityPolicy.FrameAncestorsDirectiveBuilder OverHttps() { }