Skip to content

fix(start-env): reject public-prefixed keys in the server schema - #302

Merged
ryansolid merged 1 commit into
solidjs:nextfrom
brenelz:fix/reject-prefixed-server-env-keys
Aug 11, 2026
Merged

fix(start-env): reject public-prefixed keys in the server schema#302
ryansolid merged 1 commit into
solidjs:nextfrom
brenelz:fix/reject-prefixed-server-env-keys

Conversation

@brenelz

@brenelz brenelz commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Problem

start.env enforces the public-prefix rule one-way only: client keys must carry the VITE_ prefix (or whatever envPrefix selects), but server keys are never checked for having it. Vite bakes every prefixed variable into the browser's import.meta.env regardless of which side of the schema declares it, so this config:

export default {
  server: { VITE_API_SECRET: z.string() },
};

ships the secret to every client through Vite's own channel — silently. The plugin's client-chunk leak scan can't catch it because it only watches the virtual server module's values, not import.meta.env. In dev the full value is served to the browser; in build any client reference to import.meta.env.VITE_API_SECRET inlines it.

Preventing exactly this class of leak is the core promise of start.env, so the gap undermines the feature.

Fix

assertSchemaShape now rejects server keys that carry any configured public prefix, failing fast at config time — mirroring the existing client-side guard — with a message explaining why (server cannot keep a prefixed var secret) and what to do (rename it without the prefix in the schema and the environment, or move it to client if it's public).

Tests

Added examples/start-env/env.serverprefix.ts (fixture, following the existing env.badprefix.ts pattern) and a guard assertion in the start-env suite. Full suite passes locally: 45/45 assertions.

🤖 Generated with Claude Code

…akes every VITE_-prefixed var into the browser's import.meta.env regardless of schema side, so a server-declared VITE_* secret leaked silently through Vite's own channel (the leak scan only watches the virtual server module's values); the prefix rule is now enforced both ways, with a fixture and guard assertion in the start-env suite

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Aug 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 3cbd3f9

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
vite-plugin-solid Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Aug 11, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/vite-plugin-solid@302

commit: 3cbd3f9

@ryansolid ryansolid left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed the gap: on next.24, server: { VITE_API_SECRET: ... } builds silently, and in dev the value is served straight to the browser the moment any client module references import.meta.env.VITE_API_SECRET (verified against a live dev server). Fail-fast at config time is the right call, the message is actionable, and the fixture + guard assertion follow the suite's conventions — full suite passes 45/45 here, and I confirmed the new assertion fails without the src fix. One note: the changeset says the leak scan "only watches the virtual server module's values" and can't catch this — the scan actually does catch the build-referenced case (it matches server values as literals in client chunks); the uncovered surface is dev (no scan) plus short/colliding values. No change needed from you — I'm tightening the changeset wording at merge on our side so the changelog doesn't undersell the existing scan. The guard itself needs no changes.

@ryansolid
ryansolid merged commit 74fb28b into solidjs:next Aug 11, 2026
4 checks passed
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.

2 participants