fix: implement CSRF protection for remote function requests
Closes #14791
As discussed, this makes sure the remote functions respect csrf.trustedOrigins. If trustedOrigins includes *, then any origin is allowed.
Please don't delete this checklist! Before submitting the PR, please make sure you do the following:
- [x] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
- [x] This message body should clearly illustrate what problems it solves.
- [x] Ideally, include a test that fails without this PR but passes with it.
Tests
- [x] Run the tests with
pnpm testand lint the project withpnpm lintandpnpm check
Changesets
- [x] If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running
pnpm changesetand following the prompts. Changesets that add features should beminorand those that fix bugs should bepatch. Please prefix changeset messages withfeat:,fix:, orchore:.
Edits
- [x] Please ensure that 'Allow edits from maintainers' is checked. PRs without this option may be closed.
🦋 Changeset detected
Latest commit: 52eac5be884f6619f0c6bec619ced66343f885be
The changes in this PR will be included in the next version bump.
This PR includes changesets to release 1 package
| Name | Type |
|---|---|
| @sveltejs/kit | 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
Admission: The tests are LLM written, lemme know if they're complete garbage 🤣😅
Any update? 😁
We had a lengthy discussion among the maintainers just now and concluded that trustedOrigins is the wrong tool for this job. The problem isn't that we want to expose remote functions to arbitrary callers, it's that your preview deployments don't understand what their own origin is.
Ordinarily, the origin comes from request.url, which is determined by the adapter (but in most cases, ultimately, by the platform — e.g. in the adapter-vercel case we're passed a fully-formed Request object which already has the url set). In the case of adapter-node we don't know the request.url by default, hence the ORIGIN environment variable.
One thing we could do is create a new config option, such as paths.origin:
// svelte.config.js
export default {
kit: {
paths: {
origin: process.env.ORIGIN ?? ''
}
}
};
The empty string would mean 'auto', i.e. derive the origin from request.url, but otherwise we could use the configured value.
If I understand correctly, this would satisfy your use case, and it could also replace ORIGIN in adapter-node and the kit.prerender.origin option. All without weakening CSRF guarantees. Does that sound workable?
This would be absolutely fantastic! Thank you
+1 this would really benefit one of my use cases