-
-
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
Secrets exposed in server only load
fetch dependencies
#9803
Comments
Dependencies have to be sent to the client to be able to invalidate data properly. You can use the handleFetch hook to rewrite any requests that are sent from your server. So your +layout.server.js load function can just call the URL without the key, and the dependencies will have that link instead, then inside handleFetch you can add your API key to the url. I suppose we could document this behaviour better to prevent users leaking their keys. Feel free to send a PR or point out where in the documentation you would expect it. |
Put your actual fetch inside +server and call that from your load function |
@gtm-nayan What I'm expecting is that there should be some way to override the invalidation key (which I guess is by default the fetch url). There's already a |
I was not aware of this behavior. I don’t think any value or code that is added to +layout.server.js or +server.js file should be exposed to the client under no circumstances. This is going to cause a lot of secret leak even if it’s documented. |
I still need to digest this, but what's the point of "private", "server" and "public" if everything is exposed to the client by default? |
@ramonmalcolm10 @machak Using |
It would be nice if this could be automatically done/intercepted by compiler itself and replace any secret with a unique placeholder and automatically map and rewrite URLs in a similar way as in handleFetch, instead of just documenting it and when major security leak happens pointing to people and telling them to RTFM |
This was added in #8420 Invalidation by url for urls passed into server only fetch calls seems like a rare usecase that should be opt-in rather than default, especially if it leaks information about service urls to the client. This is not only problematic if the url contains a secret token, but in general, as the url itself gives an attacker additional information that could be used in a chained attack. |
This was an oversight, thanks for bringing it to our attention. I think there are a few possible approaches:
Thoughts? In #9850 @malviyaritesh adds a new import { PRIVATE_STATIC } from '$env/static/private';
export async function load({ fetch }) {
return {
time: fetch(`http://worldtimeapi.org/api/ip?PRIVATE=${encodeURIComponent(PRIVATE_STATIC)}`, {
svelte: { depends: 'app:hidden-time-api' }
}).then((res) => res.json())
};
} ...over this: import { PRIVATE_STATIC } from '$env/static/private';
export async function load({ fetch, depends }) {
depends('app:hidden-time-api');
return {
time: fetch(`http://worldtimeapi.org/api/ip?PRIVATE=${encodeURIComponent(PRIVATE_STATIC)}`).then((res) => res.json())
};
} |
I would make this an option like We could also make it opt in to track so we don't break people but warn that people should opt into it. |
Opting people in by default would defeat the object, I think. Any thoughts on what sort of warning would guide people towards the option without annoying people who don't need it? I remember we (half-jokingly?) suggested a export default {
kit: {
dangerZone: {
trackServerFetches: true
}
}
}; |
@Rich-Harris
Yes, I also don't like to poison the standard interfaces, but there were two reasons for this:
Also, completely unrelated, I don't expect this to be considered (as it is another breaking change) but just sharing the thought. |
Describe the bug
Thanks for the awesome open source work.
I'm quite new to Svelte and SvelteKit and recently decided to use in a project to learn it more. I think, I've discovered some bug or issue in SvelteKit with my very limited experience using it.
I'm loading some data in
+layout.server.ts
from an external url which requires sending api key as query param. I've stored the api key in.env
file. I'm loading the data in+layout.server.ts
specifically because I don't want to expose api key to the client. But even this file is also exposing it to client as part of url dependency for thefetch
.I tried calling
depends
insideload
but it adds additional dependencies along with fetch url. I couldn't find any way to prevent SvelteKit using url as dependency.As an alternate solution to this, I could've created an internal api route which calls the external api with api key but I think
+layout.server.ts
shouldn't expose the url (and secrets certainly not) to client as it guarantees to run the code only server side. I don't see any benefit of using server only load of+layout.server.ts
over universal load in+layout.ts
, if it exposes the url (and secrets) to client.Reproduction
.env
file and add a secret such asAPI_KEY=top-secret-key
.+layout.server.ts
which usesfetch
to load data from external api. Import and passAPI_KEY
environment variable to fetch url as query param.+layout.svelte
.script
tag, you'll find that your secretAPI_KEY
is exposed to the client.Here's a demo project I've created to reproduce this issue:
https://stackblitz.com/edit/sveltejs-kit-template-default-eeb3rv?file=src/routes/+layout.server.js
Also note that in my testing with
@sveltejs/kit@next
version thedependencies
array is empty which is what I was expecting.Logs
No response
System Info
Severity
blocking all usage of SvelteKit
Additional Information
No response
The text was updated successfully, but these errors were encountered: