npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

penjaro-network-security-library-javascript

v1.2.5

Published

Penjaro AI-powered proxy middleware for preventive cybersecurity

Readme

Penjaro Network Security Middleware

npm version License: UNLICENSED

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.js models
  • 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 features

Core 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: '[email protected]',
      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: '[email protected]',
            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:

  1. Intercepts responses before they are sent to the client
  2. Analyzes the response content for sensitive data or verbose error information
  3. If unsafe content is detected and blockUnsafeResponses is true, blocks the response and returns a 403 error
  4. 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 responseAnalysisMaxSize option to limit the maximum size of responses to analyze
  • Consider disabling this feature for high-throughput APIs where performance is critical