From 080f6fde2c48ce59ff9dd0f17d1548093eef434b Mon Sep 17 00:00:00 2001 From: MarkStega Date: Fri, 26 Jan 2024 10:46:01 -0500 Subject: [PATCH] 1.2.0 (#28) * 2024-01-25 Spelling changes * 2024-01-25 actions/checkout * 2024-01-25 EoD * 2024-01-26 1.2.0 * Mitigate all warnings in the build --- .github/workflows/GithubActionsRelease.yml | 5 +- .github/workflows/GithubActionsWIP.yml | 5 +- .../HttpSecurity.AspNet.csproj | 8 +-- .../Services/HttpSecurityOptions.cs | 2 +- .../Services/HttpSecurityService.cs | 2 +- .../Services/IHttpSecurityService.cs | 2 +- HttpSecurity.Example/Data/WeatherForecast.cs | 12 ---- .../Data/WeatherForecastService.cs | 19 ------ .../HttpSecurity.Example.csproj | 4 +- HttpSecurity.Example/Pages/Counter.razor | 18 ------ ...dex.razor => DisplaySecurityHeaders.razor} | 2 +- HttpSecurity.Example/Pages/FetchData.razor | 48 -------------- HttpSecurity.Example/Pages/_Host.cshtml | 6 +- HttpSecurity.Example/Program.cs | 30 +++++++-- .../Properties/launchSettings.json | 24 ++----- HttpSecurity.Example/Shared/MainLayout.razor | 12 +--- HttpSecurity.Example/Shared/NavMenu.razor | 39 ------------ HttpSecurity.Example/Shared/NavMenu.razor.css | 62 ------------------- .../Shared/SurveyPrompt.razor | 16 ----- README.md | 2 + ReleaseNotes.md | 21 ++++++- SourceGenerator/SourceGenerator.cs | 2 +- SourceGenerator/SourceGenerator.csproj | 5 +- 23 files changed, 71 insertions(+), 275 deletions(-) delete mode 100644 HttpSecurity.Example/Data/WeatherForecast.cs delete mode 100644 HttpSecurity.Example/Data/WeatherForecastService.cs delete mode 100644 HttpSecurity.Example/Pages/Counter.razor rename HttpSecurity.Example/Pages/{Index.razor => DisplaySecurityHeaders.razor} (97%) delete mode 100644 HttpSecurity.Example/Pages/FetchData.razor delete mode 100644 HttpSecurity.Example/Shared/NavMenu.razor delete mode 100644 HttpSecurity.Example/Shared/NavMenu.razor.css delete mode 100644 HttpSecurity.Example/Shared/SurveyPrompt.razor diff --git a/.github/workflows/GithubActionsRelease.yml b/.github/workflows/GithubActionsRelease.yml index 9509143..5aaeed7 100644 --- a/.github/workflows/GithubActionsRelease.yml +++ b/.github/workflows/GithubActionsRelease.yml @@ -55,15 +55,14 @@ jobs: shell: bash - name: Checkout repository under $GITHUB_WORKSPACE so the job can access it 🛎️ - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: persist-credentials: false - name: Use dotnet uses: actions/setup-dotnet@v3 with: - dotnet-version: '7.0.x' - include-prerelease: true + dotnet-version: '8.x' - name: Build HttpSecurity.AspNet 🔧 run: dotnet build ${{env.projectCSFB}} --configuration ${{env.buildConfiguration}} -p:Version=${{env.version}} diff --git a/.github/workflows/GithubActionsWIP.yml b/.github/workflows/GithubActionsWIP.yml index 15ee9d2..b87097a 100644 --- a/.github/workflows/GithubActionsWIP.yml +++ b/.github/workflows/GithubActionsWIP.yml @@ -50,15 +50,14 @@ jobs: shell: bash - name: Checkout repository under $GITHUB_WORKSPACE so the job can access it 🛎️ - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: persist-credentials: false - name: Use dotnet uses: actions/setup-dotnet@v3 with: - dotnet-version: '7.0.x' - include-prerelease: true + dotnet-version: '8.x' - name: Build HttpSecurity.AspNet 🔧 run: dotnet build ${{env.projectCSFB}} --configuration ${{env.buildConfiguration}} --version-suffix ${{env.ciSuffix}} diff --git a/HttpSecurity.AspNet/HttpSecurity.AspNet.csproj b/HttpSecurity.AspNet/HttpSecurity.AspNet.csproj index a0cbdcb..c627e7c 100644 --- a/HttpSecurity.AspNet/HttpSecurity.AspNet.csproj +++ b/HttpSecurity.AspNet/HttpSecurity.AspNet.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 11 enable enable @@ -10,10 +10,8 @@ - - - - + + diff --git a/HttpSecurity.AspNet/Services/HttpSecurityOptions.cs b/HttpSecurity.AspNet/Services/HttpSecurityOptions.cs index 6fdb791..09b88de 100644 --- a/HttpSecurity.AspNet/Services/HttpSecurityOptions.cs +++ b/HttpSecurity.AspNet/Services/HttpSecurityOptions.cs @@ -14,7 +14,7 @@ public sealed class HttpSecurityOptions /// /// The built content security policy. /// - internal ContentSecurityPolicyOptions ContentSecurityPolicy { get; set; } = null; + internal ContentSecurityPolicyOptions? ContentSecurityPolicy { get; set; } = null; /// diff --git a/HttpSecurity.AspNet/Services/HttpSecurityService.cs b/HttpSecurity.AspNet/Services/HttpSecurityService.cs index 21e5862..71f726d 100644 --- a/HttpSecurity.AspNet/Services/HttpSecurityService.cs +++ b/HttpSecurity.AspNet/Services/HttpSecurityService.cs @@ -68,7 +68,7 @@ public string GetFileHashString(string fileName) /// - string IHttpSecurityService.GetCSPHashesSubsting(StaticFileExtension staticFileExtension) + string IHttpSecurityService.GetCSPHashesSubstring(StaticFileExtension staticFileExtension) { return _fileHashDataset.GetCSPSubstring(staticFileExtension); } diff --git a/HttpSecurity.AspNet/Services/IHttpSecurityService.cs b/HttpSecurity.AspNet/Services/IHttpSecurityService.cs index 97f1282..f9191d8 100644 --- a/HttpSecurity.AspNet/Services/IHttpSecurityService.cs +++ b/HttpSecurity.AspNet/Services/IHttpSecurityService.cs @@ -50,5 +50,5 @@ public interface IHttpSecurityService /// /// /// - internal string GetCSPHashesSubsting(StaticFileExtension staticFileExtension); + internal string GetCSPHashesSubstring(StaticFileExtension staticFileExtension); } diff --git a/HttpSecurity.Example/Data/WeatherForecast.cs b/HttpSecurity.Example/Data/WeatherForecast.cs deleted file mode 100644 index a5df450..0000000 --- a/HttpSecurity.Example/Data/WeatherForecast.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace HttpSecurity.Example.Data; - -public class WeatherForecast -{ - public DateTime Date { get; set; } - - public int TemperatureC { get; set; } - - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); - - public string? Summary { get; set; } -} diff --git a/HttpSecurity.Example/Data/WeatherForecastService.cs b/HttpSecurity.Example/Data/WeatherForecastService.cs deleted file mode 100644 index 06aacde..0000000 --- a/HttpSecurity.Example/Data/WeatherForecastService.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace HttpSecurity.Example.Data; - -public class WeatherForecastService -{ - private static readonly string[] Summaries = new[] - { - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" - }; - - public Task GetForecastAsync(DateTime startDate) - { - return Task.FromResult(Enumerable.Range(1, 5).Select(index => new WeatherForecast - { - Date = startDate.AddDays(index), - TemperatureC = Random.Shared.Next(-20, 55), - Summary = Summaries[Random.Shared.Next(Summaries.Length)] - }).ToArray()); - } -} diff --git a/HttpSecurity.Example/HttpSecurity.Example.csproj b/HttpSecurity.Example/HttpSecurity.Example.csproj index a2c446e..965ef17 100644 --- a/HttpSecurity.Example/HttpSecurity.Example.csproj +++ b/HttpSecurity.Example/HttpSecurity.Example.csproj @@ -1,7 +1,7 @@ - + - net7.0 + net8.0 enable enable diff --git a/HttpSecurity.Example/Pages/Counter.razor b/HttpSecurity.Example/Pages/Counter.razor deleted file mode 100644 index ef23cb3..0000000 --- a/HttpSecurity.Example/Pages/Counter.razor +++ /dev/null @@ -1,18 +0,0 @@ -@page "/counter" - -Counter - -

Counter

- -

Current count: @currentCount

- - - -@code { - private int currentCount = 0; - - private void IncrementCount() - { - currentCount++; - } -} diff --git a/HttpSecurity.Example/Pages/Index.razor b/HttpSecurity.Example/Pages/DisplaySecurityHeaders.razor similarity index 97% rename from HttpSecurity.Example/Pages/Index.razor rename to HttpSecurity.Example/Pages/DisplaySecurityHeaders.razor index 3d1c386..cb8c82a 100644 --- a/HttpSecurity.Example/Pages/Index.razor +++ b/HttpSecurity.Example/Pages/DisplaySecurityHeaders.razor @@ -3,7 +3,7 @@ @inject IHttpSecurityService HttpSecurityService @inject IHttpContextAccessor HttpContextAccessor; -Index +Display Security Headers

Http Security Headers

diff --git a/HttpSecurity.Example/Pages/FetchData.razor b/HttpSecurity.Example/Pages/FetchData.razor deleted file mode 100644 index d721c62..0000000 --- a/HttpSecurity.Example/Pages/FetchData.razor +++ /dev/null @@ -1,48 +0,0 @@ -@page "/fetchdata" - -Weather forecast - -@using HttpSecurity.Example.Data -@inject WeatherForecastService ForecastService - -

Weather forecast

- -

This component demonstrates fetching data from a service.

- -@if (forecasts == null) -{ -

Loading...

-} -else -{ - - - - - - - - - - - @foreach (var forecast in forecasts) - { - - - - - - - } - -
DateTemp. (C)Temp. (F)Summary
@forecast.Date.ToShortDateString()@forecast.TemperatureC@forecast.TemperatureF@forecast.Summary
-} - -@code { - private WeatherForecast[]? forecasts; - - protected override async Task OnInitializedAsync() - { - forecasts = await ForecastService.GetForecastAsync(DateTime.Now); - } -} diff --git a/HttpSecurity.Example/Pages/_Host.cshtml b/HttpSecurity.Example/Pages/_Host.cshtml index 9a7e2a4..f5755a1 100644 --- a/HttpSecurity.Example/Pages/_Host.cshtml +++ b/HttpSecurity.Example/Pages/_Host.cshtml @@ -12,14 +12,14 @@ - + @* *@ - + - +
diff --git a/HttpSecurity.Example/Program.cs b/HttpSecurity.Example/Program.cs index eaddede..993d894 100644 --- a/HttpSecurity.Example/Program.cs +++ b/HttpSecurity.Example/Program.cs @@ -1,5 +1,4 @@ using HttpSecurity.AspNet; -using HttpSecurity.Example.Data; using System.Globalization; var builder = WebApplication.CreateBuilder(args); @@ -8,7 +7,6 @@ builder.Services.AddHttpContextAccessor(); builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(); -builder.Services.AddSingleton(); builder.Services.AddHttpsSecurityHeaders(options => { @@ -17,50 +15,70 @@ { cspOptions .AddBaseUri(o => o.AddSelf()) + .AddBlockAllMixedContent() + .AddChildSrc(o => o.AddSelf()) + .AddConnectSrc(o => o .AddSelf() .AddUri((baseUri, baseDomain) => $"wss://{baseDomain}:*")) + // The generated hashes do nothing here, and we include it here only to show that generated hash values can be added to policies - script-src would generally be the policy where you use this technique. .AddDefaultSrc(o => o .AddSelf() .AddStrictDynamicIf(() => !builder.Environment.IsDevelopment()) .AddUnsafeInline() .AddGeneratedHashValues(StaticFileExtension.CSS)) + .AddFontSrc(o => o.AddSelf()) + .AddFrameAncestors(o => o.AddNone()) + .AddFrameSrc(o => o.AddSelf()) + .AddFormAction(o => o.AddNone()) + .AddImgSrc(o => o .AddSelf() .AddUri("www.google-analytics.com") .AddUri("*.openstreetmap.org") .AddSchemeSource(SchemeSource.Data, "w3.org/svg/2000")) + .AddManifestSrc(o => o.AddSelf()) + .AddMediaSrc(o => o.AddSelf()) + .AddObjectSrc(o => o.AddNone()) + .AddReportUri(o => o.AddUri((baseUri, baseDomain) => $"https://{baseUri}/api/CspReporting/UriReport")) + .AddScriptSrc(o => o .AddSelf() .AddNonce() .AddHashValue(HashAlgorithm.SHA256, "v8v3RKRPmN4odZ1CWM5gw80QKPCCWMcpNeOmimNL2AA=") - .AddUriIf((baseUri, baseDomain) => $"https://{baseUri}/_framework/aspnetcore-browser-refresh.js", () => builder.Environment.IsDevelopment()) - .AddStrictDynamicIf(() => !builder.Environment.IsDevelopment()) - .AddUnsafeInline().AddReportSample().AddUnsafeEval().AddUri("https://www.googletagmanager.com/gtag/js") + // StrictDynamic works on Chromium browsers but fails for both Firefox and Safari + //.AddStrictDynamicIf(() => !builder.Environment.IsDevelopment()) + .AddReportSample() + .AddUri("https://www.googletagmanager.com/gtag/js") + .AddUri((baseUri, baseDomain) => $"https://{baseUri}/_framework/aspnetcore-browser-refresh.js") + .AddUri((baseUri, baseDomain) => $"https://{baseUri}/_framework/blazor.server.js") .AddGeneratedHashValues(StaticFileExtension.JS)) + .AddStyleSrc(o => o .AddSelf() .AddUnsafeInline() .AddUnsafeHashes() .AddReportSample()) + .AddUpgradeInsecureRequests() + .AddWorkerSrc(o => o.AddSelf()); }) .AddReferrerPolicy(ReferrerPolicyDirective.NoReferrer) .AddPermissionsPolicy("accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()") .AddStrictTransportSecurity(31536000, true) - .AddXClientId("Material.Blazor") + .AddXClientId("HttpSecurity.Example") .AddXContentTypeOptionsNoSniff() .AddXFrameOptionsDirective(XFrameOptionsDirective.Deny) .AddXXssProtectionDirective(XXssProtectionDirective.OneModeBlock) diff --git a/HttpSecurity.Example/Properties/launchSettings.json b/HttpSecurity.Example/Properties/launchSettings.json index 8350f27..b7eca4f 100644 --- a/HttpSecurity.Example/Properties/launchSettings.json +++ b/HttpSecurity.Example/Properties/launchSettings.json @@ -1,28 +1,14 @@ { - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:10639", - "sslPort": 44398 - } - }, "profiles": { "HttpSecurity.Example": { "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "applicationUrl": "https://localhost:7256;http://localhost:5080", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "IIS Express": { - "commandName": "IISExpress", "launchBrowser": true, "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "hotReloadEnabled": false, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:50083", } } -} +} \ No newline at end of file diff --git a/HttpSecurity.Example/Shared/MainLayout.razor b/HttpSecurity.Example/Shared/MainLayout.razor index 8ba2196..28c6778 100644 --- a/HttpSecurity.Example/Shared/MainLayout.razor +++ b/HttpSecurity.Example/Shared/MainLayout.razor @@ -3,17 +3,9 @@ HttpSecurity Example
- - -
-
- About -
- +
- @Body +
diff --git a/HttpSecurity.Example/Shared/NavMenu.razor b/HttpSecurity.Example/Shared/NavMenu.razor deleted file mode 100644 index 689213d..0000000 --- a/HttpSecurity.Example/Shared/NavMenu.razor +++ /dev/null @@ -1,39 +0,0 @@ - - -
- -
- -@code { - private bool collapseNavMenu = true; - - private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null; - - private void ToggleNavMenu() - { - collapseNavMenu = !collapseNavMenu; - } -} diff --git a/HttpSecurity.Example/Shared/NavMenu.razor.css b/HttpSecurity.Example/Shared/NavMenu.razor.css deleted file mode 100644 index acc5f9f..0000000 --- a/HttpSecurity.Example/Shared/NavMenu.razor.css +++ /dev/null @@ -1,62 +0,0 @@ -.navbar-toggler { - background-color: rgba(255, 255, 255, 0.1); -} - -.top-row { - height: 3.5rem; - background-color: rgba(0,0,0,0.4); -} - -.navbar-brand { - font-size: 1.1rem; -} - -.oi { - width: 2rem; - font-size: 1.1rem; - vertical-align: text-top; - top: -2px; -} - -.nav-item { - font-size: 0.9rem; - padding-bottom: 0.5rem; -} - - .nav-item:first-of-type { - padding-top: 1rem; - } - - .nav-item:last-of-type { - padding-bottom: 1rem; - } - - .nav-item ::deep a { - color: #d7d7d7; - border-radius: 4px; - height: 3rem; - display: flex; - align-items: center; - line-height: 3rem; - } - -.nav-item ::deep a.active { - background-color: rgba(255,255,255,0.25); - color: white; -} - -.nav-item ::deep a:hover { - background-color: rgba(255,255,255,0.1); - color: white; -} - -@media (min-width: 641px) { - .navbar-toggler { - display: none; - } - - .collapse { - /* Never collapse the sidebar for wide screens */ - display: block; - } -} diff --git a/HttpSecurity.Example/Shared/SurveyPrompt.razor b/HttpSecurity.Example/Shared/SurveyPrompt.razor deleted file mode 100644 index e3e6429..0000000 --- a/HttpSecurity.Example/Shared/SurveyPrompt.razor +++ /dev/null @@ -1,16 +0,0 @@ -
- - @Title - - - Please take our - brief survey - - and tell us what you think. -
- -@code { - // Demonstrates how a parent component can supply parameters - [Parameter] - public string? Title { get; set; } -} diff --git a/README.md b/README.md index 0ecb55b..c2f4f53 100644 --- a/README.md +++ b/README.md @@ -55,3 +55,5 @@ By default CompressedStaticFiles is configured to allow slightly larger files fo ## Example An example can be found in the [Example](https://github.com/material-blazor/HttpSecurity.AspNet/tree/main/HttpSecurity.Example) directory. + +If you are running with a cloned repository you can remove the comment in _host.cshtml around "link rel='stylesheet' href='https://a.com/a.css'" to cause a security violation. diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 977edb1..65b4424 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -4,6 +4,21 @@ title: ReleaseNotes --- # Release Notes +#### [1.2.0](https://github.com/Material-Blazor/HttpSecurity.AspNet/tree/1.2.0) + +Released 2024-01-27 + +**Updates** +- Removed deprecated NuGet packages. + +**Breaking Changes** + +- Moved from .Net 7 to .Net 8 + +**Known issues** + +
+ #### [1.1.0](https://github.com/Material-Blazor/HttpSecurity.AspNet/tree/1.1.0) Released 2023-06-07 @@ -24,11 +39,11 @@ Released 2023-01-19 **Updates** -Removed AddAccessControlAllowOrigin*() headers. +- Removed AddAccessControlAllowOrigin*() headers. **Breaking Changes** -Moved from .Net 6 to .Net 7 +- Moved from .Net 6 to .Net 7 **Known issues** @@ -40,7 +55,7 @@ Released 2022-11-03 **Updates** -Added ReferenceOutputAssembly="false" to the project reference for the source generator. This prevents a nuget packaging error that makes nuget believe that there is a missing reference. +- Added ReferenceOutputAssembly="false" to the project reference for the source generator. This prevents a nuget packaging error that makes nuget believe that there is a missing reference. **Breaking Changes** diff --git a/SourceGenerator/SourceGenerator.cs b/SourceGenerator/SourceGenerator.cs index 98dd8bb..e86a841 100644 --- a/SourceGenerator/SourceGenerator.cs +++ b/SourceGenerator/SourceGenerator.cs @@ -406,7 +406,7 @@ private bool ProcessHashValuePolicyOptionsAttribute(INamedTypeSymbol classSymbol sb.AppendLinesIndented(2, ""); sb.AppendLinesIndented(2, "foreach (var extension in StaticFileExtensions)"); sb.AppendLinesIndented(2, "{"); - sb.AppendLinesIndented(3, "result += httpSecurityService.GetCSPHashesSubsting(extension);"); + sb.AppendLinesIndented(3, "result += httpSecurityService.GetCSPHashesSubstring(extension);"); sb.AppendLinesIndented(2, "}"); sb.AppendLinesIndented(2, ""); sb.AppendLinesIndented(2, "return result;"); diff --git a/SourceGenerator/SourceGenerator.csproj b/SourceGenerator/SourceGenerator.csproj index 1d981c3..def7e04 100644 --- a/SourceGenerator/SourceGenerator.csproj +++ b/SourceGenerator/SourceGenerator.csproj @@ -4,6 +4,8 @@ netstandard2.0 11 + true + @@ -15,8 +17,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - +