Skip to content

Commit 8497420

Browse files
Merge pull request #285 from GeekInTheNorth/hotfix/v3.0.2
Merge HF 3.0.2 into Main
2 parents 321a3f9 + 4a36cfb commit 8497420

40 files changed

Lines changed: 292 additions & 540 deletions

src/Stott.Security.Optimizely.Test/Features/Csp/CspOptimizerTests.cs

Lines changed: 52 additions & 31 deletions
Large diffs are not rendered by default.

src/Stott.Security.Optimizely.Test/Features/Csp/CspServiceTests.cs

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public sealed class CspServiceTests
3737
public void SetUp()
3838
{
3939
_mockReportUrlResolver = new Mock<ICspReportUrlResolver>();
40-
_mockReportUrlResolver.Setup(x => x.GetReportUriPath()).Returns("https://www.example.com/");
40+
_mockReportUrlResolver.Setup(x => x.GetReportToPath()).Returns("https://www.example.com/");
4141

4242
_mockSettingsService = new Mock<ICspSettingsService>();
4343

@@ -213,28 +213,6 @@ public async Task Build_GivenReportingIsConfiguredWithAReportingUrl_ThenReportTo
213213

214214
// Assert
215215
Assert.That(actualHeader.Value.Contains(CspConstants.Directives.ReportTo), Is.True);
216-
Assert.That(actualHeader.Value.Contains(CspConstants.Directives.ReportUri), Is.True);
217-
}
218-
219-
[Test]
220-
public async Task Build_GivenReportingIsConfiguredWithAnExternalReportingUri_ThenReportingAndExternalUrlShouldBePresent()
221-
{
222-
// Arrange
223-
var sources = new List<CspSource>
224-
{
225-
new() { Source = "https://www.example.com", Directives = CspConstants.Directives.DefaultSource }
226-
};
227-
228-
SetupCspSettings(true, false, false, true);
229-
_mockPermissionService.Setup(x => x.GetAsync()).ReturnsAsync(sources);
230-
231-
// Act
232-
var policy = await _cspService.GetCompiledHeaders(null);
233-
var actualHeader = policy.First(x => x.Key == CspConstants.HeaderNames.ContentSecurityPolicy);
234-
235-
// Assert
236-
Assert.That(actualHeader.Value.Contains(CspConstants.Directives.ReportTo), Is.True);
237-
Assert.That(actualHeader.Value.Contains($"{CspConstants.Directives.ReportUri} https://www.example.com"), Is.True);
238216
}
239217

240218
[Test]
@@ -443,8 +421,7 @@ private void SetupCspSettings(bool isEnabled, bool isReportOnly = false, bool us
443421
IsUpgradeInsecureRequestsEnabled = isUpgradeInsecureRequestsEnabled,
444422
UseExternalReporting = useExternalReporting,
445423
UseInternalReporting = useInternalReporting,
446-
ExternalReportToUrl = useExternalReporting ? "https://www.example.com" : string.Empty,
447-
ExternalReportUriUrl = useExternalReporting ? "https://www.example.com" : string.Empty
424+
ExternalReportToUrl = useExternalReporting ? "https://www.example.com" : string.Empty
448425
};
449426

450427
_mockSettingsService.Setup(x => x.GetAsync()).ReturnsAsync(settings);
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using NUnit.Framework;
2+
3+
using Stott.Security.Optimizely.Common;
4+
using Stott.Security.Optimizely.Features.Csp.Dtos;
5+
6+
namespace Stott.Security.Optimizely.Test.Features.Csp.Dtos;
7+
8+
[TestFixture]
9+
public sealed class CspSourceDtoTests
10+
{
11+
[Test]
12+
public void Constructor_ValidSourceAndDirectives_SetsProperties()
13+
{
14+
// Arrange
15+
var source = "https://example.com";
16+
var directives = "script-src, img-src";
17+
18+
// Act
19+
var dto = new CspSourceDto(source, directives);
20+
21+
// Assert
22+
Assert.That(dto.Source, Is.EqualTo(source));
23+
Assert.That(dto.Directives, Has.Count.EqualTo(2));
24+
Assert.That(dto.Directives.Contains(CspConstants.Directives.ScriptSource), Is.True);
25+
Assert.That(dto.Directives.Contains(CspConstants.Directives.ImageSource), Is.True);
26+
}
27+
28+
[Test]
29+
public void Constructor_GivenAnInvalidDirective_TheOnlyTheValidDirectivesAreSet()
30+
{
31+
// Arrange
32+
var source = "https://example.com";
33+
var directives = "script-src, invalid-directive";
34+
35+
// Act
36+
var dto = new CspSourceDto(source, directives);
37+
38+
// Assert
39+
Assert.That(dto.Source, Is.EqualTo(source));
40+
Assert.That(dto.Directives, Has.Count.EqualTo(1));
41+
Assert.That(dto.Directives.Contains(CspConstants.Directives.ScriptSource), Is.True);
42+
}
43+
44+
[Test]
45+
public void Constructor_GivenDirectivesContainInCorrectCasing_ThenCasingWillBeCorrectedWhenSet()
46+
{
47+
// Arrange
48+
var source = "https://example.com";
49+
var directives = "Script-Src, IMG-SRC";
50+
51+
// Act
52+
var dto = new CspSourceDto(source, directives);
53+
54+
// Assert
55+
Assert.That(dto.Source, Is.EqualTo(source));
56+
Assert.That(dto.Directives, Has.Count.EqualTo(2));
57+
Assert.That(dto.Directives.Contains(CspConstants.Directives.ScriptSource), Is.True);
58+
Assert.That(dto.Directives.Contains(CspConstants.Directives.ImageSource), Is.True);
59+
}
60+
}

src/Stott.Security.Optimizely.Test/Features/Csp/Permissions/Save/SavePermissionModelTestCases.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@ public static IEnumerable<TestCaseData> GetValidDirectivesTestCases
125125
yield return new TestCaseData(new List<string> { CspConstants.Directives.ImageSource });
126126
yield return new TestCaseData(new List<string> { CspConstants.Directives.ManifestSource });
127127
yield return new TestCaseData(new List<string> { CspConstants.Directives.MediaSource });
128-
yield return new TestCaseData(new List<string> { CspConstants.Directives.NavigateTo });
129128
yield return new TestCaseData(new List<string> { CspConstants.Directives.ObjectSource });
130129
yield return new TestCaseData(new List<string> { CspConstants.Directives.PreFetchSource });
131130
yield return new TestCaseData(new List<string> { CspConstants.Directives.ScriptSourceAttribute });

src/Stott.Security.Optimizely.Test/Features/Csp/Reporting/CspReportingControllerTests.cs

Lines changed: 0 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -78,78 +78,6 @@ public void SetUp()
7878
};
7979
}
8080

81-
[Test]
82-
[TestCase(false, false)]
83-
[TestCase(false, true)]
84-
[TestCase(true, false)]
85-
public async Task ReportUriViolation_WhenReportingIsNotEnabled_ReturnsAnOkObjectResultWithoutSaving(bool isEnabled, bool useInternalReporting)
86-
{
87-
// Arrange
88-
_mockSettingsService.Setup(x => x.GetAsync())
89-
.ReturnsAsync(new CspSettings { IsEnabled = isEnabled, UseInternalReporting = useInternalReporting });
90-
91-
// Act
92-
var result = await _controller.ReportUriViolation();
93-
94-
// Assert
95-
Assert.That(result, Is.AssignableTo<OkObjectResult>());
96-
97-
_mockReportService.Verify(x => x.SaveAsync(It.IsAny<ICspReport>()), Times.Never());
98-
}
99-
100-
[Test]
101-
public void ReportUriViolation_WhenTheCommandThrowsAnException_ThenTheErrorIsReThrown()
102-
{
103-
// Arrange
104-
var saveModel = JsonConvert.SerializeObject(new ReportUriWrapper { CspReport = new ReportUriBody() });
105-
var testStream = new MemoryStream(Encoding.UTF8.GetBytes(saveModel));
106-
107-
_mockRequest.Setup(x => x.Body).Returns(testStream);
108-
109-
_mockReportService.Setup(x => x.SaveAsync(It.IsAny<ICspReport>()))
110-
.ThrowsAsync(new Exception(string.Empty));
111-
112-
// Assert
113-
Assert.ThrowsAsync<Exception>(() => _controller.ReportUriViolation());
114-
}
115-
116-
[Test]
117-
public async Task ReportUriViolation_WhenTheCommandIsSuccessful_ThenAnOkResponseIsReturned()
118-
{
119-
// Arrange
120-
var saveModel = JsonConvert.SerializeObject(new ReportUriWrapper { CspReport = new ReportUriBody() });
121-
var testStream = new MemoryStream(Encoding.UTF8.GetBytes(saveModel));
122-
123-
_mockRequest.Setup(x => x.Body).Returns(testStream);
124-
125-
// Act
126-
var response = await _controller.ReportUriViolation();
127-
128-
// Assert
129-
Assert.That(response, Is.AssignableFrom<OkResult>());
130-
}
131-
132-
[Test]
133-
[TestCase(true, 1)]
134-
[TestCase(false, 0)]
135-
public async Task ReportUriViolation_AddsViolationToTheCspWhenItIsOnTheAllowList(bool isOnAllowList, int expectedUpdatesToCsp)
136-
{
137-
// Arrange
138-
var saveModel = JsonConvert.SerializeObject(new ReportUriWrapper { CspReport = new ReportUriBody() });
139-
var testStream = new MemoryStream(Encoding.UTF8.GetBytes(saveModel));
140-
141-
_mockRequest.Setup(x => x.Body).Returns(testStream);
142-
143-
_mockAllowListService.Setup(x => x.IsOnAllowListAsync(It.IsAny<string>(), It.IsAny<string>()))
144-
.ReturnsAsync(isOnAllowList);
145-
146-
// Act
147-
await _controller.ReportUriViolation();
148-
149-
// Assert
150-
_mockAllowListService.Verify(x => x.AddFromAllowListToCspAsync(It.IsAny<string>(), It.IsAny<string>()), Times.Exactly(expectedUpdatesToCsp));
151-
}
152-
15381
[Test]
15482
[TestCase(false, false)]
15583
[TestCase(false, true)]

src/Stott.Security.Optimizely.Test/Features/Csp/Reporting/Models/ReportUriBodyTests.cs

Lines changed: 0 additions & 65 deletions
This file was deleted.

src/Stott.Security.Optimizely.Test/Features/Csp/Reporting/ViolationReportSummaryTestCases.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ public static IEnumerable<TestCaseData> DirectiveSuggestionTestCases
8787
yield return new TestCaseData(CspConstants.Directives.ImageSource, new List<string> { CspConstants.Directives.ImageSource });
8888
yield return new TestCaseData(CspConstants.Directives.ManifestSource, new List<string> { CspConstants.Directives.ManifestSource });
8989
yield return new TestCaseData(CspConstants.Directives.MediaSource, new List<string> { CspConstants.Directives.MediaSource });
90-
yield return new TestCaseData(CspConstants.Directives.NavigateTo, new List<string> { CspConstants.Directives.NavigateTo });
9190
yield return new TestCaseData(CspConstants.Directives.ObjectSource, new List<string> { CspConstants.Directives.ObjectSource });
9291
yield return new TestCaseData(CspConstants.Directives.PreFetchSource, new List<string> { CspConstants.Directives.PreFetchSource });
9392
yield return new TestCaseData(CspConstants.Directives.ScriptSourceAttribute, new List<string> { CspConstants.Directives.ScriptSourceAttribute, CspConstants.Directives.ScriptSource });

src/Stott.Security.Optimizely.Test/Features/Tools/MigrationRepositoryDataTests.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,7 @@ public async Task GivenSettingsDoesContainACsp_AndTheDataRecordDoesNotExist_Then
9292
IsStrictDynamicEnabled = true,
9393
UseInternalReporting = true,
9494
UseExternalReporting = true,
95-
ExternalReportToUrl = "https://www.example.com/two/",
96-
ExternalReportUriUrl = "https://www.example.com/three/"
95+
ExternalReportToUrl = "https://www.example.com/two/"
9796
}
9897
};
9998

@@ -114,7 +113,6 @@ public async Task GivenSettingsDoesContainACsp_AndTheDataRecordDoesNotExist_Then
114113
Assert.That(updatedRecord.UseInternalReporting, Is.EqualTo(settings.Csp.UseInternalReporting));
115114
Assert.That(updatedRecord.UseExternalReporting, Is.EqualTo(settings.Csp.UseExternalReporting));
116115
Assert.That(updatedRecord.ExternalReportToUrl, Is.EqualTo(settings.Csp.ExternalReportToUrl));
117-
Assert.That(updatedRecord.ExternalReportUriUrl, Is.EqualTo(settings.Csp.ExternalReportUriUrl));
118116
}
119117

120118
[Test]
@@ -134,8 +132,7 @@ public async Task GivenSettingsDoesContainACsp_AndTheDataRecordDoesExist_ThenARe
134132
IsStrictDynamicEnabled = true,
135133
UseInternalReporting = true,
136134
UseExternalReporting = true,
137-
ExternalReportToUrl = "https://www.example.com/two/",
138-
ExternalReportUriUrl = "https://www.example.com/three/"
135+
ExternalReportToUrl = "https://www.example.com/two/"
139136
}
140137
};
141138

@@ -164,7 +161,6 @@ public async Task GivenSettingsDoesContainACsp_AndTheDataRecordDoesExist_ThenARe
164161
Assert.That(updatedRecord.UseInternalReporting, Is.EqualTo(settings.Csp.UseInternalReporting));
165162
Assert.That(updatedRecord.UseExternalReporting, Is.EqualTo(settings.Csp.UseExternalReporting));
166163
Assert.That(updatedRecord.ExternalReportToUrl, Is.EqualTo(settings.Csp.ExternalReportToUrl));
167-
Assert.That(updatedRecord.ExternalReportUriUrl, Is.EqualTo(settings.Csp.ExternalReportUriUrl));
168164
}
169165

170166
[Test]

src/Stott.Security.Optimizely/Common/CspConstants.cs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ public static class CspConstants
2020

2121
public const int TwoYearsInSeconds = 63072000;
2222

23-
public const int MaxHeaderSize = 8192;
23+
public const int SplitThreshold = 8000;
24+
25+
public const int SimplifyThreshold = 12000;
26+
27+
public const int TerminalThreshold = 15500;
2428

2529
/// <summary>
2630
/// A collection of directives which can take URL style sources.
@@ -38,7 +42,6 @@ public static class CspConstants
3842
Directives.ImageSource,
3943
Directives.ManifestSource,
4044
Directives.MediaSource,
41-
Directives.NavigateTo,
4245
Directives.ObjectSource,
4346
Directives.PreFetchSource,
4447
Directives.ScriptSourceAttribute,
@@ -136,14 +139,10 @@ public static class Directives
136139

137140
public const string MediaSource = "media-src";
138141

139-
public const string NavigateTo = "navigate-to";
140-
141142
public const string ObjectSource = "object-src";
142143

143144
public const string PreFetchSource = "prefetch-src";
144145

145-
// public const string RequireTrustedTypes = "require-trusted-types-for";
146-
147146
public const string Sandbox = "sandbox";
148147

149148
public const string ScriptSourceAttribute = "script-src-attr";
@@ -158,13 +157,9 @@ public static class Directives
158157

159158
public const string StyleSource = "style-src";
160159

161-
// public const string TrustedTypes = "trusted-types";
162-
163160
public const string UpgradeInsecureRequests = "upgrade-insecure-requests";
164161

165162
public const string WorkerSource = "worker-src";
166-
167-
public const string ReportUri = "report-uri";
168163

169164
public const string ReportTo = "report-to";
170165
}

0 commit comments

Comments
 (0)