From 750b25ba77bf477bd290a5da64d84c279398727a Mon Sep 17 00:00:00 2001 From: dtzp555-max Date: Sun, 10 May 2026 06:49:00 +1000 Subject: [PATCH] =?UTF-8?q?chore(release):=20v3.14.0=20=E2=80=94=20securit?= =?UTF-8?q?y=20hardening=20(sessions=20namespacing=20+=20file=20modes=20+?= =?UTF-8?q?=20/api/usage=20scope)=20(#89)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bump version 3.13.0 → 3.14.0. No functional code change in this PR; all three security fixes are already merged in main via PRs #86, #87, #88. This PR covers only metadata + docs: - package.json: version bump to 3.14.0 - CHANGELOG.md: v3.14.0 entry with Features / Behavior changes / Verification / Governance sections - README.md: /api/usage self-scope note in Auth Modes §, API Endpoints table row update, file-mode bullet in Important Notes § cli.js citation N/A: this release PR modifies no server.mjs / setup.mjs / keys.mjs. The three underlying security PRs (#86, #87, #88) each carry their own cli.js-citation-not-applicable disclaimer per PR #75 pattern, as they are OCP-internal access-control, session-state, and file-permission changes with no corresponding cli.js operation. Co-authored-by: dtzp555 Co-authored-by: Claude Sonnet 4.6 --- CHANGELOG.md | 26 ++++++++++++++++++++++++++ README.md | 5 ++++- package.json | 2 +- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e5f4d8..3afcc88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,31 @@ # Changelog +## v3.14.0 — 2026-05-10 + +### Features (security hardening) + +- **Per-key session isolation** (PR #86, S1) — the `sessions` Map in `server.mjs` is now keyed by `${keyName}|${conversationId}` instead of bare `conversationId`. Before this fix, two clients using distinct API keys but the same `session_id` value (e.g. both defaulting to `"default"`) would share the same `cli.js` subprocess and conversation history, creating a cross-tenant leak path. Post-fix each (key, session) pair is isolated end-to-end, extending the per-key cache isolation shipped in v3.13.0 D1 to the session layer. +- **On-disk credential file modes 0700/0600** (PR #87, S2) — `setup.mjs` now creates `~/.ocp` at mode 0700 and both `admin-key` and `ocp.db` at mode 0600. An idempotent `reconcileFileModes()` call in `server.mjs` startup tightens any existing installation to these modes automatically on every launch, so existing prod boxes fix themselves without manual `chmod`. Before this fix, all three files were created at the process's default umask (typically world-readable 0644 / 0755), leaving plaintext credentials readable by other local users. +- **`/api/usage` default scope = self; admin all-keys requires `?all=true`** (PR #88, S3) — the usage endpoint now applies a least-privilege default: anonymous callers receive only their own rows, non-admin authenticated callers receive only their own rows, and admin callers receive only their own rows unless they explicitly pass `?all=true`. When `?all=true` is used, an audit log line is emitted. Before this fix, any admin-token holder could silently enumerate usage data for every key on the server. + +### Behavior changes + +- **Breaking change for admin tooling**: `/api/usage` no longer returns all-keys data by default. Existing cron jobs, dashboards, or scripts that rely on the admin token seeing all-keys output must add `?all=true` to their request URL after upgrading to v3.14.0. +- **File mode reconcile at server startup** logs a one-line notice per path when mode is tightened (e.g. `[security] tightened ~/.ocp/ocp.db → 0600`). No action is required from the operator; the reconcile is idempotent and silent when modes are already correct. +- **`sessions` Map key is now `${keyName}|${conversationId}` internally.** No client-visible wire change — the `session_id` field in request/response is unchanged. + +### Verification + +- Stress-test pass: 11/11 phases including S1/S2/S3 security regression checks (Phase E, I, J). 35-minute sustained run, 60 calls, 0 errors, 0 timeouts. RSS dropped 51→47 MB across the window. Per-key cache isolation, singleflight, cache_control bypass, quota enforcement, file-mode reconcile, and scope guard against escalation all verified against running code. + +### Governance + +- All three PRs (#86, #87, #88) include the explicit `cli.js`-citation-not-applicable disclaimer (per PR #75 pattern) since they are OCP-internal access-control, session-state, and file-permission changes with no corresponding `cli.js` operation to cite. + +### No new env vars / no public API surface change beyond the documented breaking change + +This release adds no new env vars or endpoints. The only externally visible change is the `/api/usage` scope guard (breaking for admin all-keys consumers; see Behavior changes above). + ## v3.13.0 — 2026-05-07 ### Features (cache layer hardening) diff --git a/README.md b/README.md index 5ecdc76..aa61049 100644 --- a/README.md +++ b/README.md @@ -392,6 +392,8 @@ ocp keys revoke son-ipad # Revoke a key | `shared` | `CLAUDE_AUTH_MODE=shared` + `PROXY_API_KEY=xxx` | Everyone shares one key | | `multi` | `CLAUDE_AUTH_MODE=multi` + `OCP_ADMIN_KEY=xxx` | Per-person keys with usage tracking (recommended) | +> **Usage scope (v3.14.0+):** `/api/usage` returns the caller's own rows by default. Admin callers must pass `?all=true` to retrieve data for all keys; doing so emits an audit log line. + ### Anonymous Access (optional) In `multi` mode, the admin can designate a single well-known "anonymous" key that bypasses `validateKey()` and grants public read/write access. This is useful for letting LAN users (or clients like OpenClaw multi-agent setups) connect without individual per-user keys. @@ -460,6 +462,7 @@ When a key exceeds its quota, OCP returns HTTP 429 with a structured error: - Keys are stored in `~/.ocp/ocp.db` (SQLite, zero external dependencies) - Admin key is required for key management API endpoints - The dashboard (`/dashboard`) and health check (`/health`) are always public +- File modes for `~/.ocp` (0700), `admin-key` + `ocp.db` (0600) are auto-tightened at server startup as of v3.14.0 ## Built-in Usage Monitoring @@ -657,7 +660,7 @@ The canonical list lives in [`models.json`](./models.json) — the single source | `/api/keys` | GET/POST | List or create API keys (admin only) | | `/api/keys/:id` | DELETE | Revoke an API key (admin only) | | `/api/keys/:id/quota` | GET/PATCH | View or set per-key quota (admin only) | -| `/api/usage` | GET | Per-key usage stats (`?since=&until=&hours=&limit=`) | +| `/api/usage` | GET | Per-key usage stats (`?since=&until=&hours=&limit=`); returns self only by default — pass `?all=true` (admin only) for all-keys data | | `/cache/stats` | GET | Cache statistics (admin only) | | `/cache` | DELETE | Clear response cache (admin only) | diff --git a/package.json b/package.json index 301c877..2545cc8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "open-claude-proxy", - "version": "3.13.0", + "version": "3.14.0", "description": "OCP (Open Claude Proxy) — use your Claude Pro/Max subscription as an OpenAI-compatible API for any IDE. Works with Cline, OpenCode, Aider, Continue.dev, OpenClaw, and more.", "type": "module", "bin": {