-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
$env/dynamic/public becomes $env/static/public for pre-rendered pages, breaking app and exposing information #10008
Comments
If the rationale is that pre-rendered pages should use |
It would be a shame to simply preclude the use of two useful features within the same app. From what I can tell, the dynamic public env values are embedded into the HTML page output. They are then 'loaded' from an external JS file which uses a rather odd looking snippet that just exports the thing already defined in the embedded JS. Example JS embedded in the HTML page: __sveltekit_4vbc3j = {
base: new URL(".", location).pathname.slice(0, -1),
env: {"PUBLIC_API_KEY":"proper-public-key"}
}; public.[hash].js file: const e=globalThis.__sveltekit_4vbc3j.env;export{e}; The problem happens because the wrong thing is embedded in the pre-rendered pages, but if the Note: I tried using .env.development and while it stops any dev-mode values being exposed, it still causes errors because the env values are then undefined instead on pre-rendered pages. If you use dynamic envs and pre-rendered pages, your app is going to break but you may not notice because it depends on the page people land on first. And the reason for not using .env / static values is that the correct runtime versions may not even be known at build time. If an app is deployed using automated infrastructure (e.g. Terraform) then cross-references between services can be configured by setting env values for the runtime services. This way the exact same build can be tested and deployed to dev / test / prod without having to configure and build for each separately. A docker image needs to be built before the deploy can happen. |
I feel like it makes sense that the static adapter is using the values it found where it was built, since the point of the static adapter is that you can deploy it to hosts that don't have a server and only serve files |
No, this is NOT about the static adapter. AFAIK it can only ever use static values. This is about the combination of adapter-node (or potentially any adapter with SSR support) + dynamic env + pre-renderring. The three things together are incompatible / breaks the app. |
I don't see how we could fix this with pages that use prerendering & some environment variable. For example say I wanted to fetch an api on a prerendered page, it would use the credentials I have at build time which makes sense. And then I have the same api but on a SSR page it would use the credentials I have at build/runtime (depending on $env/static or dynamic). I think that for pages in which you want to take advantage of |
I'm pretty sure it can be fixed. Don't put the env values in the HTML, put them in the JS (that is loaded anyway). Any JS module using the values has to wait for that env JS to load anyway, so embedding values into HTML isn't really saving anything IMO - in fact it's inefficient as they have to be served out many more times. I can create an endpoint in my app to serve up the values, but surely the idea of the |
I think I mostly agree that it should actually be gotten dynamically rather than prerendered into the page as prerendering it into the page makes it static. Folks who want to prerender dynamic env vars should probably update their apps to use static env vars or to pass in a prop representing the value instead. That'd be a little tricky to implement. We can't put the values into the JS as you suggest because the JS is also created at build time. We'd need to implement a built-in endpoint. Private env vars don't have this issue because they're only used on the server. I almost think we should just get rid of |
It's not really whether there should be a pre-render option or not, I don't think there is any case to be made for it - unless the app is built on the server it will run on (which would be a bit weird) or you happen to have a local Pre-rendering stops the "dynamic" part doing what it says on the tin. The purpose of dynamic should always be to reflect that values set on the server, not anything that is compiled into the app, otherwise you'd just use the static option. |
I'm not sure how to proceed here. Runtime variables can also be added at built time, for example you could set a node env variable in your Vercel project dashboard which is used at build time. Or take the use case in #10737 where |
It doesn't really change whether it's a static or dynamic variable. How does it factor into this decision?
You can still do it. We simply won't give you a way to do it that comes with a footgun. But it's really not hard to implement yourself and we could add some documentation around it. |
Thinking out loud:
That solves the easy part of the problem. The trickier part is subsequently populating Since a prerendered page could access Which means that in the prerendered case I don't think we have a choice other than to serve env vars dynamically, from a Mitigations:
|
Will |
Yes |
(except in the |
#11277 fixes this |
Describe the bug
The docs for
$env/dynamic/public
state:For pre-rendered pages though, this is incorrect and misleading. They actually behave more like
$env/static/public
with values coming from build-time.env
files used. Not only does this risk exposing information that wasn't intended to be exposed but the behavior of the app becomes indeterminate because the values used in the app depend on the order of page navigation.As an example, I'm using
$env/dynamic/public
to read Firebase config from runtime environment values set in Google Cloud Run. Every so often Firebase auth on the client would fail, but a page refresh would always fix it. It depended on which page was initially viewed and exposed development-use configuration that was not intended to be exposed.Reproduction
See https://github.com/CaptainCodeman/svelte-kit-10008
Logs
No response
System Info
Severity
annoyance (had to disable pre-rendered pages for correct functionality)
Additional Information
Maybe related to #8946
The text was updated successfully, but these errors were encountered: