diff --git a/CLAUDE.md b/CLAUDE.md index 687a08c..f2ca179 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -126,7 +126,7 @@ See README.md for complete `.env` setup. Key variables: - **Neo4j**: `NEO4J_URI`, `NEO4J_USER`, `NEO4J_PASSWORD` - **Storage**: `OBJECT_STORAGE_URI`, `MINIO_ACCESS_KEY`, `MINIO_SECRET_KEY`, `MINIO_OBJECTS_BUCKET_NAME` - **Authorization**: `RESTRICTED_BRANCH_NAME` - branch containing restricted blobs -- **Optional**: `POSTHOG_HOST`, `POSTHOG_PROJECT_API_KEY`, `NODE_ENV`, `ALLOWED_ORIGINS`, `SENSITIVE_REGISTRY_VALUES` +- **Optional**: `POSTHOG_HOST`, `POSTHOG_PROJECT_API_KEY`, `NODE_ENV`, `SENSITIVE_REGISTRY_VALUES` ## Testing Strategy - Jest 30 with ts-jest for TypeScript support diff --git a/README.md b/README.md index 29225db..145bf98 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,6 @@ POSTHOG_PROJECT_API_KEY= # Optional - Environment NODE_ENV=development -ALLOWED_ORIGINS=https://oswatcher.github.io,http://127.0.0.1:8080 # Optional - Registry Filtering # Unused unless the plugin commented out in src/index.ts is re-enabled diff --git a/docs/reference/access-restrictions.md b/docs/reference/access-restrictions.md index a36ceb7..beb3ff0 100644 --- a/docs/reference/access-restrictions.md +++ b/docs/reference/access-restrictions.md @@ -536,7 +536,7 @@ When adding new restrictions: | Rate Limiting | Middleware | All endpoints | Block (429) | Hardcoded (100/min) | Active | | Result Set Limits | GraphQL Schema | All paginated queries | Limit to 5000 | `@limit` directive | Active | | Mutations | GraphQL Schema | Write operations | Block (disabled) | `@mutation(operations: [])` | Active | -| CORS | Middleware | All endpoints | Block | `ALLOWED_ORIGINS` | Active | +| CORS | Middleware | All endpoints | Allow any origin | None | Open by design (no credentials are ever sent) | --- diff --git a/src/index.ts b/src/index.ts index b17725c..a05712b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,6 +17,12 @@ import { createRestRouter } from "./rest-routes.js"; // import { filterSensitiveRegistryValues } from "./registry-response-filter.js"; import express, { Request, Response } from "express"; import { expressMiddleware } from "@as-integrations/express5"; +// The API is public, read-only and unauthenticated: no cookies, no +// Authorization header, nothing a browser could be tricked into attaching. An +// origin allow-list therefore protects nothing (curl ignores CORS entirely) +// while breaking every local frontend and third-party tool. Access control +// that does matter is enforced server-side: rate limiting and restricted-branch +// filtering. import cors from "cors"; import axios from "axios"; import { createServer } from "http"; @@ -61,10 +67,6 @@ const env = cleanEnv(process.env, { default: "development", desc: "Node environment", }), - ALLOWED_ORIGINS: str({ - default: "https://oswatcher.github.io,http://127.0.0.1:8080", - desc: "Comma-separated list of allowed CORS origins", - }), SENSITIVE_REGISTRY_VALUES: str({ default: "", desc: "Comma-separated list of sensitive registry value names to redact", @@ -329,10 +331,7 @@ async function main() { if (isProduction && env.POSTHOG_PROJECT_API_KEY) { app.use( "/events", - cors({ - origin: env.ALLOWED_ORIGINS.split(","), - credentials: true, - }), + cors(), express.raw({ type: "*/*", limit: "10mb" }), async (req: Request, res: Response) => { try { @@ -378,10 +377,7 @@ async function main() { // Blob REST API - mounted before GraphQL app.use( "/blob", - cors({ - origin: env.ALLOWED_ORIGINS.split(","), - credentials: true, - }), + cors(), createRateLimit(100, 60000), // 100 requests per minute express.json({ limit: "1mb" }), createRestRouter( @@ -397,10 +393,7 @@ async function main() { // Apply middleware app.use( "/graphql", - cors({ - origin: env.ALLOWED_ORIGINS.split(","), - credentials: true, - }), + cors(), createRateLimit(100, 60000), // 100 requests per minute express.json({ limit: "1mb" }), expressMiddleware(server, {