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 🙏

© 2026 – Pkg Stats / Ryan Hefner

perishable

v1.0.1

Published

A secure proxy for OpenAI (and compatible) APIs that prevents key abuse. You will never have to worry about exposing your keys when vibecoding.

Readme

Perishable

A secure proxy for OpenAI API that prevents key abuse while maintaining full SDK compatibility.

Overview

Perishable is a library that allows frontend applications to use OpenAI's API without exposing API keys. It consists of two parts:

  1. A client-side library that acts as a shim layer over the OpenAI SDK
  2. A proxy server that validates requests and forwards them to OpenAI

The library includes multiple security features to prevent API abuse:

  • Client fingerprinting with entropy collection
  • Session management
  • Rate limiting
  • Request validation

Installation

npm install perishable

CLI Usage

Perishable includes a command-line interface for easily running the proxy server:

# Install globally to use the CLI directly
npm install -g perishable

# Run with environment variable for API key
OPENAI_API_KEY=your-api-key perishable-proxy

# Run with a configuration file
perishable-proxy --config ./perishable.config.json

# Run with specific options
OPENAI_API_KEY=your-api-key perishable-proxy --port 8080

# Run with a custom OpenAI-compatible API
OPENAI_API_KEY=your-api-key OPENAI_BASE_URL=https://api.anthropic.com/v1 perishable-proxy

The CLI will automatically look for a perishable.config.json file in the current directory if no config file is specified.

For detailed CLI documentation, see CLI Usage Guide.

Usage

Server Setup

First, set up the Perishable proxy server:

import { server } from 'perishable';

const serverInstance = new server.PerishableServer({
  openaiApiKey: process.env.OPENAI_API_KEY,
  port: 3000,
  rateLimitOptions: {
    points: 100,        // requests
    duration: 60,       // per 60 seconds
    blockDuration: 60   // block for 60 seconds when rate limit exceeded
  },
  clientValidationOptions: {
    enableFingerprintValidation: true,
    maxSessionsPerFingerprint: 5,
    enableEntropyValidation: true,
    minEntropyThreshold: 50
  },
  sessionOptions: {
    timeout: 30 * 60 * 1000 // 30 minutes
  },
  securityOptions: {
    enableCORS: true,
    allowedOrigins: ['*']
  }
});

serverInstance.start();

Client Setup

Then, use the client library in your frontend application:

import { client } from 'perishable';

// Initialize entropy collection for enhanced security
client.PerishableOpenAI.initEntropyCollection();

const perishableClient = new client.PerishableOpenAI({
  proxyUrl: 'http://localhost:3000',
  abusePreventionOptions: {
    maxRetries: 3,
    retryDelay: 1000,
    requestTimeout: 30000,
    requireUserInteraction: true
  },
  sessionOptions: {
    expiryBuffer: 5 * 60 * 1000 // 5 minutes
  }
});

// Create a chat completion
const response = await perishableClient.createChatCompletion({
  model: 'gpt-3.5-turbo',
  messages: [
    {
      role: 'user',
      content: 'Hello!'
    }
  ]
});

const data = await response.json();
console.log(data.choices[0].message.content);

Direct API Access (for development/testing)

For development and testing, you can use the Perishable client with a direct OpenAI API key:

import { client } from 'perishable';

const perishableClient = new client.PerishableOpenAI({
  proxyUrl: 'http://localhost:3000',
  apiKey: process.env.OPENAI_API_KEY // Direct API access
});

// This will use the OpenAI API directly, bypassing the proxy
const response = await perishableClient.createChatCompletion({
  model: 'gpt-3.5-turbo',
  messages: [
    {
      role: 'user',
      content: 'Hello!'
    }
  ]
});

Security Features

Client Fingerprinting with Entropy Collection

Perishable generates a fingerprint for each client based on various browser characteristics and requires user interaction entropy:

  • User agent
  • Language
  • Timezone
  • Screen dimensions
  • Installed plugins
  • Canvas rendering
  • WebGL capabilities
  • Mouse movements
  • Key presses

The client must provide sufficient entropy through user interactions before a session can be created:

  • Minimum 10 mouse movements OR
  • Minimum 3 key presses OR
  • 5 seconds of page activity

Session Management

Clients must create sessions before making API requests:

  • Sessions expire after 30 minutes of inactivity (configurable)
  • Each session is tied to a specific client fingerprint
  • Sessions are automatically cleaned up

Rate Limiting

The proxy server implements rate limiting:

  • By default, 100 requests per minute per client (configurable)
  • Automatic IP and session-based tracking
  • Configurable block duration when rate limit is exceeded

Client Validation

The proxy server validates clients:

  • Fingerprint validation (optional but recommended)
  • Entropy validation (requires user interaction)
  • Session validation
  • Request validation

API Endpoints

POST /session

Create a new session.

Request Body:

{
  "fingerprint": "client-fingerprint-string",
  "entropyData": "entropy-data-string"
}

Response:

{
  "sessionId": "session-id-string",
  "expiresAt": 1234567890
}

POST /openai/*

Proxy endpoint for OpenAI API calls.

Headers:

  • X-Session-ID: Session ID obtained from /session endpoint

Response: Forwarded from OpenAI API.

GET /health

Health check endpoint.

Response:

{
  "status": "ok",
  "timestamp": "2023-01-01T00:00:00.000Z",
  "uptime": 1234.56
}

Configuration

Server Options

interface PerishableServerOptions {
  openaiApiKey: string;
  openaiBaseUrl?: string;  // Base URL for OpenAI API (default: https://api.openai.com/v1)
  port?: number;
  
  rateLimitOptions?: {
    points?: number;        // Number of requests allowed
    duration?: number;      // Time window in seconds
    blockDuration?: number; // Block duration in seconds
  };
  
  clientValidationOptions?: {
    enableFingerprintValidation?: boolean;  // Enable fingerprint validation
    maxSessionsPerFingerprint?: number;     // Max sessions per fingerprint
    enableEntropyValidation?: boolean;      // Enable entropy validation
    minEntropyThreshold?: number;           // Minimum entropy threshold
  };
  
  sessionOptions?: {
    timeout?: number; // Session timeout in milliseconds
  };
  
  securityOptions?: {
    enableCORS?: boolean;    // Enable CORS
    allowedOrigins?: string[]; // Allowed origins for CORS
  };
}

Configuration File

You can create a perishable.config.json file in your project directory to configure the server:

{
  "port": 3000,
  "rateLimitOptions": {
    "points": 100,
    "duration": 60,
    "blockDuration": 60
  },
  "clientValidationOptions": {
    "enableFingerprintValidation": true,
    "maxSessionsPerFingerprint": 5,
    "enableEntropyValidation": true,
    "minEntropyThreshold": 50
  },
  "sessionOptions": {
    "timeout": 1800000
  },
  "securityOptions": {
    "enableCORS": true,
    "allowedOrigins": ["*"]
  }
}

CLI Options

perishable-proxy [options]

Options:
  -c, --config <path>     Path to configuration file
  -p, --port <number>     Port to run the server on
  --openai-api-key <key>  OpenAI API key
  -h, --help              Display help for command
  -V, --version           Display version information

Client Options

interface PerishableClientOptions {
  proxyUrl: string;
  apiKey?: string;
  
  abusePreventionOptions?: {
    maxRetries?: number;          // Maximum number of retries
    retryDelay?: number;          // Delay between retries in ms
    requestTimeout?: number;      // Request timeout in ms
    requireUserInteraction?: boolean; // Require user interaction for entropy
  };
  
  sessionOptions?: {
    expiryBuffer?: number; // Buffer time before session expiry (ms)
  };
}

Testing

Perishable includes a comprehensive test suite:

Unit Tests

npm test

Client Tests

npm test src/client/__tests__/perishable-client.test.ts

Building

npm run build

Linting

npm run lint

Security Approach

Perishable uses a defense-in-depth security approach:

  1. Server-side Validation - All critical security checks happen on the server
  2. Client Fingerprinting - Identifies and tracks clients to prevent abuse
  3. Entropy Collection - Requires user interaction to prevent automated abuse
  4. Session Management - Time-limited sessions with automatic expiration
  5. Rate Limiting - Prevents abuse through request throttling
  6. CORS Protection - Controls which origins can access the API

Obfuscation

Perishable does not rely on obfuscation for security because:

  • Client-side obfuscation provides minimal security since all code is visible in the browser
  • Server-side obfuscation is unnecessary since server code should not be publicly accessible
  • True security comes from API-level protections, not code obfuscation

Instead, Perishable focuses on strong server-side validation and multiple layers of protection.

License

MIT