# Security Considerations for Exposing FreeLLMAPI on a Network

> Expose FreeLLMAPI on your network securely. Discover defense-in-depth features like hashed tokens, encrypted keys, rate limiting, and cooldowns for safe LLM gateway access.

- Repository: [Tashfeen/freellmapi](https://github.com/tashfeenahmed/freellmapi)
- Tags: best-practices
- Published: 2026-06-30

---

**FreeLLMAPI implements defense-in-depth security through SHA-256 hashed session tokens, AES-GCM encrypted API keys, sliding-window rate limiting, and automatic cooldown mechanisms to safely expose LLM gateways on public or private networks.**

When deploying the `tashfeenahmed/freellmapi` gateway beyond localhost, understanding its built-in safeguards is critical. This self-hosted service acts as a reverse proxy to multiple LLM providers, handling sensitive credentials and user data. The codebase provides multiple layers of protection—ranging from cryptographic storage to intelligent rate limiting—that mitigate common attack vectors when the API is exposed to any network.

## Authentication and Session Management

FreeLLMAPI uses a session-based authentication system for dashboard access. User credentials are never stored in plain text; instead, the system relies on robust hashing algorithms implemented in [`src/lib/password.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/src/lib/password.ts).

The `hashPassword` and `verifyPassword` functions salt and hash passwords before persistence. Upon successful authentication via `verifyCredentials` in [`src/services/auth.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/src/services/auth.ts), the system generates a cryptographically random 256-bit token. Critically, only the **SHA-256 hash** of this token is stored in the database—never the token itself. Subsequent requests validate the presented token against this hash using constant-time comparison to prevent timing attacks.

```typescript
import { createUser, verifyCredentials, createSession } from './services/auth';

// Register a new dashboard user
const user = createUser('admin@example.com', 'SecureP@ssw0rd!');

// Authenticate and establish session
const cred = verifyCredentials('admin@example.com', 'SecureP@ssw0rd!');
if (cred) {
  const token = createSession(cred.userId);
  // Token is sent to client; only its hash persists server-side
}

```

## Transport Layer and Secret Management

The application enforces **TLS encryption** for all communications and centralizes secret handling through environment variables. The [`src/env.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/src/env.ts) module loads configuration at startup, ensuring no API keys or database credentials are hard-coded in the source.

For data at rest, [`src/lib/crypto.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/src/lib/crypto.ts) provides AES-GCM encryption for all provider API keys stored in the SQLite database. This symmetric encryption ensures that even if the database file is exfiltrated, keys remain inaccessible without the encryption key. Additionally, [`src/lib/error-redaction.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/src/lib/error-redaction.ts) automatically scrubs sensitive fields from logs and error responses, preventing accidental secret leakage through stack traces.

```typescript
// Secrets are injected via environment variables only
import { env } from './env';
// env.API_KEY references process.env variables, never hardcoded strings

```

## Rate Limiting and Abuse Mitigation

The gateway implements sophisticated traffic controls in [`src/services/ratelimit.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/src/services/ratelimit.ts) to prevent abuse and manage provider quotas effectively.

### Sliding-Window Quotas

Per-model limits are enforced using sliding-window counters tracked per platform-model-key combination. The system supports per-minute (**rpm**, **tpm**) and per-day (**rpd**, **tpd**) limits. Counters persist in SQLite, ensuring that restarts do not reset usage statistics or allow quota bypass.

The `canMakeRequest` function checks current utilization against configured limits before forwarding any request, while `recordRequest` atomically increments the appropriate counters.

```typescript
import { canMakeRequest, recordRequest } from './services/ratelimit';

const limits = { rpm: 60, rpd: 1000, tpm: 10000, tpd: 100000 };

if (canMakeRequest('openrouter', 'gpt-4o', keyId, limits)) {
  // Forward to provider
  recordRequest('openrouter', 'gpt-4o', keyId);
} else {
  throw new Error('Rate limit exceeded');
}

```

### Automatic Cooldown Escalation

When downstream providers return HTTP 429, 402, or 403 status codes, the system activates an escalating backoff strategy. The `setCooldown` function in [`src/services/ratelimit.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/src/services/ratelimit.ts) applies progressive delays: **2 minutes → 10 minutes → 1 hour → 1 day**. This cooldown state persists in the `rate_limit_cooldowns` table, surviving application crashes and preventing immediate retry storms.

```typescript
import { getCooldownDurationForLimit, setCooldown } from './services/ratelimit';

function handleProviderError(platform, modelId, keyId, limits, retryAfter) {
  const cooldownMs = getCooldownDurationForLimit(
    platform,
    modelId,
    keyId,
    limits,
    retryAfter
  );
  setCooldown(platform, modelId, keyId, cooldownMs);
}

```

### Provider Limit Learning

The system includes a self-hardening mechanism via `learnLimitFromError`. When providers return error messages containing explicit rate-limit information, this function parses the response and updates the internal model catalog with stricter ceilings. This prevents subsequent requests from hitting known limits, effectively learning provider constraints in real time.

```typescript
import { learnLimitFromError } from './services/ratelimit';

try {
  // Provider request
} catch (err) {
  const learned = learnLimitFromError(modelDbId, err);
  if (learned) {
    console.log(`Adjusted limit to ${learned} based on provider feedback`);
  }
}

```

## Input Validation and Data Protection

All database interactions use **parameterized queries** with `?` placeholders, eliminating SQL injection vectors. The codebase contains no string interpolation for SQL commands.

The health monitoring system in [`src/services/health.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/src/services/health.ts) exposes a `/health` endpoint for operational monitoring without revealing internal metrics or sensitive state. Additionally, this service automatically disables API keys that repeatedly fail authentication, reducing the attack surface from brute-force attempts or compromised credentials.

## Summary

- **Cryptographic Storage**: Passwords use salted hashing; API keys use AES-GCM encryption at rest; session tokens store only SHA-256 hashes.
- **Persistent Rate Limiting**: SQLite-backed sliding windows enforce per-model and per-provider quotas across application restarts.
- **Intelligent Backoff**: Automatic cooldown escalation (2min → 1day) triggers on provider errors, with persistent state storage.
- **Self-Hardening**: Real-time parsing of provider error messages tightens rate limits automatically to prevent repeated violations.
- **Injection Prevention**: Parameterized SQL queries and input validation prevent injection attacks.
- **Secret Hygiene**: Environment variable isolation and log redaction prevent credential leakage.

## Frequently Asked Questions

### How does FreeLLMAPI protect stored passwords and session tokens?

Passwords are processed through `hashPassword` in [`src/lib/password.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/src/lib/password.ts) using modern salting and hashing algorithms before storage. For sessions, FreeLLMAPI generates a 256-bit random token for the user but only persists the SHA-256 hash of that token in the database. The original token is transmitted to the client once and then forgotten by the server, ensuring that session database breaches do not compromise active sessions.

### What happens when a downstream provider returns a 429 error?

The system invokes `setCooldown` in [`src/services/ratelimit.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/src/services/ratelimit.ts) to impose an escalating delay on the specific platform-model-key combination. Cooldowns progress from 2 minutes to 10 minutes, then 1 hour, and finally 1 day for repeated violations. This state is stored in the SQLite `rate_limit_cooldowns` table, ensuring the backoff survives server restarts and prevents immediate retry loops.

### Are API keys vulnerable if the database is compromised?

No. API keys are encrypted using AES-GCM via the helpers in [`src/lib/crypto.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/src/lib/crypto.ts) before being written to the SQLite `keys` table. The encryption keys are derived from environment variables loaded at startup ([`src/env.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/src/env.ts)), meaning an attacker with database access alone cannot decrypt the stored provider credentials without also compromising the server's environment configuration.

### Is SQL injection possible in FreeLLMAPI?

No. The codebase exclusively uses parameterized queries with `?` placeholders for all database operations. There is no string concatenation or interpolation used in SQL command construction, effectively neutralizing SQL injection attacks against the SQLite backend.