Problem Statement
SafeWebCore path policies currently replace the entire global configuration object when a path match occurs.
This behavior is non-obvious and creates a security footgun: users may assume a path-specific policy only overrides the settings they explicitly configure, while in reality all unspecified values silently fall back to library defaults.
This can unintentionally weaken security headers on specific endpoints.
Current Behavior
`options.HstsValue = "max-age=63072000; includeSubDomains; preload";
options.PathPolicy("/api", api =>
{
api.XFrameOptions = "DENY";
});`
A developer might reasonably expect /api to inherit the global HSTS configuration and only override X-Frame-Options.
Instead, the /api policy receives a fresh configuration object. Any values not explicitly redefined fall back to SafeWebCore defaults.
As a result:
Strict-Transport-Security: max-age=31536000
may be emitted on /api instead of the globally configured:
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
Security Impact
This can lead to unintentional header downgrades.
A concrete example is HSTS:
HSTS is host-scoped.
Browsers continuously update the remembered HSTS policy from received responses.
If a path policy emits a weaker Strict-Transport-Security header than the rest of the application, browsers may update the stored policy to the weaker value.
Developers may therefore weaken effective domain-wide HSTS protection without realizing it.
The same risk applies to other security-related settings when teams assume inheritance semantics.
Why This Is Surprising
Most configuration systems follow one of these patterns:
Override only explicitly specified values.
Support inheritance from a base policy.
Offer a merge mechanism between global and path-specific configuration.
SafeWebCore currently appears to do neither.
Because ApplyPreset(...) is internal and there is no public inheritance mechanism, consumers must manually duplicate all desired settings in every path policy.
This is error-prone and difficult to maintain.
Proposed Solution
Suggested Improvements
Option 1: Merge with global configuration
Have path policies start from a clone of the global configuration and allow overriding specific settings.
options.PathPolicy("/api", api => { api.ContentSecurityPolicy = null; });
Everything else would inherit automatically.
Option 2: Public inheritance API
Expose something like:
options.PathPolicy("/api", api => { api.ApplyPreset(options); });
or
options.PathPolicy("/api", api => { api.InheritGlobal(); });
before applying overrides
Option 3: Documentation
At minimum, document prominently that:
Path policies replace the global configuration completely and do not inherit or merge settings.
This should be highlighted in both documentation and examples because it is not the behavior many users will expect.
Reproduction
Configure a custom global HSTS value.
Configure a path policy that only changes a single setting.
Request a matching endpoint.
Observe that unspecified settings revert to SafeWebCore defaults rather than inheriting the global configuration.
Expected Behavior
Path policies should either:
inherit from the global policy by default, or
expose an official inheritance/merge mechanism, or
clearly document that replacement semantics are used.
Additional Context
Verified against SafeWebCore 1.6.0 using reflection and live endpoint testing.
The behavior is currently worked around by maintaining a custom helper that manually copies all desired settings into every path-specific policy. This avoids accidental security regressions but introduces configuration duplication and maintenance overhead.
Alternatives Considered
No response
Problem Statement
SafeWebCore path policies currently replace the entire global configuration object when a path match occurs.
This behavior is non-obvious and creates a security footgun: users may assume a path-specific policy only overrides the settings they explicitly configure, while in reality all unspecified values silently fall back to library defaults.
This can unintentionally weaken security headers on specific endpoints.
Current Behavior
`options.HstsValue = "max-age=63072000; includeSubDomains; preload";
options.PathPolicy("/api", api =>
{
api.XFrameOptions = "DENY";
});`
A developer might reasonably expect /api to inherit the global HSTS configuration and only override X-Frame-Options.
Instead, the /api policy receives a fresh configuration object. Any values not explicitly redefined fall back to SafeWebCore defaults.
As a result:
Strict-Transport-Security: max-age=31536000may be emitted on /api instead of the globally configured:
Strict-Transport-Security: max-age=63072000; includeSubDomains; preloadSecurity Impact
This can lead to unintentional header downgrades.
A concrete example is HSTS:
HSTS is host-scoped.
Browsers continuously update the remembered HSTS policy from received responses.
If a path policy emits a weaker Strict-Transport-Security header than the rest of the application, browsers may update the stored policy to the weaker value.
Developers may therefore weaken effective domain-wide HSTS protection without realizing it.
The same risk applies to other security-related settings when teams assume inheritance semantics.
Why This Is Surprising
Most configuration systems follow one of these patterns:
Override only explicitly specified values.
Support inheritance from a base policy.
Offer a merge mechanism between global and path-specific configuration.
SafeWebCore currently appears to do neither.
Because ApplyPreset(...) is internal and there is no public inheritance mechanism, consumers must manually duplicate all desired settings in every path policy.
This is error-prone and difficult to maintain.
Proposed Solution
Suggested Improvements
Option 1: Merge with global configuration
Have path policies start from a clone of the global configuration and allow overriding specific settings.
options.PathPolicy("/api", api => { api.ContentSecurityPolicy = null; });Everything else would inherit automatically.
Option 2: Public inheritance API
Expose something like:
options.PathPolicy("/api", api => { api.ApplyPreset(options); });or
options.PathPolicy("/api", api => { api.InheritGlobal(); });before applying overrides
Option 3: Documentation
At minimum, document prominently that:
Path policies replace the global configuration completely and do not inherit or merge settings.
This should be highlighted in both documentation and examples because it is not the behavior many users will expect.
Reproduction
Configure a custom global HSTS value.
Configure a path policy that only changes a single setting.
Request a matching endpoint.
Observe that unspecified settings revert to SafeWebCore defaults rather than inheriting the global configuration.
Expected Behavior
Path policies should either:
inherit from the global policy by default, or
expose an official inheritance/merge mechanism, or
clearly document that replacement semantics are used.
Additional Context
Verified against SafeWebCore 1.6.0 using reflection and live endpoint testing.
The behavior is currently worked around by maintaining a custom helper that manually copies all desired settings into every path-specific policy. This avoids accidental security regressions but introduces configuration duplication and maintenance overhead.
Alternatives Considered
No response