Add optional Minimal API security defaults - #836
Conversation
Co-authored-by: AndreaCuneo <5227688+AndreaCuneo@users.noreply.github.com>
Co-authored-by: AndreaCuneo <5227688+AndreaCuneo@users.noreply.github.com>
Co-authored-by: AndreaCuneo <5227688+AndreaCuneo@users.noreply.github.com>
Co-authored-by: AndreaCuneo <5227688+AndreaCuneo@users.noreply.github.com>
Co-authored-by: AndreaCuneo <5227688+AndreaCuneo@users.noreply.github.com>
Co-authored-by: AndreaCuneo <5227688+AndreaCuneo@users.noreply.github.com>
Co-authored-by: AndreaCuneo <5227688+AndreaCuneo@users.noreply.github.com>
Co-authored-by: AndreaCuneo <5227688+AndreaCuneo@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds an opt-in Minimal API “security profile” to Ark.Tools.AspNetCore.MinimalApi, wires it into the mediator sample startup sequence, and documents the recommended registration/middleware ordering. Also introduces a TestServer test and updates lockfiles for the new dependency.
Changes:
- Add
AddArkMinimalApiSecurity()/UseArkMinimalApiSecurity()extensions backed byNetEscapades.AspNetCore.SecurityHeaders+ HSTS. - Apply the new middleware early in the mediator sample pipeline and document the intended ordering.
- Add a MinimalApi TestServer test and update relevant
packages.lock.jsonfiles.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Ark.Tools.AspNetCore.MinimalApi.Tests/packages.lock.json | Adds the transitive lock entry for the new security headers dependency in tests. |
| tests/Ark.Tools.AspNetCore.MinimalApi.Tests/ArkMinimalApiSecurityTests.cs | Adds TestServer coverage for security headers (currently missing an HSTS assertion). |
| src/aspnetcore/Ark.Tools.AspNetCore.MinimalApi/packages.lock.json | Locks the new direct dependency for the MinimalApi package. |
| src/aspnetcore/Ark.Tools.AspNetCore.MinimalApi/ArkMinimalApiSecurityExtensions.cs | Introduces the new opt-in security profile extensions (contains a compile issue + policy selector mismatch). |
| src/aspnetcore/Ark.Tools.AspNetCore.MinimalApi/Ark.Tools.AspNetCore.MinimalApi.csproj | Adds NetEscapades.AspNetCore.SecurityHeaders package reference. |
| samples/Ark.MediatorFramework.Sample/test/Ark.MediatorFramework.Sample.Tests/packages.lock.json | Updates sample test lockfile for the new transitive dependency. |
| samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.WebInterface/SampleStartup.cs | Applies the new security profile in the sample service registration and middleware ordering. |
| samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.WebInterface/packages.lock.json | Updates sample web lockfile for the new transitive dependency. |
| docs/mediator-framework/guide/host-setup-and-composition.md | Documents registration and updated middleware ordering including the new security profile. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Andrea Cuneo <kaildio@gmail.com>
AndreaCuneo
left a comment
There was a problem hiding this comment.
also integrate master and ensure build and tests success @copilot
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.
Suppressed comments (4)
src/aspnetcore/Ark.Tools.AspNetCore.MinimalApi/ArkMinimalApiSecurityExtensions.cs:40
- The "Swagger" policy is registered but never selected: for /swagger and /openapi paths the selector always returns the "Scalar" policy, so the "Swagger" policy is dead code (and any future divergence between the two policies would silently not apply).
if (path.StartsWithSegments("/scalar", StringComparison.OrdinalIgnoreCase)
|| path.StartsWithSegments("/swagger", StringComparison.OrdinalIgnoreCase)
|| path.StartsWithSegments("/openapi", StringComparison.OrdinalIgnoreCase))
{
return context.ConfiguredPolicies["Scalar"];
}
src/aspnetcore/Ark.Tools.AspNetCore.MinimalApi/ArkMinimalApiSecurityExtensions.cs:6
- This file uses HeaderPolicyCollection but doesn't import the NetEscapades.AspNetCore.SecurityHeaders namespace, which makes the type reference unresolved.
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
src/aspnetcore/Ark.Tools.AspNetCore.MinimalApi/ArkMinimalApiSecurityExtensions.cs:45
- The gRPC reflection selector uses StartsWithSegments("/grpc.reflection"), but reflection endpoints are typically under the first segment "grpc.reflection.v1alpha.ServerReflection". StartsWithSegments requires a segment boundary ('/' or end), so this condition won't match and the reflection policy won't apply.
if (path.StartsWithSegments("/grpc.reflection", StringComparison.OrdinalIgnoreCase))
{
return context.ConfiguredPolicies["GrpcReflection"];
}
src/aspnetcore/Ark.Tools.AspNetCore.MinimalApi/ArkMinimalApiSecurityExtensions.cs:38
- SetPolicySelector introduces path-based branching for Scalar/Swagger/OpenAPI and gRPC reflection responses, but the new tests only verify the default ("/") case. Add coverage for at least one documentation path (e.g. /scalar or /swagger) and a gRPC reflection path to ensure the selector stays correct.
.SetPolicySelector(context =>
{
var path = context.HttpContext.Request.Path;
if (path.StartsWithSegments("/scalar", StringComparison.OrdinalIgnoreCase)
|| path.StartsWithSegments("/swagger", StringComparison.OrdinalIgnoreCase)
|| path.StartsWithSegments("/openapi", StringComparison.OrdinalIgnoreCase))
{
Co-authored-by: AndreaCuneo <5227688+AndreaCuneo@users.noreply.github.com>
…aster Co-authored-by: AndreaCuneo <5227688+AndreaCuneo@users.noreply.github.com>
Merged master into branch (resolved lock file conflicts by regenerating), full solution builds with 0 warnings/errors. Commit: |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.
Suppressed comments (2)
src/aspnetcore/Ark.Tools.AspNetCore.MinimalApi/ArkMinimalApiSecurityExtensions.cs:7
HeaderPolicyCollectionis used but its namespace isn't imported in this file. Unless it's brought in via a global using, this will not compile; add the NetEscapades using (or fully-qualify the type).
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
namespace Ark.Tools.AspNetCore.MinimalApi;
src/aspnetcore/Ark.Tools.AspNetCore.MinimalApi/ArkMinimalApiSecurityExtensions.cs:39
- The policy selector routes
/swaggerand/openapito the "Scalar" policy, leaving the "Swagger" policy unused. Either remove the unused policy or return the "Swagger" policy for those paths to keep the configuration consistent and future-proof.
if (path.StartsWithSegments("/scalar", StringComparison.OrdinalIgnoreCase)
|| path.StartsWithSegments("/swagger", StringComparison.OrdinalIgnoreCase)
|| path.StartsWithSegments("/openapi", StringComparison.OrdinalIgnoreCase))
{
return context.ConfiguredPolicies["Scalar"];
The mediator framework lacked reusable ASP.NET Core Minimal API security-header and HSTS defaults. This task adds an opt-in Ark security profile and applies it to the mediator sample.
Serverheader.