Package Exports
- penjaro-network-security-library-javascript
- penjaro-network-security-library-javascript/dist/library.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (penjaro-network-security-library-javascript) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
Penjaro Network Security Middleware
AI-Powered Network Security for Modern Web Applications
Penjaro provides intelligent, proactive network security for your web applications and APIs. It acts as a smart shield between your application and potential threats, analyzing incoming requests and outgoing responses using a sophisticated combination of:
- Rule-based detection
- Threat intelligence feeds
- AI-powered analysis (optional)
- Framework-specific hardening techniques
Stop attacks before they reach your application logic. Penjaro integrates seamlessly as middleware or a standalone proxy, offering a powerful layer of defense against common and sophisticated threats.
Why Choose Penjaro?
- Proactive Defense: Identifies and blocks threats like SQL injection, XSS, command injection, malicious bots, DoS attempts, and more at the edge
- AI-Powered Intelligence: Leverage TensorFlow.js models to detect novel and complex attack patterns that signature-based methods might miss
- Threat Feed Integration: Stay ahead of attackers by automatically blocking IPs known for malicious activity (malware C&C, scanners, Tor exits, etc.)
- Response Security: Prevent accidental leaks of sensitive data (API keys, PII) or verbose error messages in responses
- Framework Native: Easy integration with popular Node.js frameworks (Express, NestJS, Koa, Fastify, Hapi)
- Highly Configurable: Fine-tune security policies to match your application's specific needs and risk profile
- Distributed Ready: Use Redis to share rate limiting and threat intelligence state across multiple instances
Key Features
Request Filtering
- Rule-based detection (SQLi, XSS, Cmd Inj, Path Trav, SSRF, Log4j, etc.)
- Customizable rule patterns
- Threat intelligence IP blocking (Tor, FireHOL, Feodo, CINS, custom feeds)
- IP Rate Limiting (in-memory or Redis)
- JA3 TLS Fingerprint blocking
- GraphQL Protection (depth, complexity, introspection, keyword blocking)
- Advanced Bot Protection (behavioral analysis, browser challenges, fingerprinting)
Response Filtering (Proxy Mode Only)
- Data leak prevention (detects common key/PII patterns)
- Verbose error message scrubbing
- Customizable detection patterns
Security Headers and Browser Protection
- Content Security Policy (CSP) with violation reporting
- Comprehensive HTTP security headers management
- Encrypted cookies with transparent encryption/decryption
- Subresource Integrity (SRI) for script and stylesheet verification
AI-Powered Analysis (Optional)
- Integrates with pre-trained
tf.jsmodels - Customizable feature extraction
- Configurable failure modes (fail-open/fail-closed)
Incident Reporting
- Reports blocked requests/responses to the Penjaro API for visibility
Flexible Deployment
- Middleware Mode: Integrate directly into your application code
- Proxy Mode: Run as a standalone reverse proxy shielding your backend
Advanced Security Features
In addition to the core security features, Penjaro provides several advanced security mechanisms to enhance your application's protection:
Content Security Policy (CSP) Reporting
Content Security Policy is one of the most powerful browser security features, restricting which resources can be loaded and executed by the browser. Penjaro provides comprehensive CSP support with violation reporting:
- Configure and apply CSP headers with sensible defaults
- Set up CSP violation reporting endpoints
- Store, analyze, and respond to CSP violation reports
- Multiple storage options (in-memory, file, callback)
- Notification hooks for real-time alerts
const penjaroMiddleware = await createPenjaroProxy({
apiKey: 'your-api-key',
securityHeaders: {
contentSecurityPolicy: {
enableReporting: true,
reportingPath: '/csp-report',
directives: {
'default-src': ["'self'"],
'script-src': ["'self'", "https://trusted-cdn.com"]
}
}
}
});Security Headers Management
HTTP security headers provide critical browser-level protections against common web vulnerabilities. Penjaro offers a comprehensive set of security headers with sensible defaults:
- Content-Security-Policy (CSP)
- Strict-Transport-Security (HSTS)
- X-Frame-Options
- X-Content-Type-Options
- Referrer-Policy
- Permissions-Policy
- Cross-Origin headers (Opener, Embedder, Resource Policy)
const penjaroMiddleware = await createPenjaroProxy({
apiKey: 'your-api-key',
securityHeaders: {
frameOptions: 'DENY',
hsts: 'max-age=31536000; includeSubDomains; preload',
referrerPolicy: 'strict-origin-when-cross-origin',
permissionsPolicy: 'camera=(), microphone=(), geolocation=()'
}
});Encrypted Cookies
Cookies often store sensitive session data that needs protection. Penjaro's encrypted cookies feature provides transparent encryption and decryption:
- AES-GCM encryption for cookie values
- Automatic encryption/decryption
- Cookie-specific encryption targeting
- Configurable cookie options (httpOnly, secure, SameSite)
- Convenience methods for setting/getting encrypted cookies
const penjaroMiddleware = await createPenjaroProxy({
apiKey: 'your-api-key',
encryptedCookies: {
secretKey: 'at-least-32-characters-long-secret-key',
cookieNames: ['session', 'auth', 'token'],
defaultCookieOptions: {
httpOnly: true,
secure: true,
sameSite: 'strict'
}
}
});
// In your route handlers
app.get('/profile', (req, res) => {
// Access decrypted cookie
const sessionData = req.getDecryptedCookie('session');
// Set encrypted cookie
res.setEncryptedCookie('session', JSON.stringify({ userId: 123 }));
});Subresource Integrity (SRI)
Ensure resources loaded from external sources (like CDNs) haven't been tampered with:
- Generate integrity hashes for scripts and stylesheets
- Verify resource integrity
- Cache generated hashes for performance
- Generate SRI-enabled HTML tags
const { createSRIManager } = require('penjaro-network-security-library-javascript');
// Setup SRI
const sriManager = createSRIManager({
algorithms: ['sha384'],
cacheDir: '.sri-cache'
});
// Generate integrity hash
const integrity = await sriManager.generateIntegrity('https://cdn.example.com/script.js');
console.log(integrity.integrity); // outputs: "sha384-a1b2c3d4..."
// Generate script tag with integrity
const scriptTag = await sriManager.generateScriptTag('https://cdn.example.com/script.js');Advanced Bot Protection
Detect and block malicious bots, scrapers, and automated tools:
- User-Agent pattern detection
- Browser fingerprinting
- Behavioral analysis
- Challenge-based verification
- Whitelist trusted crawlers (Google, Bing, etc.)
- Customizable challenge pages
const penjaroMiddleware = await createPenjaroProxy({
apiKey: 'your-api-key',
botProtection: {
enableChallenges: true,
enableFingerprinting: true,
enableBehavioralAnalysis: true,
cookieName: '_bot_verify',
excludePatterns: [/^\/api\/public/, /\.(jpg|png|gif)$/],
trustedBotPatterns: [/Googlebot/i, /bingbot/i]
}
});Installation
# Install the core package
npm install penjaro-network-security-library-javascript
# Or with yarn
yarn add penjaro-network-security-library-javascript
# Install peer dependencies for your framework (e.g., Express)
npm install express
# Optional dependencies (needed for specific features)
npm install redis # For Redis-based rate limiting / threat intel
npm install graphql # For GraphQL protection
npm install @tensorflow/tfjs-node # For AI featuresCore Concept: Operating Modes
Penjaro can operate in two distinct modes, determined by the presence of the targetServer option:
1. Middleware Mode (No targetServer)
- Integrates directly into your framework's middleware chain
- Analyzes incoming requests only
- Blocks malicious requests or passes legitimate ones to your application logic
- Ideal for securing existing applications without changing infrastructure
2. Proxy Mode (targetServer is provided)
- Acts as a reverse proxy
- Analyzes both incoming requests and outgoing responses
- Forwards valid requests to your target server
- Provides comprehensive protection including data leak prevention
- Requires Penjaro to run as a separate process or container
Quick Start Examples
Express (Middleware Mode)
import express from 'express';
import { createPenjaroProxy, PenjaroConfigOptions } from 'penjaro-network-security-library-javascript';
const app = express();
const penjaroOptions: PenjaroConfigOptions = {
apiKey: process.env.PENJARO_API_KEY,
enableRateLimit: true,
enableThreatIntelCheck: true,
includeDefaultFireholFeed: true,
};
async function startServer() {
try {
// Initialize Penjaro middleware
const penjaroMiddleware = await createPenjaroProxy(penjaroOptions);
// Apply Penjaro middleware BEFORE other routes/middleware
app.use(penjaroMiddleware);
// Your application routes
app.get('/', (req, res) => {
res.send('Hello World!');
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running with Penjaro protection on port ${PORT}`);
});
} catch (error) {
console.error("Failed to initialize Penjaro or start server:", error);
process.exit(1);
}
}
startServer();Express (Proxy Mode)
import express from 'express';
import { createPenjaroProxy, PenjaroConfigOptions } from 'penjaro-network-security-library-javascript';
async function startProxy() {
try {
const penjaroOptions: PenjaroConfigOptions = {
apiKey: process.env.PENJARO_API_KEY,
targetServer: 'http://localhost:8080', // Your actual application server
enableRateLimit: true,
enableResponseAnalysis: true, // Enable response analysis
enableDataLeakChecks: true,
enableVerboseErrorChecks: true,
};
// Initialize Penjaro proxy
const penjaroProxy = await createPenjaroProxy(penjaroOptions);
// Create an Express app that just uses the proxy
const app = express();
app.use(penjaroProxy);
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Penjaro proxy running on port ${PORT}, forwarding to ${penjaroOptions.targetServer}`);
});
} catch (error) {
console.error("Failed to initialize Penjaro proxy:", error);
process.exit(1);
}
}
startProxy();Express 5.x Compatibility
Penjaro now includes built-in support for both Express 4.x and Express 5.x. The library has been updated to handle the middleware changes in Express 5, including:
- Handling of async/await middleware functions
- Support for Express 5's promise-based middleware chain
- Compatibility with Express 5's updated response object
Using Penjaro with Express 5.x
For the best compatibility with Express 5.x, use the dedicated Express adapter:
import express from 'express';
import { createExpressMiddleware } from 'penjaro-network-security-library-javascript';
const app = express();
async function startServer() {
try {
// Use the Express-specific adapter for best compatibility
const penjaroMiddleware = await createExpressMiddleware({
apiKey: process.env.PENJARO_API_KEY,
enableRateLimit: true,
// ... other options
});
// Apply Penjaro middleware
app.use(penjaroMiddleware);
// Your Express 5.x routes
app.get('/', async (req, res) => {
// Express 5.x allows async route handlers
const data = await fetchSomeData();
res.send(data);
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Express 5.x server running with Penjaro protection on port ${PORT}`);
});
} catch (error) {
console.error("Failed to initialize Penjaro:", error);
process.exit(1);
}
}
startServer();Flexible Dependency Versioning
Penjaro now supports a wider range of dependency versions:
- Express:
^4.17.1 || ^5.0.0 - NestJS:
^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 - Koa:
^2.13.0 || ^3.0.0 - Fastify:
^4.0.0 || ^5.0.0 - Redis:
^4.0.0 || ^5.0.0 - And more...
This makes it easier to integrate Penjaro into projects using different versions of these frameworks and libraries.
Framework Integration Examples
NestJS
NestJS integration is easy and clean with Penjaro's dedicated adapter. Here's a complete example:
1. Create a Penjaro Module
// src/penjaro/penjaro.module.ts
import { Module, DynamicModule } from '@nestjs/common';
import { PenjaroService } from './penjaro.service';
import { PenjaroConfigOptions } from 'penjaro-network-security-library-javascript';
@Module({})
export class PenjaroModule {
static register(options: PenjaroConfigOptions): DynamicModule {
return {
module: PenjaroModule,
providers: [
{
provide: 'PENJARO_OPTIONS',
useValue: options,
},
PenjaroService,
],
exports: [PenjaroService],
};
}
}2. Create a Penjaro Service
// src/penjaro/penjaro.service.ts
import { Injectable, Inject, OnModuleInit, OnModuleDestroy, Logger } from '@nestjs/common';
import { createPenjaroProxy, PenjaroConfigOptions } from 'penjaro-network-security-library-javascript';
import { RequestHandler } from 'express';
@Injectable()
export class PenjaroService implements OnModuleInit, OnModuleDestroy {
private middleware: RequestHandler | null = null;
private redisClient: unknown | null = null;
private readonly logger = new Logger(PenjaroService.name);
private initializationPromise: Promise<void> | null = null;
constructor(
@Inject('PENJARO_OPTIONS') private readonly options: PenjaroConfigOptions,
) {}
async onModuleInit() {
this.initializationPromise = this.initialize();
await this.initializationPromise;
}
private async initialize() {
try {
this.logger.log('Initializing Penjaro middleware...');
this.middleware = (await createPenjaroProxy(
this.options,
)) as unknown as RequestHandler;
// Store redis client reference if it exists
if (this.options.redisClient) {
this.redisClient = this.options.redisClient;
}
this.logger.log('Penjaro middleware initialized successfully');
} catch (error) {
this.logger.error(`Failed to initialize Penjaro middleware: ${error.message}`);
throw error;
}
}
async onModuleDestroy() {
// Clean up redis connection if needed
if (
this.redisClient &&
typeof (this.redisClient as any).disconnect === 'function'
) {
try {
await (this.redisClient as any).disconnect();
this.logger.log('Redis client disconnected successfully');
} catch (error) {
this.logger.error(`Error disconnecting Redis client: ${error.message}`);
}
}
}
getMiddleware(): RequestHandler {
if (!this.middleware) {
throw new Error('Penjaro middleware not initialized');
}
return this.middleware;
}
}3. Create a Penjaro Middleware
// src/penjaro/penjaro.middleware.ts
import { Injectable, NestMiddleware, Logger } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
import { PenjaroService } from './penjaro.service';
@Injectable()
export class PenjaroMiddleware implements NestMiddleware {
private readonly logger = new Logger(PenjaroMiddleware.name);
constructor(private readonly penjaroService: PenjaroService) {}
use(req: Request, res: Response, next: NextFunction) {
try {
const middleware = this.penjaroService.getMiddleware();
middleware(req, res, (err?: any) => {
if (err) {
this.logger.error(`Penjaro middleware error: ${err.message}`);
return next(err);
}
next();
});
} catch (error) {
this.logger.error(`Failed to get Penjaro middleware: ${error.message}`);
next(error);
}
}
}4. Use in App Module
// src/app.module.ts
import { Module, MiddlewareConsumer, NestModule } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { PenjaroModule } from './penjaro/penjaro.module';
import { PenjaroMiddleware } from './penjaro/penjaro.middleware';
@Module({
imports: [
PenjaroModule.register({
apiKey: process.env.PENJARO_API_KEY,
enableRateLimit: true,
rateLimitPoints: 5,
rateLimitDuration: 10, // 10 seconds
enableResponseAnalysis: true,
enableDataLeakChecks: true,
enableVerboseErrorChecks: true,
// Example custom rules
customRequestRulePatterns: {
xss: [/<script[^>]*>[\s\S]*?<\/script>/i],
sql: [/(\%27)|(\')|(\-\-)|(\%23)|(#)/i, /(\s|;|\/\*)+(select|union|insert|drop|delete|update|create|alter)/i],
},
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(PenjaroMiddleware)
.exclude('health') // Exclude health check endpoint
.forRoutes('*');
}
}Alternative NestJS with Adapter Factory
// src/app.module.ts
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { createPenjaroAdapter, Framework } from 'penjaro-network-security-library-javascript/dist/adapters';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule implements NestModule {
async configure(consumer: MiddlewareConsumer) {
const penjaroMiddleware = await createPenjaroAdapter(Framework.NESTJS, {
apiKey: process.env.PENJARO_API_KEY,
enableRateLimit: true,
rateLimitPoints: 10,
rateLimitDuration: 1,
});
consumer
.apply(penjaroMiddleware)
.forRoutes('*');
}
}Koa Example
import Koa from 'koa';
import { createPenjaroAdapter, Framework } from 'penjaro-network-security-library-javascript/dist/adapters';
const app = new Koa();
async function start() {
try {
const penjaroMiddleware = await createPenjaroAdapter(Framework.KOA, {
apiKey: process.env.PENJARO_API_KEY,
enableRateLimit: true,
enableThreatIntelCheck: true,
includeDefaultFireholFeed: true,
});
// Add Penjaro middleware
app.use(penjaroMiddleware);
// Add your routes
app.use(async (ctx) => {
ctx.body = 'Hello World';
});
// Start server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
} catch (error) {
console.error('Failed to initialize Penjaro middleware:', error);
process.exit(1);
}
}
start();Fastify Example
import Fastify from 'fastify';
import { createPenjaroAdapter, Framework } from 'penjaro-network-security-library-javascript/dist/adapters';
const fastify = Fastify({ logger: true });
async function start() {
try {
const penjaroPlugin = await createPenjaroAdapter(Framework.FASTIFY, {
apiKey: process.env.PENJARO_API_KEY,
enableRateLimit: true,
enableThreatIntelCheck: true,
});
// Register Penjaro plugin
await fastify.register(penjaroPlugin);
// Define routes
fastify.get('/', async (request, reply) => {
return { hello: 'world' };
});
// Start server
await fastify.listen({ port: 3000, host: '0.0.0.0' });
console.log(`Server running on ${fastify.server.address().port}`);
} catch (error) {
console.error('Failed to start server:', error);
process.exit(1);
}
}
start();Hapi Example
import Hapi from '@hapi/hapi';
import { createPenjaroAdapter, Framework } from 'penjaro-network-security-library-javascript/dist/adapters';
async function start() {
try {
const server = Hapi.server({
port: 3000,
host: 'localhost',
});
const penjaroPlugin = await createPenjaroAdapter(Framework.HAPI, {
apiKey: process.env.PENJARO_API_KEY,
enableRateLimit: true,
rateLimitPoints: 10,
rateLimitDuration: 1,
});
// Register Penjaro plugin
await server.register(penjaroPlugin);
// Define routes
server.route({
method: 'GET',
path: '/',
handler: (request, h) => {
return 'Hello World!';
},
});
// Start server
await server.start();
console.log(`Server running on ${server.info.uri}`);
} catch (error) {
console.error('Failed to start server:', error);
process.exit(1);
}
}
start();Comprehensive Configuration Examples
Below is a complete configuration example with detailed comments for each option:
import { PenjaroConfigOptions } from 'penjaro-network-security-library-javascript';
import * as tf from '@tensorflow/tfjs-node'; // Only if using AI features
// Load a pre-trained model (only if using AI features)
async function loadModel() {
const model = await tf.loadLayersModel('file:///path/to/model/model.json');
return model;
}
async function createConfiguration() {
// Optional: Load AI model
const aiModel = await loadModel().catch(err => {
console.error('Failed to load AI model:', err);
return null;
});
const penjaroConfig: PenjaroConfigOptions = {
//======================================================================
// REQUIRED CONFIGURATION
//======================================================================
// Your unique API key obtained from Penjaro dashboard
apiKey: process.env.PENJARO_API_KEY || 'your_api_key',
//======================================================================
// OPERATING MODE
//======================================================================
// Target server URL - if specified, enables Proxy Mode
// If omitted, operates in Middleware Mode
// targetServer: 'http://localhost:8080',
// HTTP Proxy configuration (only used in Proxy Mode)
proxyConfig: {
// Options passed directly to http-proxy-middleware
// See: https://github.com/chimurai/http-proxy-middleware#options
changeOrigin: true,
ws: true, // Support WebSockets
// pathRewrite: { '^/api': '' }, // URL rewriting
},
//======================================================================
// RATE LIMITING
//======================================================================
// Enable IP-based rate limiting
enableRateLimit: true,
// Maximum requests allowed per time window
rateLimitPoints: 100,
// Time window in seconds
rateLimitDuration: 60, // 100 requests per minute
//======================================================================
// THREAT INTELLIGENCE
//======================================================================
// Enable checking IPs against threat intelligence feeds
enableThreatIntelCheck: true,
// Custom threat intelligence feed URLs (plain text, one IP per line)
threatIntelFeedUrls: [
'https://your-organization.com/custom-blocklist.txt',
],
// How often to refresh the threat intelligence feeds (in minutes)
threatIntelFetchIntervalMinutes: 60, // Hourly updates
// Include default feeds
includeDefaultTorFeed: true, // Tor exit nodes
includeDefaultFireholFeed: true, // FireHOL Level 1 blocklist
includeDefaultFeodoFeed: true, // Feodo Tracker botnet IPs
includeDefaultCinsFeed: true, // CINS Army List
// IPs that should never be blocked, even if in block lists
whitelistIps: [
'127.0.0.1', '::1', // Localhost
'192.168.0.0/16', // Private network
'your-office-ip.example.com', // Office IP
],
// Callback for threat intel fetch errors
onThreatIntelError: (error) => {
console.error('Threat intel error:', error);
// You can implement notifications or logging here
},
//======================================================================
// GRAPHQL PROTECTION
//======================================================================
// Enable GraphQL-specific protections (requires graphql package)
enableGraphqlProtection: true,
// Maximum allowed query nesting depth
graphqlMaxDepth: 7,
// Maximum allowed query complexity score
graphqlMaxComplexity: 500,
// Block GraphQL introspection queries in production
graphqlBlockIntrospection: process.env.NODE_ENV === 'production',
// Block if these keywords appear in GraphQL string values
graphqlBlockKeywords: [
'UNION SELECT', 'DROP TABLE', '../../', 'eval(', 'etc/passwd'
],
//======================================================================
// RESPONSE ANALYSIS (PROXY MODE ONLY)
//======================================================================
// Master switch for response analysis
enableResponseAnalysis: true,
// Enable checks for data leaks in responses
enableDataLeakChecks: true,
// Enable checks for verbose errors in responses
enableVerboseErrorChecks: true,
// Max size in bytes to analyze (1MB default)
responseAnalysisMaxSize: 1048576,
// Content types to analyze
responseAnalysisContentTypes: [
'application/json', 'text/html', 'text/plain',
'application/xml', 'text/xml'
],
// Block responses with sensitive data/errors?
blockUnsafeResponses: true,
// Replace default patterns instead of adding to them?
replaceDefaultPatterns: false,
// Custom data leak patterns to detect
customDataLeakPatterns: [
/api[_-]?key["\s]*[:=]\s*["']([a-zA-Z0-9]{16,})["']/i,
/password["\s]*[:=]\s*["']([^"']{8,})["']/i,
/private[_-]key["\s]*[:=]\s*["']-{5}BEGIN(?:(?!\n-{5}END).)*-{5}END/is
],
// Custom verbose error patterns to detect
customVerboseErrorPatterns: [
/TypeError:.*at\s+.*\(.*:\d+:\d+\)/i,
/internal server error/i,
/Database connection failed/i
],
// URL paths to exclude from data leak checks
excludePathsFromDataLeakCheck: [
/\/auth\/login/i, // Auth endpoints containing credentials
/\/user\/profile/i, // Profile pages with PII
],
// URL paths to exclude from error checks
excludePathsFromErrorCheck: [
/\/debug\//i, // Debug endpoints
/\/developer\//i // Developer tools
],
//======================================================================
// JA3 FINGERPRINTING
//======================================================================
// Enable JA3 TLS fingerprint checking
// REQUIRES upstream proxy (Nginx, Envoy, etc.) to provide the hash
enableJa3Check: false,
// Header name containing the JA3 hash from upstream proxy
ja3HeaderName: 'X-JA3-Hash',
// Known malicious JA3 hashes to block
badJa3Hashes: [
'e7d705a3286e19ea42f587b344ee6865', // Cobalt Strike variant
'4d7a28d5dd63494652553193b9a3a0cf', // Metasploit variant
'6734f37431670b3ab4292b8f60f29984' // Malware variant
],
//======================================================================
// REQUEST RULE CUSTOMIZATION
//======================================================================
// Disable specific built-in rule categories
disableDefaultRequestRules: {
ssrf: true, // Disable SSRF detection (for local dev)
ssrfHeader: true, // Disable SSRF header checks
sql: false, // Keep SQL injection checks
xss: false, // Keep XSS checks
command: false, // Keep command injection checks
traversal: false, // Keep path traversal checks
header: false, // Keep header checks
log4j: false, // Keep Log4j checks
info: false, // Keep information disclosure checks
scanner: false, // Keep scanner detection
xssLib: false // Keep XSS library checks
},
// Custom request rule patterns to add or replace
customRequestRulePatterns: {
sql: [
/UNION\s+SELECT/i,
/ORDER\s+BY\s+\d+/i
],
xss: [
/<script[^>]*>[\s\S]*?<\/script>/i,
/javascript:alert\(/i
],
creditcard: [
/4[0-9]{12}(?:[0-9]{3})?/, // Visa
/5[1-5][0-9]{14}/ // Mastercard
]
},
// Replace default request patterns instead of merging?
replaceDefaultRequestPatterns: false,
//======================================================================
// AI INTEGRATION
//======================================================================
// Pre-loaded TensorFlow.js model (optional)
aiModel: aiModel,
// Custom function to extract features from requests
featureExtractor: (req) => {
// Extract numerical features from request for AI model
return [
req.headers['content-length'] ? parseInt(req.headers['content-length'], 10) : 0,
req.url ? req.url.length : 0,
req.query ? Object.keys(req.query).length : 0,
// Add more features as needed
];
},
// Behavior if AI analysis fails
aiAnalysisFailureMode: 'fail-open', // Options: 'fail-open' or 'fail-closed'
//======================================================================
// REDIS INTEGRATION (DISTRIBUTED DEPLOYMENT)
//======================================================================
// Redis URL for distributed rate limiting and threat intel
redisUrl: process.env.REDIS_URL,
// Redis connection options (used if redisUrl not provided)
// redisOptions: {
// host: 'localhost',
// port: 6379,
// password: 'your-password'
// },
// Optional: Pre-configured Redis client
// redisClient: yourRedisClient,
//======================================================================
// INCIDENT REPORTING
//======================================================================
// Enable reporting of security incidents to Penjaro API
enableIncidentReporting: true
};
return penjaroConfig;
}
## Framework-Specific Integration Examples
### Express.js
#### Middleware Mode
```typescript
// middleware-mode.ts
import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
import { createPenjaroProxy, PenjaroConfigOptions } from 'penjaro-network-security-library-javascript';
import dotenv from 'dotenv';
dotenv.config();
const app = express();
const PORT = process.env.PORT || 3000;
async function startServer() {
try {
// Configure Penjaro
const penjaroOptions: PenjaroConfigOptions = {
apiKey: process.env.PENJARO_API_KEY || 'your_api_key',
enableRateLimit: true,
enableThreatIntelCheck: true,
includeDefaultFireholFeed: true,
// Disable SSRF checks for local development
disableDefaultRequestRules: {
ssrf: true,
ssrfHeader: true
}
};
// Initialize Penjaro middleware
console.log('Initializing Penjaro middleware...');
const penjaroMiddleware = await createPenjaroProxy(penjaroOptions);
console.log('Penjaro middleware initialized successfully!');
// Apply standard middleware
app.use(cors());
app.use(helmet());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Apply Penjaro middleware BEFORE routes
app.use(penjaroMiddleware);
// Define your routes
app.get('/', (req, res) => {
res.send('Hello World - Protected by Penjaro');
});
// Error handler
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({
message: 'Something went wrong!'
});
});
// Start server
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
} catch (error) {
console.error('Failed to start server:', error);
process.exit(1);
}
}
startServer();Proxy Mode
// proxy-mode.ts
import express from 'express';
import { createPenjaroProxy, PenjaroConfigOptions } from 'penjaro-network-security-library-javascript';
import dotenv from 'dotenv';
dotenv.config();
// In proxy mode, we need two servers:
// 1. The target server (your actual application)
// 2. The proxy server with Penjaro
// 1. First, the target server (this would be your actual app)
const targetApp = express();
const TARGET_PORT = process.env.TARGET_PORT || 8080;
// Define your backend routes
targetApp.get('/', (req, res) => {
res.send('Hello from target server');
});
targetApp.get('/api/data', (req, res) => {
res.json({ message: 'This is protected data' });
});
// Start the target server
targetApp.listen(TARGET_PORT, () => {
console.log(`Target server running on port ${TARGET_PORT}`);
});
// 2. Now, the proxy server with Penjaro
async function startProxy() {
try {
// Configure Penjaro in proxy mode
const penjaroOptions: PenjaroConfigOptions = {
apiKey: process.env.PENJARO_API_KEY || 'your_api_key',
// This is what activates proxy mode
targetServer: `http://localhost:${TARGET_PORT}`,
// Rate limiting
enableRateLimit: true,
rateLimitPoints: 100,
rateLimitDuration: 60,
// Response analysis (only available in proxy mode)
enableResponseAnalysis: true,
enableDataLeakChecks: true,
enableVerboseErrorChecks: true,
// Disable SSRF for local development
disableDefaultRequestRules: {
ssrf: true,
ssrfHeader: true
}
};
// Create the proxy server
const proxyApp = express();
// Initialize Penjaro proxy
const penjaroProxy = await createPenjaroProxy(penjaroOptions);
// Apply Penjaro proxy middleware
proxyApp.use(penjaroProxy);
// Start the proxy server
const PROXY_PORT = process.env.PORT || 3000;
proxyApp.listen(PROXY_PORT, () => {
console.log(`Penjaro proxy running on port ${PROXY_PORT}`);
console.log(`Forwarding to target server at http://localhost:${TARGET_PORT}`);
});
} catch (error) {
console.error('Failed to start proxy server:', error);
process.exit(1);
}
}
startProxy();NestJS
Middleware Mode
// penjaro.config.ts
import { PenjaroConfigOptions } from 'penjaro-network-security-library-javascript';
export const penjaroConfig: PenjaroConfigOptions = {
apiKey: process.env.PENJARO_API_KEY || 'your_api_key',
enableRateLimit: true,
rateLimitPoints: 60,
rateLimitDuration: 60,
enableThreatIntelCheck: true,
includeDefaultFireholFeed: true,
// Disable SSRF detection for local development
disableDefaultRequestRules: {
ssrf: true,
ssrfHeader: true
},
// Custom request rules
customRequestRulePatterns: {
sql: [/union\s+select/i, /exec\s+xp_cmdshell/i],
xss: [/<script>.*<\/script>/i]
}
};// penjaro.module.ts
import { Module, DynamicModule } from '@nestjs/common';
import { PenjaroService } from './penjaro.service';
import { PenjaroConfigOptions } from 'penjaro-network-security-library-javascript';
@Module({})
export class PenjaroModule {
static register(options: PenjaroConfigOptions): DynamicModule {
return {
module: PenjaroModule,
providers: [
{
provide: 'PENJARO_OPTIONS',
useValue: options,
},
PenjaroService,
],
exports: [PenjaroService],
};
}
}// app.module.ts
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { PenjaroModule } from './penjaro/penjaro.module';
import { PenjaroMiddleware } from './penjaro/penjaro.middleware';
import { penjaroConfig } from './penjaro/penjaro.config';
@Module({
imports: [
PenjaroModule.register(penjaroConfig),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(PenjaroMiddleware)
.exclude('health', 'metrics') // Exclude monitoring endpoints
.forRoutes('*');
}
}Proxy Mode
// main.ts (Proxy mode)
import { NestFactory } from '@nestjs/core';
import { ExpressAdapter } from '@nestjs/platform-express';
import { AppModule } from './app.module';
import express from 'express';
import { createPenjaroProxy } from 'penjaro-network-security-library-javascript';
async function bootstrap() {
// First, start the target application
const targetApp = express();
const targetServer = await NestFactory.create(
AppModule,
new ExpressAdapter(targetApp),
);
const TARGET_PORT = process.env.TARGET_PORT || 8080;
await targetServer.listen(TARGET_PORT);
console.log(`Target server running on port ${TARGET_PORT}`);
// Then create the proxy server with Penjaro
const proxyApp = express();
const penjaroProxy = await createPenjaroProxy({
apiKey: process.env.PENJARO_API_KEY,
targetServer: `http://localhost:${TARGET_PORT}`,
enableResponseAnalysis: true,
enableDataLeakChecks: true,
enableVerboseErrorChecks: true,
disableDefaultRequestRules: {
ssrf: true,
ssrfHeader: true
}
});
proxyApp.use(penjaroProxy);
const PROXY_PORT = process.env.PORT || 3000;
proxyApp.listen(PROXY_PORT, () => {
console.log(`Penjaro proxy running on port ${PROXY_PORT}`);
console.log(`Forwarding to NestJS server at http://localhost:${TARGET_PORT}`);
});
}
bootstrap();Koa
Middleware Mode
import Koa from 'koa';
import bodyParser from 'koa-bodyparser';
import { createPenjaroAdapter, Framework } from 'penjaro-network-security-library-javascript/dist/adapters';
import dotenv from 'dotenv';
dotenv.config();
const app = new Koa();
const PORT = process.env.PORT || 3000;
async function startServer() {
try {
// Initialize Penjaro middleware for Koa
const penjaroMiddleware = await createPenjaroAdapter(Framework.KOA, {
apiKey: process.env.PENJARO_API_KEY,
enableRateLimit: true,
enableThreatIntelCheck: true,
includeDefaultFireholFeed: true,
disableDefaultRequestRules: {
ssrf: true,
ssrfHeader: true
}
});
// Apply Penjaro middleware first (before other middleware)
app.use(penjaroMiddleware);
// Apply other middleware
app.use(bodyParser());
// Define your routes
app.use(async (ctx) => {
if (ctx.path === '/') {
ctx.body = { message: 'Hello World - Protected by Penjaro' };
} else if (ctx.path === '/api/data') {
ctx.body = { data: 'Sensitive information' };
} else {
ctx.status = 404;
ctx.body = { error: 'Not found' };
}
});
// Start server
app.listen(PORT, () => {
console.log(`Koa server with Penjaro running on port ${PORT}`);
});
} catch (error) {
console.error('Failed to start server:', error);
process.exit(1);
}
}
startServer();Proxy Mode
import Koa from 'koa';
import bodyParser from 'koa-bodyparser';
import express from 'express';
import { createPenjaroProxy } from 'penjaro-network-security-library-javascript';
import dotenv from 'dotenv';
dotenv.config();
// First, create and start the target Koa server
const targetApp = new Koa();
const TARGET_PORT = process.env.TARGET_PORT || 8080;
// Configure target server
targetApp.use(bodyParser());
// Add routes to target server
targetApp.use(async (ctx) => {
if (ctx.path === '/') {
ctx.body = { message: 'Hello from target Koa server' };
} else if (ctx.path === '/api/data') {
ctx.body = {
data: 'Sensitive data',
apiKey: 'secret_api_key_12345' // This should be caught by data leak protection
};
} else {
ctx.status = 404;
ctx.body = { error: 'Not found' };
}
});
// Start target server
targetApp.listen(TARGET_PORT, () => {
console.log(`Target Koa server running on port ${TARGET_PORT}`);
});
// Now create the proxy with Penjaro
async function startProxy() {
try {
// Create Penjaro proxy
const penjaroProxy = await createPenjaroProxy({
apiKey: process.env.PENJARO_API_KEY,
targetServer: `http://localhost:${TARGET_PORT}`,
enableResponseAnalysis: true,
enableDataLeakChecks: true,
enableVerboseErrorChecks: true,
disableDefaultRequestRules: {
ssrf: true,
ssrfHeader: true
}
});
// Create Express app for the proxy
const proxyApp = express();
proxyApp.use(penjaroProxy);
// Start proxy server
const PROXY_PORT = process.env.PORT || 3000;
proxyApp.listen(PROXY_PORT, () => {
console.log(`Penjaro proxy running on port ${PROXY_PORT}`);
console.log(`Forwarding to Koa server at http://localhost:${TARGET_PORT}`);
});
} catch (error) {
console.error('Failed to start proxy server:', error);
process.exit(1);
}
}
startProxy();Fastify
Middleware Mode
import Fastify from 'fastify';
import { createPenjaroAdapter, Framework } from 'penjaro-network-security-library-javascript/dist/adapters';
import dotenv from 'dotenv';
dotenv.config();
const fastify = Fastify({ logger: true });
const PORT = process.env.PORT || 3000;
async function startServer() {
try {
// Initialize Penjaro plugin for Fastify
const penjaroPlugin = await createPenjaroAdapter(Framework.FASTIFY, {
apiKey: process.env.PENJARO_API_KEY,
enableRateLimit: true,
rateLimitPoints: 100,
rateLimitDuration: 60,
disableDefaultRequestRules: {
ssrf: true,
ssrfHeader: true
}
});
// Register Penjaro plugin
await fastify.register(penjaroPlugin);
// Define routes
fastify.get('/', async (request, reply) => {
return { message: 'Hello World - Protected by Penjaro' };
});
fastify.get('/api/data', async (request, reply) => {
return { data: 'Protected data' };
});
// Start server
await fastify.listen({ port: PORT, host: '0.0.0.0' });
console.log(`Fastify server with Penjaro running on port ${PORT}`);
} catch (error) {
console.error('Failed to start server:', error);
process.exit(1);
}
}
startServer();Proxy Mode
import Fastify from 'fastify';
import express from 'express';
import { createPenjaroProxy } from 'penjaro-network-security-library-javascript';
import dotenv from 'dotenv';
dotenv.config();
// First, create and start the target Fastify server
const targetApp = Fastify({ logger: true });
const TARGET_PORT = process.env.TARGET_PORT || 8080;
// Add routes to target server
targetApp.get('/', async () => {
return { message: 'Hello from target Fastify server' };
});
targetApp.get('/api/data', async () => {
return {
user: {
name: 'John Doe',
email: 'john@example.com',
password: 'plaintext_password', // This should be caught by data leak protection
apiKey: 'secret_api_key_12345' // This should be caught by data leak protection
}
};
});
// Start target server
async function startServers() {
try {
await targetApp.listen({ port: TARGET_PORT, host: '0.0.0.0' });
console.log(`Target Fastify server running on port ${TARGET_PORT}`);
// Now create the proxy with Penjaro
const penjaroProxy = await createPenjaroProxy({
apiKey: process.env.PENJARO_API_KEY,
targetServer: `http://localhost:${TARGET_PORT}`,
enableResponseAnalysis: true,
enableDataLeakChecks: true,
enableVerboseErrorChecks: true,
disableDefaultRequestRules: {
ssrf: true,
ssrfHeader: true
}
});
// Create Express app for the proxy
const proxyApp = express();
proxyApp.use(penjaroProxy);
// Start proxy server
const PROXY_PORT = process.env.PORT || 3000;
proxyApp.listen(PROXY_PORT, () => {
console.log(`Penjaro proxy running on port ${PROXY_PORT}`);
console.log(`Forwarding to Fastify server at http://localhost:${TARGET_PORT}`);
});
} catch (error) {
console.error('Failed to start servers:', error);
process.exit(1);
}
}
startServers();Hapi
Middleware Mode
import Hapi from '@hapi/hapi';
import { createPenjaroAdapter, Framework } from 'penjaro-network-security-library-javascript/dist/adapters';
import dotenv from 'dotenv';
dotenv.config();
const PORT = process.env.PORT || 3000;
async function startServer() {
try {
// Create Hapi server
const server = Hapi.server({
port: PORT,
host: 'localhost'
});
// Initialize Penjaro plugin for Hapi
const penjaroPlugin = await createPenjaroAdapter(Framework.HAPI, {
apiKey: process.env.PENJARO_API_KEY,
enableRateLimit: true,
rateLimitPoints: 100,
rateLimitDuration: 60,
disableDefaultRequestRules: {
ssrf: true,
ssrfHeader: true
}
});
// Register Penjaro plugin
await server.register(penjaroPlugin);
// Define routes
server.route({
method: 'GET',
path: '/',
handler: () => {
return { message: 'Hello World - Protected by Penjaro' };
}
});
server.route({
method: 'GET',
path: '/api/data',
handler: () => {
return { data: 'Protected data' };
}
});
// Start server
await server.start();
console.log(`Hapi server with Penjaro running on ${server.info.uri}`);
} catch (error) {
console.error('Failed to start server:', error);
process.exit(1);
}
}
startServer();Proxy Mode
import Hapi from '@hapi/hapi';
import express from 'express';
import { createPenjaroProxy } from 'penjaro-network-security-library-javascript';
import dotenv from 'dotenv';
dotenv.config();
// First, create and start the target Hapi server
async function startServers() {
try {
const TARGET_PORT = process.env.TARGET_PORT || 8080;
// Create target server
const targetServer = Hapi.server({
port: TARGET_PORT,
host: 'localhost'
});
// Add routes to target server
targetServer.route({
method: 'GET',
path: '/',
handler: () => {
return { message: 'Hello from target Hapi server' };
}
});
targetServer.route({
method: 'GET',
path: '/api/data',
handler: () => {
return {
user: {
name: 'John Doe',
email: 'john@example.com',
password: 'plaintext_password', // This should be caught by data leak protection
apiKey: 'secret_api_key_12345' // This should be caught by data leak protection
}
};
}
});
// Start target server
await targetServer.start();
console.log(`Target Hapi server running on ${targetServer.info.uri}`);
// Now create the proxy with Penjaro
const penjaroProxy = await createPenjaroProxy({
apiKey: process.env.PENJARO_API_KEY,
targetServer: `http://localhost:${TARGET_PORT}`,
enableResponseAnalysis: true,
enableDataLeakChecks: true,
enableVerboseErrorChecks: true,
disableDefaultRequestRules: {
ssrf: true,
ssrfHeader: true
}
});
// Create Express app for the proxy
const proxyApp = express();
proxyApp.use(penjaroProxy);
// Start proxy server
const PROXY_PORT = process.env.PORT || 3000;
proxyApp.listen(PROXY_PORT, () => {
console.log(`Penjaro proxy running on port ${PROXY_PORT}`);
console.log(`Forwarding to Hapi server at http://localhost:${TARGET_PORT}`);
});
} catch (error) {
console.error('Failed to start servers:', error);
process.exit(1);
}
}
startServers();Local Development Considerations
When developing locally, you may encounter issues with some security rules, particularly SSRF detection which blocks localhost connections. To solve this, add these settings to your configuration:
const localDevConfig = {
// Other configuration...
// Whitelist localhost and development networks
whitelistIps: ['127.0.0.1', '::1', 'localhost', '192.168.0.0/16'],
// Disable SSRF checks for local development
disableDefaultRequestRules: {
ssrf: true, // Disable SSRF pattern checks
ssrfHeader: true // Disable SSRF header checks
}
};This allows local development while still protecting against other types of attacks like SQL injection and XSS.
License
Currently UNLICENSED. Please contact the author for licensing inquiries.
Support and Contact
For support, feature requests, or bug reports, please contact:
- Author: Ugochukwu Nwajagu
- Repository: GitHub
Response Analysis in Middleware Mode
Penjaro now supports response analysis in middleware mode, allowing you to detect and block responses containing sensitive data or verbose error information. This feature was previously only available in proxy mode, but now can be used in middleware mode as well.
Enabling Response Analysis in Middleware Mode
To enable response analysis in middleware mode, use the enableMiddlewareResponseAnalysis option when creating the middleware:
const { createPenjaroProxy } = require('penjaro-network-security-library-javascript');
// Create the Penjaro middleware with response analysis enabled
const penjaroMiddleware = await createPenjaroProxy({
apiKey: 'your-api-key',
enableMiddlewareResponseAnalysis: true, // Enable response analysis in middleware mode
enableDataLeakChecks: true, // Check for data leaks (credit cards, API keys, etc.)
enableVerboseErrorChecks: true, // Check for verbose error messages (stack traces, etc.)
blockUnsafeResponses: true, // Block unsafe responses and return a 403 error
// Optionally, provide custom patterns and exclusions
customDataLeakPatterns: [
/customer_id["\s]*[:=]\s*["']([0-9]{16})["']/i, // Custom pattern for customer IDs
],
excludePathsFromDataLeakCheck: [
/^\/api\/admin\//i, // Exclude admin API from data leak checks
]
});
// Apply the middleware to your Express app
app.use(penjaroMiddleware);How It Works
When response analysis is enabled in middleware mode, Penjaro:
- Intercepts responses before they are sent to the client
- Analyzes the response content for sensitive data or verbose error information
- If unsafe content is detected and
blockUnsafeResponsesis true, blocks the response and returns a 403 error - Otherwise, allows the response to be sent to the client
This feature works by overriding the Express response object's write and end methods to capture and analyze the response content before it's sent to the client.
Performance Considerations
Response analysis requires buffering the entire response before sending it to the client, which can introduce additional latency and memory usage. It is recommended to:
- Use path exclusions to skip analysis for known safe paths or large responses
- Set the
responseAnalysisMaxSizeoption to limit the maximum size of responses to analyze - Consider disabling this feature for high-throughput APIs where performance is critical