Skip to content

fix(security): move secret env var reads from build time to runtime#478

Open
hendrikheil wants to merge 13 commits into
nuxt-content:mainfrom
hendrikheil:fix/runtime-config-secrets
Open

fix(security): move secret env var reads from build time to runtime#478
hendrikheil wants to merge 13 commits into
nuxt-content:mainfrom
hendrikheil:fix/runtime-config-secrets

Conversation

@hendrikheil

@hendrikheil hendrikheil commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

What and why

Previously, all secret env vars (STUDIO_GITHUB_CLIENT_SECRET, AI_GATEWAY_API_KEY, git tokens, etc.) were read from process.env during nuxt build and baked into the server bundle. This causes two problems:

  • Security - any CI environment that has secrets available at build time ends up with those values as plaintext literals in the .output/server/ artifact. Build artifacts are often cached, stored, or shared in ways that runtime environments aren't.
  • DX - because the AI feature flag was evaluated at build time (if (options.ai?.apiKey)), deploying a generic image without AI_GATEWAY_API_KEY set at build time permanently disables AI, even if the var is present at runtime. Same applies to auth providers.

Approach

A Nitro server plugin (studio-env.ts) now runs at server startup and merges the STUDIO_* env vars into useRuntimeConfig() for any values that aren't already set. All auth routes and session utils read exclusively from useRuntimeConfig(event).studio.*.

The runtimeConfig.studio schema in module.ts is initialised with empty string stubs so Nuxt knows the shape at build time. The plugin fills in real values at startup. Nuxt-native NUXT_STUDIO_* env vars still take precedence over the legacy names.

Backward compatibility

All existing env var names continue to work unchanged. No changes to the nuxt.config.ts configuration API.

Test plan

  • pnpm typecheck passes
  • pnpm test passes
  • pnpm verify passes
  • No secret process.env.* reads remain in auth routes or module setup

@vercel

vercel Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

@hendrikheil is attempting to deploy a commit to the Nuxt Team on Vercel.

A member of the Team first needs to authorize it.

@pkg-pr-new

pkg-pr-new Bot commented Jun 10, 2026

Copy link
Copy Markdown
npm i https://pkg.pr.new/nuxt-studio@478

commit: 693bd6d

@hendrikheil hendrikheil force-pushed the fix/runtime-config-secrets branch from cccd400 to 13f34f7 Compare June 10, 2026 21:56
hendrikheil and others added 10 commits June 11, 2026 00:03
…udio-env plugin

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace direct process.env reads with values from useRuntimeConfig(event).studio.
The studio-env Nitro plugin populates runtimeConfig.studio.auth.github.* from
legacy STUDIO_GITHUB_* env vars at server startup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace direct `process.env.*` reads with values from `useRuntimeConfig(event).studio`. This ensures env vars are properly managed through the studio-env Nitro plugin at server startup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Migrate SSO and git token configuration from direct environment variable reads to runtime config, which is populated by the studio-env Nitro plugin at server startup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace direct process.env reads with values from useRuntimeConfig(event).studio for Google OAuth configuration, Git provider tokens, and moderators list.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add explicit typed objects to runtimeConfig.studio auth blocks so
auth routes can access redirectUrl and moderators without ts-expect-error.
Tighten studio-env.ts casts from Record<string,any> to typed variants.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… rename vars

- auth.github.instanceUrl defaults to 'https://github.com', auth.gitlab.instanceUrl
  defaults to 'https://gitlab.com' — these are not secrets
- AI server routes now only registered when options.ai.apiKey is set at build time;
  users relying on env vars use NUXT_STUDIO_AI_API_KEY (Nuxt-native convention) or
  set apiKey explicitly in nuxt.config.ts
- ai.enabled public flag restored to Boolean(options.ai?.apiKey) at build time;
  studio-env plugin no longer touches AI config
- Rename single-letter variables in studio-env.ts for readability

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@hendrikheil hendrikheil force-pushed the fix/runtime-config-secrets branch from 13f34f7 to 693bd6d Compare June 10, 2026 22:03
hendrikheil and others added 3 commits June 11, 2026 00:14
…through entries

- studio-env.ts: replace custom fill() helper with defu for env var defaults
- auth routes: remove credential passthroughs from mergeConfig that echoed values
  already present in the first argument (clientId, clientSecret, applicationId, etc.)
- sso.get.ts: drop mergeConfig entirely, inline the redirectUrl→redirectURL rename
- module.ts: remove redundant instanceUrl fallbacks now covered by module defaults

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- auth.ts: restore upstream version (logger tag, git token check, Google moderator validation)
- studio-env.ts: replace Object.assign+defu with direct assignment

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ssertions

- only set publicUrl to public/ dir when not using external media storage
- fix non-null assertions on instanceUrl to avoid unsafe optional chain pattern

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@hendrikheil

Copy link
Copy Markdown
Contributor Author

@larbish can you rerun the module / build job? Seems to have been a transient Cloudflare error

@hendrikheil hendrikheil marked this pull request as ready for review June 11, 2026 08:24
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