Skip to content

Fix wildcard CORS, restrict credential file permissions, add body size limit#7

Open
glitch-ux wants to merge 1 commit intoRelayPlane:mainfrom
glitch-ux:fix/security-hardening
Open

Fix wildcard CORS, restrict credential file permissions, add body size limit#7
glitch-ux wants to merge 1 commit intoRelayPlane:mainfrom
glitch-ux:fix/security-hardening

Conversation

@glitch-ux
Copy link
Copy Markdown

Summary

Three quick security hardening fixes that address vulnerabilities in how the proxy handles CORS, stores credentials, and accepts request bodies.

1. Replace wildcard CORS with localhost allowlist

File: src/server.ts

The proxy currently sets Access-Control-Allow-Origin: * on every response. This means any website can make cross-origin requests to the proxy and read the responses — including sensitive endpoints like /v1/budget, /v1/runs/{id}, /v1/policies, and /v1/simulate/* which return cost data, routing decisions, and policy evaluations.

Attack scenario: A user visits a malicious webpage. JavaScript on that page fetches http://localhost:4100/v1/budget and silently exfiltrates the user's budget state, run traces, and policy configuration.

Fix: Replace * with an explicit allowlist of localhost origins (localhost:4100, localhost:3000, and 127.0.0.1 equivalents). The Access-Control-Allow-Origin header is only set when the request's Origin matches the allowlist. Cross-origin requests from non-localhost origins are blocked by the browser's same-origin policy.

2. Restrict credential and config file permissions to owner-only

Files: src/credentials.ts, src/config.ts

credentials.json and config.json (which can contain api_key) are written with Node's default file permissions (typically 0644 on Unix), making them readable by any local user. The .relayplane/ directory is also created with default permissions.

Attack scenario: On a shared system (CI runner, dev server, multi-user workstation), any user can cat ~/.relayplane/credentials.json and steal API keys for Anthropic, OpenAI, or other providers.

Fix:

  • Create ~/.relayplane/ directory with mode 0700 (owner-only access)
  • Write credentials.json and config.json with mode 0600 (owner read/write only)
  • Applied consistently across all write paths: saveAgentCredentials(), saveConfig(), and setApiKey()

3. Add 1 MB request body size limit

File: src/server.ts

The readBody() helper accumulates the request body with body += chunk without any size check. All POST endpoints that parse JSON bodies (/v1/policies/test, /v1/simulate/policy, /v1/simulate/routing, /v1/chat/completions, etc.) are vulnerable.

Attack scenario: An attacker sends a multi-gigabyte POST body to any endpoint, exhausting server memory and crashing the proxy (OOM).

Fix: Track accumulated byte size in readBody() and destroy the request with a clear error message if it exceeds 1 MB. The limit is defined as a static class constant (MAX_BODY_SIZE) for easy adjustment.

Test plan

  • TypeScript compiles clean (npx tsc --noEmit — zero errors)
  • Full test suite: 802 passed, 40 failed (all failures are pre-existing: missing optional deps like @relayplane/learning-engine, missing tsx binary — unrelated to these changes)
  • Middleware tests pass (5/5) — confirms proxy request handling still works
  • Manual: verify the dashboard at localhost:4100 still loads (CORS allows localhost:4100)
  • Manual: verify a cross-origin fetch from a different origin is blocked
  • Manual: verify sending a >1MB POST body returns a clear error instead of hanging
  • Manual: verify ~/.relayplane/credentials.json is created with 600 permissions on a fresh setup

…est body size limit

- Replace Access-Control-Allow-Origin: * with a localhost-only allowlist
  (localhost:4100, localhost:3000, and 127.0.0.1 equivalents) to prevent
  cross-site data exfiltration from any malicious webpage.

- Write credentials.json and config.json with mode 0600 (owner-only)
  and create the .relayplane directory with mode 0700. Previously these
  files were created with default 0644 permissions, allowing any local
  user to read API keys.

- Add a 1 MB size limit to readBody() to reject oversized payloads
  before they exhaust server memory. Protects simulation and policy
  test endpoints from denial-of-service via large JSON bodies.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant