-
Notifications
You must be signed in to change notification settings - Fork 5
Description
Problem
The Vite plugin currently exposes all environment variables from the schema to client code, including server-only variables like PORT. This happens because the plugin doesn't filter to only VITE_* prefixed variables.
Current Behavior
In apps/playgrounds/vite/vite.config.ts, a single schema Env is reused for both:
- Server-side validation (via
arkenv(Env, loadEnv(...))) - Client-side exposure (via
arkenvVitePlugin(Env))
The schema includes:
PORT(server-only, unprefixed)VITE_MY_VAR,VITE_MY_NUMBER,VITE_MY_BOOLEAN(client-safe, prefixed)
However, the plugin implementation in packages/vite-plugin/src/index.ts does:
const env = createEnv(options, loadEnv(...))
const define = Object.fromEntries(
Object.entries(env).map(([key, value]) => [
`import.meta.env.${key}`,
JSON.stringify(value),
])
);This means every key in the schema (including PORT) ends up as import.meta.env.* in the client bundle, not just the VITE_* ones.
Impact
- Security risk: Server-only variables (like
PORT, database URLs, API keys, etc.) can be accidentally exposed to client code - Misleading documentation: The comment in
vite.config.tssays unprefixed variables are "server-only and not exposed to client code", but this is not true - User confusion: Users following the example pattern may accidentally expose sensitive variables in production
Evidence
You can see PORT is accessible in the client in apps/playgrounds/vite/src/App.tsx:
<p>My port: {String(import.meta.env.PORT)}</p>Proposed Solutions
Choose one of the following approaches:
Option 1: Split the schema (Recommended)
- Create a
ServerEnvschema (e.g.,PORT) for use witharkenv() - Create a
ClientEnvschema (onlyVITE_*variables) for use witharkenvVitePlugin() - Update the example to show this pattern
Option 2: Filter in the plugin
- Modify
arkenvVitePluginto automatically filter to onlyVITE_*prefixed keys - Update documentation and comments to reflect this behavior
- This would make the plugin safer by default
Option 3: Update example only
- Keep
Envclient-only in the example - Introduce a separate server-only schema in documentation
- This is the simplest fix but doesn't solve the underlying plugin behavior
Additional Note
For VITE_MY_BOOLEAN, the current implementation coerces anything other than "true" to false. If you want stricter validation, consider explicitly validating "true"/"false" and throwing an error on invalid values rather than silently coercing.
Files Affected
apps/playgrounds/vite/vite.config.ts(lines 10-15, 19-20, 28-30)packages/vite-plugin/src/index.ts(lines 23, 26-31)apps/playgrounds/vite/src/App.tsx(lines 44-48 - test code showing the leak)