Skip to content

Commit 5758a5d

Browse files
committed
fix(server): make CORS origin env-driven, restore CORS_AT_INGRESS interlock
Replace the hardcoded origin:'*' with CORS_ORIGIN (default '*', accepts a comma-separated list) so the allowed origin lives in the deployment values instead of the source — keeps published charts publicly embeddable while letting reusers restrict it. Re-enable the CORS_AT_INGRESS guard so the app skips its own CORS middleware when the ingress handles it, avoiding duplicate Access-Control-Allow-Origin headers. Drop the dead commented-out CORS code. Chart: expose CORS_ORIGIN in server.env and remove the redundant CORS_AT_INGRESS default (the server-deployment template injects it on ingress.cors.enabled, so keeping it produced a duplicate env var).
1 parent 08d2359 commit 5758a5d

4 files changed

Lines changed: 32 additions & 22 deletions

File tree

charts/graph-italia/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,8 @@ server:
197197
PORT: "3003"
198198
DATABASE_URL: "postgresql://user:pass@host:5432/db"
199199
JWT_SECRET: "your-secret"
200-
DOMAINS: "https://graph-italia.example.com"
200+
CORS_ORIGIN: "*" # CORS allowed origin(s); "*" = public embeds, or a comma-separated list to restrict
201+
DOMAINS: "https://graph-italia.example.com" # trusted origins for CSRF (not CORS)
201202
UPLOAD_SIZE_LIMIT: "15mb"
202203
ROUTES_PREFIX: "/api"
203204
SENDER_EMAIL: "noreply@example.com"

charts/graph-italia/values.yaml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,14 @@ server:
203203
UPLOAD_SIZE_LIMIT: "15mb"
204204
ROUTES_PREFIX: ""
205205
DATABASE_URL: ""
206-
# Set to "true" automatically when ingress.cors.enabled=true to avoid duplicate CORS headers
207-
CORS_AT_INGRESS: ""
206+
# CORS allowed origin(s) for the app-level CORS middleware.
207+
# "*" keeps published charts/dashboards embeddable from any site; set a single
208+
# origin or a comma-separated list to restrict it. Ignored when CORS is handled
209+
# at the ingress (see ingress.cors below, which sets CORS_AT_INGRESS).
210+
CORS_ORIGIN: "*"
211+
# NOTE: CORS_AT_INGRESS is injected automatically by the server-deployment
212+
# template when ingress.cors.enabled=true — do not set it here (it would
213+
# produce a duplicate env var).
208214
# Add other environment variables as needed
209215
# Horizontal Pod Autoscaler
210216
autoscaling:

packages/server/index.ts

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -54,31 +54,30 @@ const allowHeaders = ["Content-Type", "Authorization", "x-project-id", "Access-C
5454

5555
// CORS must be first so OPTIONS preflights are answered before any other
5656
// middleware (rate limiter, CSRF, auth) can return a response without headers.
57+
//
58+
// Origin is env-driven, never hardcoded: defaults to "*" so that published
59+
// charts and dashboards stay embeddable from any site, and can be restricted
60+
// via CORS_ORIGIN (a single origin or a comma-separated list) when reusing
61+
// this project in a closed context. Public endpoints serve read-only data, so
62+
// credentials are disabled — the auth cookie is same-origin only.
63+
const corsOrigin = process.env.CORS_ORIGIN?.includes(",")
64+
? process.env.CORS_ORIGIN.split(",").map((o) => o.trim())
65+
: process.env.CORS_ORIGIN || "*";
66+
5767
const publicCors = cors({
58-
origin: "*",
68+
origin: corsOrigin,
5969
credentials: false,
6070
allowMethods,
6171
allowHeaders,
6272
});
6373

64-
// const privateCors = cors({
65-
// origin: ["https://developers-italia.vercel.app", ...whitelist],
66-
// credentials: true,
67-
// allowMethods,
68-
// allowHeaders,
69-
// });
70-
71-
// if (!process.env.CORS_AT_INGRESS) {
72-
app.use("*", publicCors);
73-
// }
74-
75-
// if (!isDev) {
76-
// app.use(`/charts/*`, publicCors);
77-
// app.use(`/dashboards/*`, publicCors);
78-
// } else {
79-
// console.warn("cors is enabled for all routes in development mode. make sure to restrict this in production!");
80-
// app.use("/*", privateCors);
81-
// }
74+
// When CORS is handled at the ingress (Helm: ingress.cors.enabled=true injects
75+
// CORS_AT_INGRESS=true), the app skips its own CORS middleware so the response
76+
// doesn't carry duplicate Access-Control-Allow-Origin headers, which browsers
77+
// reject.
78+
if (!process.env.CORS_AT_INGRESS) {
79+
app.use("*", publicCors);
80+
}
8281

8382
// Prometheus metrics collection
8483
app.use("*", metricsMiddleware);

packages/server/sample.env

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
DATABASE_URL=postgresql://postgres:postgres@db:5432/postgres
22
ROUTES_PREFIX=/api
3+
# CORS allowed origin(s) for the public API. "*" (default) keeps charts embeddable
4+
# anywhere; set a single origin or a comma-separated list to restrict it.
5+
CORS_ORIGIN="*"
6+
# Trusted first-party origins for CSRF protection (comma-separated). Not the CORS list.
37
DOMAINS="http://localhost:3000,http://localhost:3003,http://127.0.0.1:3000,http://127.0.0.1:3003"
48
JWT_SECRET="una-chiave-segreta-lunga-e-casuale"
59
APP_URL="http://127.0.0.1:3000"

0 commit comments

Comments
 (0)