Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
aed61d2
fix typo
sachatrauwaen Sep 9, 2025
3655bc7
performance improvement
sachatrauwaen Sep 9, 2025
bae3d24
cleanup
sachatrauwaen Sep 11, 2025
3f96a34
cleanup
sachatrauwaen Sep 11, 2025
82e169b
Module Controls : new way to make modules compatible with mvc pipeline
sachatrauwaen Sep 11, 2025
f60ada0
restructure ModuleControls to fit more the the ViewComponent patern
sachatrauwaen Sep 11, 2025
c716f4e
fix logo styling
sachatrauwaen Sep 11, 2025
be77a41
fix html module
sachatrauwaen Sep 11, 2025
d6354b6
fix empty pane rendering
sachatrauwaen Sep 11, 2025
0edffda
fix user skin object
sachatrauwaen Sep 11, 2025
54a68f8
cleanup
sachatrauwaen Sep 12, 2025
1497a8b
rename test to demo
sachatrauwaen Sep 14, 2025
d3830ab
performance optimization for menu
sachatrauwaen Sep 14, 2025
39d8084
add cursor ai ignore
sachatrauwaen Sep 14, 2025
df72d1c
Merge branch 'feature/mvc-pipeline' into ModuleControl
sachatrauwaen Sep 15, 2025
644247f
fix unit tests
sachatrauwaen Sep 15, 2025
d3cb123
add MvcControlClass to UI and db
sachatrauwaen Sep 17, 2025
eb790e0
ad mvcmodelclass to db for html module
sachatrauwaen Sep 17, 2025
ecc5c24
add documentation for CSP
sachatrauwaen Sep 17, 2025
176faf4
update mvcmoduleclass in manifest and remove sql migration script
sachatrauwaen Sep 17, 2025
04b7a03
fix folder and leanup
sachatrauwaen Sep 18, 2025
d9bad81
refactor class names
sachatrauwaen Sep 18, 2025
9e8d260
Cleanup
sachatrauwaen Sep 19, 2025
d0ff974
fix some names in the readme
sachatrauwaen Sep 19, 2025
b9f3f61
Cleanup and ViewData to RazorModuleControl
sachatrauwaen Sep 20, 2025
da40df3
remove RateLimit, it's for later
sachatrauwaen Sep 20, 2025
62f6f72
cleanup, namespace fix, better error error handling, fix viewdata
sachatrauwaen Sep 21, 2025
c6303b5
CLEANUP NAMESPACES
sachatrauwaen Sep 21, 2025
724348c
cleanup
sachatrauwaen Sep 22, 2025
473a4d4
add ModulePartial helper
sachatrauwaen Sep 22, 2025
6c31689
clean message when module control does not support mvc pipeline
sachatrauwaen Sep 22, 2025
a472753
show error when module dous not support mvc pl for page editors
sachatrauwaen Sep 23, 2025
1cee0e5
add UI for Pipeline settings in Site and Page Settings
sachatrauwaen Sep 24, 2025
83e0277
modify url rewriter to route to mvc controller depending on the new p…
sachatrauwaen Sep 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .cursorignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
node_modules/
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
.DS_Store
.idea/
.vscode/
.gitignore
.git/
.gitignore

.vs/

build/
build.*
.yarn/
Artifacts/
DotNetNuke.Internal.SourceGenerators/
Install/
tools/
Website/
.nuget/
.github/
Packages/
Refs/
tools/
Dnn Platform/node_modules/
Dnn Platform/Tests
Original file line number Diff line number Diff line change
Expand Up @@ -365,5 +365,8 @@ public interface IPortalSettings

/// <summary>Gets a value indicating whether to display the dropdowns to quickly add a moduel to the page in the edit bar.</summary>
bool ShowQuickModuleAddMenu { get; }

/// <summary>Gets the pipeline type for the portal.</summary>
string PagePipeline { get; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information
namespace DotNetNuke.Abstractions.Portals
{
/// <summary>
/// Provides constants for the page pipelines used in the DNN platform,
/// such as WebForms and MVC.
/// </summary>
public static class PagePipelineConstants
{
/// <summary>WebForms.</summary>
public const string WebForms = "webforms";

/// <summary>MVC.</summary>
public const string Mvc = "mvc";
}
}
278 changes: 278 additions & 0 deletions DNN Platform/DotNetNuke.ContentSecurityPolicy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
# DotNetNuke.ContentSecurityPolicy

This library provides a comprehensive Content Security Policy (CSP) implementation for DotNetNuke Platform. It offers a fluent API for building, managing, and generating CSP headers to enhance web application security by preventing various types of attacks such as Cross-Site Scripting (XSS) and data injection attacks.

## Overview

Content Security Policy (CSP) is a security standard that helps prevent cross-site scripting (XSS), clickjacking, and other code injection attacks by declaring which dynamic resources are allowed to load. This library provides a robust implementation for managing CSP directives in DotNetNuke applications.

## Core Interface: IContentSecurityPolicy

The `IContentSecurityPolicy` interface is the main entry point for managing Content Security Policy directives. It provides access to various source contributors and methods for configuring security policies.

### Key Features

- **Cryptographic Nonce Generation**: Automatically generates secure nonce values for CSP policies
- **Multiple Source Types**: Support for various CSP source types (self, inline, eval, host, scheme, nonce, hash, etc.)
- **Directive Management**: Comprehensive support for all major CSP directives
- **Fluent API**: Easy-to-use method chaining for building policies
- **Reporting**: Built-in support for CSP violation reporting

## Supported Directives

The interface provides access to the following CSP directive contributors:

### Source-based Directives
- **DefaultSource**: Fallback for other source directives (`default-src`)
- **ScriptSource**: Controls script execution (`script-src`)
- **StyleSource**: Controls stylesheet loading (`style-src`)
- **ImgSource**: Controls image sources (`img-src`)
- **ConnectSource**: Controls AJAX, WebSocket, and EventSource connections (`connect-src`)
- **FontSource**: Controls font loading (`font-src`)
- **ObjectSource**: Controls plugins and embedded objects (`object-src`)
- **MediaSource**: Controls audio and video elements (`media-src`)
- **FrameSource**: Controls iframe sources (`frame-src`)
- **FrameAncestors**: Controls embedding in frames (`frame-ancestors`)
- **FormAction**: Controls form submission targets (`form-action`)
- **BaseUriSource**: Controls base URI restrictions (`base-uri`)

### Document Directives
- **Plugin Types**: Restrict allowed plugin types
- **Sandbox**: Apply sandbox restrictions
- **Upgrade Insecure Requests**: Automatically upgrade HTTP to HTTPS

### Reporting
- **Report Endpoints**: Configure violation reporting endpoints
- **Report To**: Specify report destination

## Usage Examples

### Basic Setup

```csharp
// Create a new CSP instance
IContentSecurityPolicy csp = new ContentSecurityPolicy();

// Configure basic security policy
csp.DefaultSource.AddSelf();
csp.ScriptSource.AddSelf().AddNonce(csp.Nonce);
csp.StyleSource.AddSelf().AddInline();
csp.ImgSource.AddSelf().AddScheme("data:");
```

### Advanced Configuration

```csharp
// Configure script sources with strict security
csp.ScriptSource
.AddSelf()
.AddHost("cdn.example.com")
.AddNonce(csp.Nonce)
.AddStrictDynamic();

// Configure style sources
csp.StyleSource
.AddSelf()
.AddHost("fonts.googleapis.com")
.AddHash("sha256-abc123...");

// Configure frame restrictions
csp.FrameAncestors.AddNone(); // Prevent embedding in frames

// Configure form actions
csp.AddFormAction(CspSourceType.Self, null);
csp.AddFormAction(CspSourceType.Host, "secure.example.com");
```

### Working with Nonces

```csharp
// Get the cryptographically secure nonce
string nonce = csp.Nonce;

// Use nonce in script tags
// <script nonce="@nonce">...</script>

// Nonce is automatically applied when using AddNonce()
csp.ScriptSource.AddNonce(nonce);
```

### Removing Sources

```csharp
// Remove unsafe script sources
csp.RemoveScriptSources(CspSourceType.Inline);
csp.RemoveScriptSources(CspSourceType.Eval);
```

### Reporting Configuration

```csharp
// Configure violation reporting
csp.AddReportEndpoint("default", "/api/csp-reports");
csp.AddReportTo("default");
```

### Generating Policy Headers

```csharp
// Generate the complete CSP header value
string cspHeader = csp.GeneratePolicy();
// Result: "default-src 'self'; script-src 'self' 'nonce-abc123'; style-src 'self' 'unsafe-inline'"

// Generate reporting endpoints header
string reportingHeader = csp.GenerateReportingEndpoints();
```

## Source Types

The library supports all standard CSP source types through the `CspSourceType` enumeration:

- **Host**: Specific domains (e.g., `example.com`, `*.example.com`)
- **Scheme**: Protocol schemes (e.g., `https:`, `data:`, `blob:`)
- **Self**: Same origin (`'self'`)
- **Inline**: Inline scripts/styles (`'unsafe-inline'`)
- **Eval**: Dynamic code evaluation (`'unsafe-eval'`)
- **Nonce**: Cryptographic nonce (`'nonce-abc123'`)
- **Hash**: Cryptographic hash (`'sha256-abc123'`)
- **None**: Block all sources (`'none'`)
- **StrictDynamic**: Enable strict dynamic loading (`'strict-dynamic'`)

## Security Best Practices

1. **Avoid `'unsafe-inline'`**: Use nonces or hashes instead
2. **Avoid `'unsafe-eval'`**: Prevents code injection attacks
3. **Use `'strict-dynamic'`**: For modern browsers with script loading
4. **Implement reporting**: Monitor CSP violations
5. **Start restrictive**: Begin with strict policies and relax as needed
6. **Test thoroughly**: Ensure all legitimate resources load correctly

## Implementation Details

### Key Classes

- **ContentSecurityPolicy**: Main implementation of `IContentSecurityPolicy`
- **SourceCspContributor**: Manages source-based directives
- **CspSource**: Represents individual CSP sources
- **CspDirectiveType**: Enumeration of all CSP directive types
- **CspSourceType**: Enumeration of all CSP source types

### Thread Safety

The CSP implementation is designed to be used within a single request context. For multi-threaded scenarios, create separate instances per thread or request.

### Performance Considerations

- Nonce generation uses cryptographically secure random number generation
- Policy generation is optimized for minimal string operations
- Source deduplication prevents duplicate entries

## Class Diagram

```mermaid
classDiagram
class IContentSecurityPolicy {
<<interface>>
+string Nonce
+SourceCspContributor DefaultSource
+SourceCspContributor ScriptSource
+SourceCspContributor StyleSource
+SourceCspContributor ImgSource
+SourceCspContributor ConnectSource
+SourceCspContributor FontSource
+SourceCspContributor ObjectSource
+SourceCspContributor MediaSource
+SourceCspContributor FrameSource
+SourceCspContributor FrameAncestors
+SourceCspContributor FormAction
+SourceCspContributor BaseUriSource
+RemoveScriptSources(CspSourceType) void
+AddPluginTypes(string) void
+AddSandboxDirective(string) void
+AddFormAction(CspSourceType, string) void
+AddFrameAncestors(CspSourceType, string) void
+AddReportEndpoint(string, string) void
+AddReportTo(string) void
+GeneratePolicy() string
+GenerateReportingEndpoints() string
+UpgradeInsecureRequests() void
}

class ContentSecurityPolicy {

}

class BaseCspContributor {
<<abstract>>
+Guid Id
+CspDirectiveType DirectiveType
+GenerateDirective()* string
}

class SourceCspContributor {
-List~CspSource~ Sources
+bool InlineForBackwardCompatibility
+AddInline() SourceCspContributor
+AddSelf() SourceCspContributor
+AddSourceEval() SourceCspContributor
+AddHost(string) SourceCspContributor
+AddScheme(string) SourceCspContributor
+AddNonce(string) SourceCspContributor
+AddHash(string) SourceCspContributor
+AddNone() SourceCspContributor
+AddStrictDynamic() SourceCspContributor
+AddSource(CspSource) SourceCspContributor
+RemoveSources(CspSourceType) void
+GenerateDirective() string
+GetSourcesByType(CspSourceType) IEnumerable~CspSource~
}

class ReportingCspContributor {
-List~string~ reportingEndpoints
+AddReportingEndpoint(string) void
+GenerateDirective() string
}

class ReportingEndpointContributor {
-List~ReportingEndpoint~ reportingEndpoints
+AddReportingEndpoint(string, string) void
+GenerateDirective() string
}

class CspSource {
+CspSourceType Type
+string Value
+CspSource(CspSourceType, string)
+ToString() string
-ValidateSource(CspSourceType, string) string
-ValidateHostSource(string) string
-ValidateSchemeSource(string) string
-ValidateNonceSource(string) string
-ValidateHashSource(string) string
-IsBase64String(string) bool
}



IContentSecurityPolicy <|.. ContentSecurityPolicy : implements
BaseCspContributor <|-- SourceCspContributor : extends
BaseCspContributor <|-- DocumentCspContributor : extends
BaseCspContributor <|-- ReportingCspContributor : extends
BaseCspContributor <|-- ReportingEndpointContributor : extends
ContentSecurityPolicy *-- BaseCspContributor : contains
SourceCspContributor *-- CspSource : contains



```

## Integration with DotNetNuke

This library integrates seamlessly with the DotNetNuke Platform's security infrastructure and can be used within:

- Custom modules
- Skin implementations
- HTTP modules and handlers
- API controllers
- Page rendering pipelines

Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ protected override void Initialize(RequestContext requestContext)
{
base.Initialize(requestContext);

if (requestContext.RouteData.Values.ContainsKey("mvcpage"))
if (requestContext.RouteData != null && requestContext.RouteData.Values.ContainsKey("mvcpage"))
{
var values = requestContext.RouteData.Values;
var moduleContext = new ModuleInstanceContext();
Expand All @@ -168,26 +168,12 @@ protected override void Initialize(RequestContext requestContext)

moduleContext.Configuration = moduleInfo;

/*
var desktopModule = DesktopModuleControllerAdapter.Instance.GetDesktopModule(moduleInfo.DesktopModuleID, moduleInfo.PortalID);
var moduleRequestContext = new ModuleRequestContext
{
HttpContext = httpContext,
ModuleContext = moduleContext,
ModuleApplication = new ModuleApplication(this.RequestContext, DisableMvcResponseHeader)
{
ModuleName = desktopModule.ModuleName,
FolderPath = desktopModule.FolderName,
},
};
*/

this.ModuleContext = new ModuleInstanceContext() { Configuration = moduleInfo };
this.LocalResourceFile = string.Format(
"~/DesktopModules/MVC/{0}/{1}/{2}.resx",
moduleInfo.DesktopModule.FolderName,
Localization.LocalResourceDirectory,
this.RouteData.Values["ControllerName"]);
this.RouteData.Values["controller"]);

var moduleApplication = new ModuleApplication(requestContext, true)
{
Expand All @@ -196,8 +182,6 @@ protected override void Initialize(RequestContext requestContext)
};
moduleApplication.Init();

// var viewEngines = new ViewEngineCollection();
// viewEngines.Add(new ModuleDelegatingViewEngine());
this.ViewEngineCollectionEx = moduleApplication.ViewEngines;
}

Expand Down
Loading