Skip to content

Conversation

sachatrauwaen
Copy link
Contributor

@sachatrauwaen sachatrauwaen commented Oct 3, 2025

Summary

Create a possibility to generate Content security policy (csp) headers .

Content Security Policy is a crucial security standard that helps protect your web applications from various types of attacks, including Cross-Site Scripting (XSS), clickjacking, and other code injection attacks. It works by allowing you to specify which resources (scripts, styles, images, etc.) your browser should be allowed to load.
more info about Content security policy

Description of solution

The intend is to manage CSP for WebForms and MVC pipeline.

  • Webforms can not be very struct in the policy that can be used. Here script-src 'unsafe-inline' and 'unsafe-eval' will be automatically added to csp. It is not added in the settings because it's specific for webforms.

  • In the future MVC pipeline can be very strict. Here no js evaluation will be used and all inline javascript will be marked with a nonce.

This is the default csp for the setting

default-src 'self'; script-src 'self' 'report-sample'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; object-src 'none'; base-uri 'none'; form-action 'self'; frame-ancestors 'none'; frame-src 'self'; connect-src 'self';

  • It dous not accept external resources.
  • It accept inline css : actually used by the default page of dnn and generated by ckeditor with default configuration. But it is not recomended. ckeditor can be configurated to not use inline css.
  • It accept image src starting with data: bacause it is used by default dnn page. But it is not recomended.

3 http headers will be managed : Content-Security-Policy, Content-Security-Policy-Report-Only and Reporting-Endpoints

Persona bar - Security settings

image

Implementation

It commes in a new project for csp management and a test project.

The IContentSecurityPolicy service that can be used with DI had all the stuff for skin and module developers to contribute to the policy.

For webforms skin developers actually the way to contribute is

<script runat="server">
    protected void Page_Init()
    {
        var defaultPage = (DotNetNuke.Framework.DefaultPage)this.Page;
        defaultPage.AddCsp("script-src https://ajax.aspnetcdn.com");
    }
</script>

Details of DotNetNuke.ContentSecurityPolicy library

The DotNetNuke.ContentSecurityPolicy library provides a fluent API for building and emitting Content Security Policy (CSP) headers in DNN. The IContentSecurityPolicy interface is the main entry point to compose directives, manage sources, configure reporting, and generate final header strings.

Interface: IContentSecurityPolicy

Namespace: DotNetNuke.ContentSecurityPolicy

Properties

  • Nonce: Cryptographically secure nonce value to use with inline script/style tags.
  • DefaultSource: SourceCspContributor for default-src.
  • ScriptSource: SourceCspContributor for script-src.
  • StyleSource: SourceCspContributor for style-src.
  • ImgSource: SourceCspContributor for img-src.
  • ConnectSource: SourceCspContributor for connect-src.
  • FontSource: SourceCspContributor for font-src.
  • ObjectSource: SourceCspContributor for object-src.
  • MediaSource: SourceCspContributor for media-src.
  • FrameSource: SourceCspContributor for frame-src.
  • FrameAncestors: SourceCspContributor for frame-ancestors.
  • FormAction: SourceCspContributor for form-action.
  • BaseUriSource: SourceCspContributor for base-uri.

Methods

  • RemoveScriptSources(CspSourceType cspSourceType): Remove script sources of the specified type (e.g., Inline, Self, Nonce).
  • AddPluginTypes(string value): Add values for plugin-types (e.g., application/pdf).
  • AddSandboxDirective(string value): Add sandbox options (e.g., allow-scripts allow-same-origin).
  • AddFormAction(CspSourceType sourceType, string value): Add a form-action source.
  • AddFrameAncestors(CspSourceType sourceType, string value): Add a frame-ancestors source.
  • AddReportEndpoint(string name, string value): Add a named reporting endpoint.
  • AddReportTo(string value): Add a report-to group name to the policy.
  • AddHeaders(string cspHeader): Parse and merge a CSP header string; returns the same IContentSecurityPolicy for chaining.
  • GeneratePolicy(): Build the Content-Security-Policy header value.
  • GenerateReportingEndpoints(): Build the reporting header value(s).
  • UpgradeInsecureRequests(): Add the upgrade-insecure-requests directive.

Working with sources

Directive properties expose a SourceCspContributor, which supports adding/removing sources such as:

  • AddSelf()'self'
  • AddNone()'none'
  • AddInline()'unsafe-inline'
  • AddEval()'unsafe-eval'
  • AddStrictDynamic()'strict-dynamic'
  • AddNonce(string)'nonce-<value>'
  • AddHash(string)'sha256-...', 'sha384-...', 'sha512-...'
  • AddHost(string)example.com, https://cdn.example.com
  • AddScheme(string)https:, data:, blob:
  • RemoveSources(CspSourceType) to remove by type

See: CspSourceType.cs, CspSource.cs, SourceCspContributor.cs.

Usage examples

Configure a baseline policy with a nonce

using DotNetNuke.ContentSecurityPolicy;

public class CspExample
{
    private readonly IContentSecurityPolicy _csp;

    public CspExample(IContentSecurityPolicy csp)
    {
        _csp = csp;
    }

    public void Configure()
    {
        // Default baseline
        _csp.DefaultSource.AddSelf();
        _csp.ScriptSource.AddSelf().AddNonce(_csp.Nonce);
        _csp.StyleSource.AddSelf();
        _csp.ImgSource.AddSelf().AddScheme("data:");

        // Lock down frames and forms
        _csp.FrameAncestors.AddNone();
        _csp.FormAction.AddSelf();

        // Reporting
        _csp.AddReportEndpoint("csp-endpoint", "/api/csp/report");
        _csp.AddReportTo("csp-endpoint");

        // Optionally upgrade insecure requests
        _csp.UpgradeInsecureRequests();

        // Generate header values
        var cspHeader = _csp.GeneratePolicy();
        var reportingHeader = _csp.GenerateReportingEndpoints();

    }
}

Parse and merge an existing CSP header

_csp.AddHeaders("default-src 'self'; img-src 'self' data:")
    .ScriptSource.AddNonce(_csp.Nonce);

var headerValue = _csp.GeneratePolicy();

Remove an unsafe source

_csp.RemoveScriptSources(CspSourceType.Inline);

Notes

  • Nonce: use Nonce in your inline tags: <script nonce="{policy.Nonce}">.
  • Reporting: ensure your endpoint exists to accept violation reports.
  • Parsing: AddHeaders is useful to import settings from configuration and extend them programmatically.

Fixes #6720

@mitchelsellers
Copy link
Contributor

With this, how exactly does the configured process in the persona bar work with the fact that anyone could manipulate this via other methods in the skin, module, etc?

Is the portal done first and then changes applied?

How is the users input validated in the personarbar validated? is it serialized to an object with detailed validation errors?

@sachatrauwaen sachatrauwaen marked this pull request as ready for review October 3, 2025 15:48
@sachatrauwaen
Copy link
Contributor Author

sachatrauwaen commented Oct 3, 2025

With this, how exactly does the configured process in the persona bar work with the fact that anyone could manipulate this via other methods in the skin, module, etc?
Is the portal done first and then changes applied?

Yes, the portal settings are applied first in the OnInit of the page (default.aspx).
Then skin and modules can add there policy. Normally skins and modules will only add addional policy.
And finally in the OnPreRender of the page the full policy string is generated and added to the http response header.

How is the users input validated in the personarbar validated? is it serialized to an object with detailed validation errors?

The library containt a policy parser. But actully no validation error is showed to the user that enter the settings.
I will look to add this.

@dnnsoftware dnnsoftware deleted a comment from mitchelsellers Oct 3, 2025
@dnnsoftware dnnsoftware deleted a comment from mitchelsellers Oct 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Enhancement]: Content security policy headers

2 participants