-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Description
Describe the bug
tldr;
- The existence of the
+layout.server.js
tree will lead folks to put logic there rather than in+page.server.js
. - Because SvelteKit decides on the client what to fetch from the tree, there are edge cases where important (e.g., authorization) logic in
+layout.server.js
is skipped. - This may seem a contrived edge case, but it is an attack vector that needs to be addressed through documentation.
Consider the following case. (Repo link below)
src
└── routes
└── launch-codes
├── +layout.server.js
├── +page.server.js
└── +page.svelte
Let's say I naively (but I think quite naturally) do the following things:
- I place authentication/authorization logic in the
+layout.server.js
file. Perhaps I plan to elaborate this section of the site withlaunch-codes/[id]
. - Meanwhile, I use
+page.server.js
to fetch a paged list of codes from the database.
Essentially I have separated the concerns of authorization and data collection.
Now this is totally secure as long as my user remains signed in. But let's say the following happens:
- The user goes to
/launch-codes
. This first page view runs the authorization logic in+layout.server.ts
. - They are signed out, say on another tab, or because the cookie expires, or just by deleting the cookie in the console.
- In the original tab, now signed out, they go to
/launch-codes?page=2
. The authorization logic in+layout.server.ts
is skipped, and the signed out user is shown the launch codes.
I don't think there's a way to reliably fix this in the framework. The client side router decides what to fetch, and that AFAICT will always be manipulable. The only way to "fix" it is by documentation.
(Or we could get rid of the layout data tree notion entirely. Not a bad option, IMO, but a separate losing argument.)
I know all this may seem contrived, but:
- It's not that far-fetched for a developer to assume that separating authorization concerns is partly what
+layout.server.js
is for. - It's not that far-fetched to assume that some apps may require quick cookie expiration. Think your bank.
- It exists. It's an attack vector.
Reproduction
Reproduction here, as minimal as I could make it: https://github.com/cdcarson/yellow-submarine.git
git clone https://github.com/cdcarson/yellow-submarine.git
cd yellow-submarine
npm i
npm run dev
- Go to http://127.0.0.1:5173/launch-codes
- Assuming you are not signed in, you'll be redirected to a sign in page, and redirected back after clicking the button
- Navigate through the paginated list
- In the tab's console, delete the
signedIn
cookie. (I.e. the cookie has expired or you've been signed out on another tab.) - Without refreshing the page, click to another page in the list. You will be shown that page, rather than being redirected to
/sign-in
I made a separate route with a "non-naive" implementation, getting rid of layout.server.js
and doing the authorization in +page.server.ts
.
- Go to http://127.0.0.1:5173/launch-codes-fixed
- Replicate the steps above. This time, after deleting the cookie, subsequent navigations through the list at
/launch-codes-fixed
will be redirected to/sign-in
Logs
No response
System Info
System:
OS: macOS 12.4
CPU: (8) arm64 Apple M1
Memory: 70.06 MB / 8.00 GB
Shell: 5.8.1 - /bin/zsh
Binaries:
Node: 16.13.2 - ~/.nvm/versions/node/v16.13.2/bin/node
npm: 8.1.2 - ~/.nvm/versions/node/v16.13.2/bin/npm
Browsers:
Chrome: 104.0.5112.101
Safari: 15.5
npmPackages:
@sveltejs/adapter-auto: next => 1.0.0-next.66
@sveltejs/kit: next => 1.0.0-next.442
svelte: ^3.44.0 => 3.49.0
vite: ^3.0.4 => 3.0.9
Severity
serious, but I can work around it
Additional Information
No response