v1.8.0

jo-inc/camofox-browserv1.8.0Apr 27, 2026by skyfallsin

AI Summary

Adds a global access key for route-level authentication and fixes a critical native memory leak causing orphaned processes.

Key Highlights

  • New `CAMOFOX_ACCESS_KEY` environment variable requires authentication on every route except specific exempted endpoints.
  • Fixed race condition in `browser.close()` that caused orphaned Firefox child processes to survive.
  • Implemented `_forceKillProcessTree()` to clean up orphaned children that escaped the process group.
  • Renamed crash reporter to telemetry with improved deduplication and Cloudflare Worker relay.

New Features

  • Global access key authentication
  • Native memory leak fix
  • Crash reporter renamed to telemetry

Full Release Notes

## Global Access Key

`CAMOFOX_ACCESS_KEY` env var — by @trader-payne (#586)

If you expose camofox beyond loopback — on a VPS, in a Docker network, behind a reverse proxy — you've needed to rely on network-level controls or `CAMOFOX_API_KEY` (which only gates cookie import). There was no single switch to require auth on every route.

Set `CAMOFOX_ACCESS_KEY` and every request must carry `Authorization: Bearer <key>`. Three routes are conditionally exempt:

- `GET /health` — always open (Docker/Fly healthchecks need it)
- `POST /sessions/:userId/cookies` — exempt only when `CAMOFOX_API_KEY` is also set (has its own gate)
- `POST /stop` — exempt only when `CAMOFOX_ADMIN_KEY` is also set (has its own gate)

If the dedicated key for an exempted route is *not* configured, the access key still gates it — defense-in-depth, no accidentally unprotected endpoints.

The access key also works as a superkey on `requireAuth()` routes, so you don't need two tokens in a single request. 401 responses include `WWW-Authenticate: Bearer realm="camofox"` per RFC 7235. Env var values are whitespace-trimmed to prevent copy-paste mistakes.

Fully opt-in. If you don't set the env var, nothing changes.

## Native Memory Leak Fix

`browser.close()` had a race condition that could lose the browser PID, leaving orphaned Firefox child processes alive after the context was torn down. On long-running servers this compounded — ~930MB leaked per orphaned browser tree.

Three fixes: `closeBrowserFully()` serializes concurrent close calls with a shared promise so the PID is never lost, `_forceKillProcessTree()` walks `/proc` to find and SIGKILL orphaned children that escaped the process group, and `cleanupStaleFirefoxProfiles()` sweeps leftover temp directories from `enable_cache: true` sessions on startup.

## Fixes & Improvements

- Crash reporter noise reduction: stable dedup signatures, active-tab gate, per-type rate limits, sleep/suspend false-positive suppression
- npm publishing via OIDC trusted publishing — provenance attestations on every release, no `NPM_TOKEN` secret
- Docker images published to GHCR on release: `docker pull ghcr.io/jo-inc/camofox-browser:1.8.0`

## Thank You

Thanks to @trader-payne for the access key feature.