diff --git a/apps/docs/content/guides/self-hosting/self-hosted-envoy.mdx b/apps/docs/content/guides/self-hosting/self-hosted-envoy.mdx index 150cb4a7c54..f4369c1fd3d 100644 --- a/apps/docs/content/guides/self-hosting/self-hosted-envoy.mdx +++ b/apps/docs/content/guides/self-hosting/self-hosted-envoy.mdx @@ -199,6 +199,8 @@ The gateway applies a permissive CORS policy at the virtual-host level: This matches both the current Supabase platform behavior and the previous Kong-based gateway. The auth boundary for Supabase APIs is the `apikey` header rather than the request origin. +The `/pg/` route (direct Postgres introspection via `meta`, gated by the service role key) is the exception: it carries its own stricter per-route CORS override, restricted to `SUPABASE_PUBLIC_URL` and `localhost`/`127.0.0.1` origins, since there's no legitimate reason for this route to be called from an arbitrary third-party origin. + If you customize the `cors:` block in `lds.template.yaml` to enable `allow_credentials: true`, you must restrict `allow_origin_string_match` to specific origins - browsers (and Envoy) reject the combination of credentials with a wildcard origin. diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 33972e9b136..d05807667aa 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -101,6 +101,7 @@ services: SUPABASE_SECRET_KEY: ${SUPABASE_SECRET_KEY:-} ANON_KEY_ASYMMETRIC: ${ANON_KEY_ASYMMETRIC:-} SERVICE_ROLE_KEY_ASYMMETRIC: ${SERVICE_ROLE_KEY_ASYMMETRIC:-} + SUPABASE_PUBLIC_URL: ${SUPABASE_PUBLIC_URL} DASHBOARD_USERNAME: ${DASHBOARD_USERNAME} DASHBOARD_PASSWORD: ${DASHBOARD_PASSWORD} entrypoint: ["/bin/sh", "/docker-entrypoint.sh"] diff --git a/docker/volumes/api/envoy/docker-entrypoint.sh b/docker/volumes/api/envoy/docker-entrypoint.sh index 7836038590f..2c67584a30e 100755 --- a/docker/volumes/api/envoy/docker-entrypoint.sh +++ b/docker/volumes/api/envoy/docker-entrypoint.sh @@ -15,6 +15,7 @@ sed -e "s|\${ANON_KEY}|${ANON_KEY}|g" \ -e "s|\${SERVICE_ROLE_KEY_ASYMMETRIC}|${SERVICE_ROLE_KEY_ASYMMETRIC}|g" \ -e "s|\${SUPABASE_PUBLISHABLE_KEY}|${SUPABASE_PUBLISHABLE_KEY}|g" \ -e "s|\${SUPABASE_SECRET_KEY}|${SUPABASE_SECRET_KEY}|g" \ + -e "s|\${SUPABASE_PUBLIC_URL}|${SUPABASE_PUBLIC_URL}|g" \ -e "s|\${DASHBOARD_BASIC_AUTH}|${DASHBOARD_BASIC_AUTH}|g" \ /etc/envoy/lds.template.yaml > /etc/envoy/lds.yaml diff --git a/docker/volumes/api/envoy/lds.template.yaml b/docker/volumes/api/envoy/lds.template.yaml index d6f5f314a9b..1a3c3451886 100644 --- a/docker/volumes/api/envoy/lds.template.yaml +++ b/docker/volumes/api/envoy/lds.template.yaml @@ -523,6 +523,17 @@ resources: '@type': >- type.googleapis.com/envoy.config.route.v3.FilterConfig disabled: true + envoy.filters.http.cors: + '@type': >- + type.googleapis.com/envoy.extensions.filters.http.cors.v3.CorsPolicy + allow_origin_string_match: + - exact: '${SUPABASE_PUBLIC_URL}' + - safe_regex: + regex: 'https?://(localhost|127\.0\.0\.1)(:[0-9]+)?' + allow_methods: "GET,POST,PUT,PATCH,DELETE,OPTIONS,HEAD" + allow_headers: "*" + expose_headers: "*" + max_age: "3600" - match: prefix: /api/mcp