Penjaro.AspNetCore 1.0.0

dotnet add package Penjaro.AspNetCore --version 1.0.0
                    
NuGet\Install-Package Penjaro.AspNetCore -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Penjaro.AspNetCore" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Penjaro.AspNetCore" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Penjaro.AspNetCore" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Penjaro.AspNetCore --version 1.0.0
                    
#r "nuget: Penjaro.AspNetCore, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Penjaro.AspNetCore@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Penjaro.AspNetCore&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Penjaro.AspNetCore&version=1.0.0
                    
Install as a Cake Tool

Penjaro.NET

Penjaro.NET is a comprehensive security middleware package for ASP.NET Core applications. It provides multiple layers of protection against a wide range of web attacks, security vulnerabilities, and data leaks - all with minimal configuration.

Table of Contents

Introduction

In today's threat landscape, web applications face constant attack from automated scanners, malicious bots, and targeted exploits. Penjaro.NET provides a robust, plug-and-play security solution that analyzes every request and response to protect your API or web application from various threats including:

  • SQL Injection attacks
  • Cross-Site Scripting (XSS)
  • Command Injection
  • Directory Traversal exploits
  • Server-Side Request Forgery (SSRF)
  • Information leakage
  • Brute force attacks
  • Malicious bots
  • And many more...

By adding just a few lines of code, you can dramatically improve your application's security posture with negligible performance impact.

Key Features

  • Comprehensive Request Analysis: Detects and blocks malicious requests using pattern matching, heuristics, and optional AI-based detection
  • Intelligent Response Analysis: Prevents sensitive data leaks and verbose error messages that could aid attackers
  • Adaptive Rate Limiting: Protects against brute force, credential stuffing, and denial of service attacks
  • Security Headers Management: Automatically applies best-practice security headers to prevent client-side attacks
  • Advanced Bot Detection: Identifies and blocks malicious bots while allowing legitimate crawlers
  • GraphQL-specific Protection: Special protections for GraphQL endpoints including depth limiting and introspection control
  • Real-time Threat Intelligence: Optional integration with IP reputation databases to block known malicious actors
  • Customizable Rules: Easily add custom patterns to address organization-specific security concerns
  • Minimal Performance Impact: Designed with performance in mind - microsecond overhead for most requests
  • Detailed Security Logging: Comprehensive security incident logging for forensic analysis

Installation

Add the Penjaro.NET package to your project:

dotnet add package Penjaro.AspNetCore

Quick Start Guide

Add Penjaro to an ASP.NET Core application

In your Program.cs:

using Penjaro.AspNetCore;
using Penjaro.Core;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// Add Penjaro security services
builder.Services.AddPenjaro(options => 
{
    options.ApiKey = "demo-api-key"; // Replace with your actual API key in production
    
    // Enable basic protections
    options.EnableRateLimit = true;
    options.RateLimitPoints = 100; // Allow 100 requests
    options.RateLimitDuration = 60; // Per minute
    
    // Enable response analysis to prevent data leaks
    options.EnableResponseAnalysis = true;
    options.EnableDataLeakChecks = true;
    options.EnableVerboseErrorChecks = true;
    
    // Configure security headers
    options.SecurityHeaders.ContentSecurityPolicy = "default-src 'self'; script-src 'self';";
    options.SecurityHeaders.FrameOptions = "DENY";
    options.SecurityHeaders.ReferrerPolicy = "strict-origin-when-cross-origin";
});

var app = builder.Build();

// Configure the HTTP request pipeline
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

// Add Penjaro middleware early in the pipeline
app.UsePenjaro();

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

With this minimal setup, your application is now protected against a wide range of common web attacks.

Configuration Options

Penjaro.NET provides extensive configuration options to tailor security to your application's specific needs.

Basic Security Options

// API Key for Penjaro services (if using cloud features)
options.ApiKey = "your-api-key";

// Master switches for different protection types
options.EnableRateLimit = true;
options.EnableResponseAnalysis = true;
options.EnableJa3Check = false; // TLS fingerprinting
options.EnableGraphqlProtection = false; // GraphQL-specific protections
options.EnableThreatIntelCheck = false; // IP reputation checking

Request Analysis

The request analysis engine checks incoming requests for various attack patterns:

// Disable specific rule categories if they cause false positives
options.DisableDefaultRequestRules["header"] = true; // Disable header injection checks
options.DisableDefaultRequestRules["ssrf"] = false; // Keep SSRF protection enabled

// Add custom patterns to detect specific attacks relevant to your application
options.CustomRequestRulePatterns.Add("custom_attack", new List<Regex> {
    new Regex(@"malicious-pattern-specific-to-your-app", RegexOptions.IgnoreCase)
});

// Replace default patterns instead of adding to them
options.ReplaceDefaultRequestPatterns = false; // Keep default patterns

Response Analysis

Response analysis prevents leaking sensitive data to attackers:

// Enable response analysis features
options.EnableResponseAnalysis = true;
options.EnableDataLeakChecks = true;
options.EnableVerboseErrorChecks = true;

// Add custom patterns to detect sensitive data specific to your organization
options.CustomDataLeakPatterns = new List<Regex>
{
    new Regex(@"internal-system-identifier=\w+", RegexOptions.IgnoreCase),
    new Regex(@"company-secret-\d{10}", RegexOptions.IgnoreCase)
};

// Add custom patterns to detect error messages
options.CustomVerboseErrorPatterns = new List<Regex>
{
    new Regex(@"CompanySpecificError occurred", RegexOptions.IgnoreCase)
};

// Choose behavior when issues are detected
options.SanitizeInsteadOfBlock = true; // Sanitize instead of blocking
options.SanitizedResponseStatusCode = 200; // Keep original status code
options.ResponseAnalysisMaxSize = 1048576; // Max size to analyze (1MB)

// Exclude specific paths from checks
options.ExcludePathsFromDataLeakCheck = new List<Regex>
{
    new Regex(@"^/api/public-data")
};

Rate Limiting

Rate limiting protects against brute force attacks and abuse:

// Basic rate limiting
options.EnableRateLimit = true;
options.RateLimitPoints = 10; // Requests allowed
options.RateLimitDuration = 1; // Per second

// Distributed rate limiting with Redis (for multi-server deployments)
options.RedisConnectionString = "localhost:6379";

Security Headers

Security headers protect against various client-side attacks:

// General security header settings
options.SecurityHeaders.Enabled = true;

// Content Security Policy
options.SecurityHeaders.ContentSecurityPolicy = 
    "default-src 'self'; " +
    "script-src 'self' https://trusted-cdn.com; " +
    "style-src 'self' 'unsafe-inline'; " +
    "img-src 'self' data: https://trusted-images.com; " +
    "connect-src 'self' https://api.yourservice.com;";

// Other security headers
options.SecurityHeaders.FrameOptions = "DENY"; // Prevent iframe embedding
options.SecurityHeaders.Hsts = "max-age=31536000; includeSubDomains"; // Force HTTPS
options.SecurityHeaders.ContentTypeOptions = "nosniff"; // Prevent MIME type sniffing
options.SecurityHeaders.ReferrerPolicy = "strict-origin-when-cross-origin"; // Control referrer info
options.SecurityHeaders.PermissionsPolicy = "camera=(), microphone=(), geolocation=()"; // Restrict browser features

// Custom headers
options.SecurityHeaders.CustomHeaders.Add("X-Custom-Security-Header", "value");

Bot Protection

Bot protection detects and blocks malicious automated traffic:

// Enable bot protection features
options.BotProtection.Enabled = true;
options.BotProtection.EnableChallenges = true; // JavaScript challenges for suspicious requests
options.BotProtection.EnableFingerprinting = true; // Browser fingerprinting
options.BotProtection.EnableBehavioralAnalysis = true; // Analyze request patterns

// Allow legitimate bots
options.BotProtection.TrustedBotPatterns = new List<Regex>
{
    new Regex(@"Googlebot"), // Google search bot
    new Regex(@"bingbot"), // Bing search bot
    new Regex(@"Twitterbot") // Twitter link preview bot
};

// Exclude paths from bot protection
options.BotProtection.ExcludePatterns = new List<Regex>
{
    new Regex(@"^/public/"),
    new Regex(@"^/sitemap\.xml$")
};

GraphQL Protection

GraphQL-specific protections guard against query abuse:

// Enable GraphQL protection
options.EnableGraphqlProtection = true;
options.GraphqlMaxDepth = 10; // Limit query nesting depth
options.GraphqlMaxComplexity = 1000; // Limit query complexity
options.GraphqlBlockIntrospection = true; // Block schema introspection in production

// Block queries containing sensitive keywords
options.GraphqlBlockKeywords = new List<string> 
{ 
    "password", 
    "secret", 
    "token",
    "credentials"
};

Threat Intelligence

Threat Intelligence blocks requests from known malicious IPs:

// Enable IP reputation checking
options.EnableThreatIntelCheck = true;

// Use built-in threat feeds
options.IncludeDefaultTorFeed = true; // Block Tor exit nodes
options.IncludeDefaultFireholFeed = true; // Block IPs from FireHOL list
options.IncludeDefaultFeodoFeed = true; // Block IPs running Feodo malware

// Add custom threat feeds
options.ThreatIntelFeedUrls = new List<string>
{
    "https://blocklist.example.com/malicious-ips.txt"
};

// Whitelist IPs that should never be blocked
options.WhitelistIps = new List<string>
{
    "192.168.1.100", // Internal testing server
    "203.0.113.45" // Office IP address
};

// Configure feed update frequency
options.ThreatIntelFetchIntervalMinutes = 60; // Update hourly

Advanced Options

// Optional: AI-based threat detection model
// This requires a pre-trained ML.NET model
options.AiModel = LoadThreatDetectionModel();

// Configure AI failure behavior
options.AiAnalysisFailureMode = "fail-open"; // Allow requests if AI fails
// options.AiAnalysisFailureMode = "fail-closed"; // Block requests if AI fails

// HTTP method restrictions
options.HttpMethodEnforcement.Enabled = true;
options.HttpMethodEnforcement.AllowedHttpMethods = new List<string> 
{ 
    "GET", "POST", "PUT", "DELETE" 
};
options.HttpMethodEnforcement.RestrictedHttpMethods = new List<string> 
{ 
    "TRACE", "TRACK", "DEBUG" 
};

// Configure CSP reporting
options.CspReporting.EnableReporting = true;
options.CspReporting.ReportingPath = "/csp-report";
options.CspReporting.MaxReports = 1000;

// Configure encrypted cookies
options.EncryptedCookies.Enabled = true;
options.EncryptedCookies.SecretKey = "a-very-strong-secret-key-with-at-least-32-chars";
options.EncryptedCookies.CookieNames = new List<string> { "auth-token", "session-data" };

Real-World Security Scenarios

Here's how Penjaro.NET helps protect against common security threats:

SQL Injection Protection

Without protection:

https://example.com/api/users?id=1' OR 1=1--

This could trick your application into returning all users.

With Penjaro.NET:

{
  "error": true,
  "message": "Request blocked for security reasons",
  "code": "SQL_INJECTION"
}

Preventing Data Leaks

Without protection, a stack trace might expose sensitive information:

{
  "error": "Internal Server Error",
  "stackTrace": "at Database.Connect(String connectionString='Server=prod-db;User=admin;Password=supersecret123!')"
}

With Penjaro.NET:

{
  "error": "An error occurred processing your request"
}

The sensitive connection string is removed.

Brute Force Protection

Without protection, attackers can make unlimited login attempts against user accounts.

With Penjaro.NET:

{
  "error": true,
  "message": "Rate limit exceeded. Try again later.",
  "code": "RATE_LIMIT_EXCEEDED"
}

After the configured number of attempts, further requests are blocked.

Path Traversal Prevention

Without protection:

https://example.com/api/files?path=../../../etc/passwd

Could expose system files.

With Penjaro.NET:

{
  "error": true,
  "message": "Request blocked for security reasons",
  "code": "PATH_TRAVERSAL"
}

GraphQL Query Depth Protection

Without protection, attackers could craft expensive deeply-nested queries:

query {
  users {
    posts {
      comments {
        user {
          posts {
            comments {
              # Deeply nested query continues...
            }
          }
        }
      }
    }
  }
}

With Penjaro.NET:

{
  "error": true,
  "message": "GraphQL query exceeds max depth: 12 > 10",
  "code": "GRAPHQL_DEPTH_LIMIT"
}

Complete Examples

Basic Web API Protection

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Penjaro.AspNetCore;
using Penjaro.Core;
using System.Text.RegularExpressions;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// Add Penjaro security services
builder.Services.AddPenjaro(options => 
{
    options.ApiKey = "demo-api-key"; // Replace with your actual API key
    
    // Basic protection
    options.EnableRateLimit = true;
    options.RateLimitPoints = 100;
    options.RateLimitDuration = 60;
    
    options.EnableResponseAnalysis = true;
    options.EnableDataLeakChecks = true;
    options.EnableVerboseErrorChecks = true;
    
    // Custom patterns for your business domain
    options.CustomRequestRulePatterns.Add("business_rule", new List<Regex> {
        new Regex(@"malicious-pattern-for-your-business", RegexOptions.IgnoreCase)
    });
    
    // Configure security headers
    options.SecurityHeaders.ContentSecurityPolicy = "default-src 'self'; script-src 'self';";
    options.SecurityHeaders.FrameOptions = "DENY";
    options.SecurityHeaders.ReferrerPolicy = "strict-origin-when-cross-origin";
});

var app = builder.Build();

// Configure the HTTP request pipeline
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

// Add Penjaro middleware early in the pipeline
app.UsePenjaro();

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

High-Security Financial Application

// Add Penjaro with enhanced security for financial applications
builder.Services.AddPenjaro(options => 
{
    options.ApiKey = Configuration["Penjaro:ApiKey"];
    
    // Aggressive rate limiting
    options.EnableRateLimit = true;
    options.RateLimitPoints = 30;
    options.RateLimitDuration = 60;
    
    // Full response analysis
    options.EnableResponseAnalysis = true;
    options.EnableDataLeakChecks = true;
    options.EnableVerboseErrorChecks = true;
    options.SanitizeInsteadOfBlock = false; // Block rather than sanitize
    
    // Add patterns to detect financial data
    options.CustomDataLeakPatterns = new List<Regex>
    {
        new Regex(@"\b\d{16}\b"), // Credit card numbers
        new Regex(@"account_number=\d{8,12}"), // Account numbers
        new Regex(@"routing=\d{9}") // Routing numbers
    };
    
    // Strict CSP for financial applications
    options.SecurityHeaders.ContentSecurityPolicy = 
        "default-src 'self'; " +
        "script-src 'self'; " +
        "style-src 'self'; " +
        "img-src 'self'; " +
        "connect-src 'self'; " +
        "frame-ancestors 'none'; " +
        "form-action 'self';";
    
    // Enable bot protection
    options.BotProtection.Enabled = true;
    options.BotProtection.EnableChallenges = true;
    
    // Enable threat intelligence
    options.EnableThreatIntelCheck = true;
    options.IncludeDefaultTorFeed = true;
    options.IncludeDefaultFireholFeed = true;
    
    // Advanced HTTP method enforcement
    options.HttpMethodEnforcement.Enabled = true;
    options.HttpMethodEnforcement.AllowedHttpMethods = new List<string> { "GET", "POST" };
});

GraphQL API Protection

// Add Penjaro with GraphQL-specific protections
builder.Services.AddPenjaro(options => 
{
    options.ApiKey = Configuration["Penjaro:ApiKey"];
    
    // Basic protections
    options.EnableRateLimit = true;
    options.EnableResponseAnalysis = true;
    
    // GraphQL-specific protections
    options.EnableGraphqlProtection = true;
    options.GraphqlMaxDepth = 8;
    options.GraphqlMaxComplexity = 500;
    options.GraphqlBlockIntrospection = !app.Environment.IsDevelopment(); // Allow in dev only
    options.GraphqlBlockKeywords = new List<string> 
    { 
        "password", "token", "secret", "credential", 
        "auth", "key", "api_key", "apikey"
    };
    
    // Security headers for GraphQL
    options.SecurityHeaders.ContentSecurityPolicy = 
        "default-src 'self'; " +
        "connect-src 'self';";
});

License

This project is licensed under the MIT License. See the LICENSE file for more information.

Publishing

If you've made changes to the library and want to publish your own version to NuGet, you can use the included scripts.

Prerequisites

  • .NET SDK installed
  • A NuGet.org account and API key
  • Update the package metadata in the project files:
    • src/Penjaro.Core/Penjaro.Core.csproj
    • src/Penjaro.AspNetCore/Penjaro.AspNetCore.csproj

Building and Packaging

On Mac/Linux:
cd Penjaro.NET
./publish.sh

This will:

  1. Build the projects in Release mode
  2. Create NuGet packages in the ./nupkgs directory

To build and publish in one step:

./publish.sh YOUR_NUGET_API_KEY
On Windows:
cd Penjaro.NET
publish.bat

This will build the packages and place them in the .\nupkgs directory.

To build and publish in one step:

publish.bat YOUR_NUGET_API_KEY

Manual Publishing

If you prefer to publish manually:

dotnet build -c Release
dotnet pack src/Penjaro.Core/Penjaro.Core.csproj -c Release -o ./nupkgs
dotnet pack src/Penjaro.AspNetCore/Penjaro.AspNetCore.csproj -c Release -o ./nupkgs
dotnet nuget push ./nupkgs/Penjaro.Core.*.nupkg -k YOUR_API_KEY -s https://api.nuget.org/v3/index.json
dotnet nuget push ./nupkgs/Penjaro.AspNetCore.*.nupkg -k YOUR_API_KEY -s https://api.nuget.org/v3/index.json
Product Compatible and additional computed target framework versions.
.NET net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 310 5/7/2025