-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Cross-site POST form submissions are forbidden #6589
Comments
How are you running the server? I would bet the issue is that you're not using https://github.com/sveltejs/kit/tree/master/packages/adapter-node#environment-variables to tell the server what origin it's serving from. Note that in particular in production the Node adapter will assume by default that it has an HTTPS proxy in front of it and that its origin is |
Thanks, I did have it behind an https proxy but something must have been off because setting the ORIGIN env var explicitly helped. |
So how is the ORIGIN env var being pulled in? Any help appreciated. |
Same issue here. |
@nevermindthelabel I'm not familiar w/ the I've tried prefixing both the build step and the execution step w/ the environment variable but no luck. Does the env variable need to be part of the build to be compiled into the output? Does |
I should also say that I am using adapter-node. That builds the You need to pass the origin as an argument at runtime, and if you are doing it from docker you might need to do -e origin=http://localhost:port or wherever the sveltekit app is running. |
Use |
Can someone please know how to handle this if the app is served from multiple origins (subdomains like *.mysite.com) ? |
Same here, demand to use |
Encountered and solved this issue; full details down towards bottom of thread: Just putting it down here as I'd visited earlier and somehow missed following that link at the top indicating [that link] had closed this issue... |
And while on development how can I set the I used |
Looks like that's still an open issue: #8026 |
I'm using |
im using |
@joecorsi if you're having this issue on Vercel, then this is a different issue. Please open a separate issue with a minimal reproduction. |
@geoffrich thanks for reply. the issue i was having was just local. once deployed i dont have this issue. adding this to svelte.config.js while developing solves the issue:
|
I'm just previewing on localhost but I added a
|
Does anybody know if ORIGIN env variable can have some kind of wildcard or something? |
Thank you for being specific and not sending me on a wild goose chase. |
How to handle multiple ORIGINs? |
For anybody new coming to this issue looking for a solution. |
Perhaps you could create a new issue with this question? I will be needing this in the future maybe :) |
So, this broke any app that responds on multiple domains, right? |
To add some context, I have an application behind a "proxy" (rewrites on vercel.json) on Vercel. When I try to submit a form, I get this response: |
@stefanosandes did you ever come up with a solution? running into this same issue now. |
No, unfortunately. |
In my case the issue was present at local dev environment but not on production. My dev environment runs behind Nginx reverse proxy. The way I fixed it is by replacing proxy_set_header Origin http://$http_host; Something similar might work with other reverse proxy configurations. It seems Vite completely ignores the To debug the issue you can compare the request origin header and the url.origin property here: Hope this helps someone! |
I worked around the multiple ORIGIN issue by modifying SvelteKit's internal CSRF implementation to allow multiple origins import { error, type Handle, type RequestEvent } from "@sveltejs/kit";
import { allowedOrigins } from "$lib/config";
const csrf = (
event: RequestEvent,
allowedOrigins: string[],
) => {
const { request, url } = event;
const forbidden =
isFormContentType(request) &&
(request.method === "POST" ||
request.method === "PUT" ||
request.method === "PATCH" ||
request.method === "DELETE") &&
!allowedOrigins.includes(request.headers.get("origin") || "");
if (forbidden) {
error(403, `Cross-site ${request.method} form submissions are forbidden`);
}
};
function isContentType(request: Request, ...types: string[]) {
const type = request.headers.get("content-type")?.split(";", 1)[0].trim() ?? "";
return types.includes(type.toLowerCase());
}
function isFormContentType(request: Request) {
// These content types must be protected against CSRF
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/enctype
return isContentType(
request,
"application/x-www-form-urlencoded",
"multipart/form-data",
"text/plain",
);
}
export const handle: Handle = async ({ event, resolve }) => {
csrf(event, allowedOrigins);
return await resolve(event);
}; You'll also have to set Inspiration from this thread. |
It might not apply to many people, but I thought I'd share my case. The issue occurred when I made a fetch request from the browser to an endpoint defined in // no
await fetch(location.origin, {
method: 'post',
body: JSON.stringify({data: res.data} satisfies MyData),
});
// ok
await fetch(location.origin, {
method: 'post',
body: JSON.stringify({data: res.data} satisfies MyData),
headers: {
'Content-Type': 'application/json'
}
}); I hope this information will be useful to future readers. |
Hope I help someone, Im running my app with node adapter through docker in development I put in docker file # Assuming the default app runnning host:port
ENV ORIGIN=http://localhost:3000 or in docker-compose file version: '3.8'
services:
mysveltenodeapp-deploy:
image: mysveltenodeapp
ports:
- '3000:3000'
environment:
- ...
- ORIGIN=http://localhost:3000 |
Thank you @sundaycrafts, this was useful for me. |
Currently, this is working for me. I'm running my sveltekit app in a docker container. So far, the form is submitting successfully. I'm planning to put this app behind a reverse proxy using nginx with:
Hoping this still will work even behind a proxy because I want this form to submit from multiple domains and it seems like you cant have a wildcard ORIGIN var unless you do a custom one yourself. |
After installing "dotenv" via npm manually, I configured the scripts section of my package.json with this line: "start": "node --env-file=.env build". Then, I updated my .env file with ORIGIN=http://localhost:3000, and it worked! 😁 |
For anyone deploying with docker make sure you are also setting: ENV NODE_ENV=production Someone else might be able to explain why this is necessary but it worked for me! Dockerfile: FROM node:20.17-alpine AS builder
WORKDIR /app
RUN npm install [email protected] -g
# install dependencies
COPY package.json pnpm-lock.yaml ./
RUN pnpm install
COPY . .
RUN pnpm build
FROM node:20.17-alpine AS runner
WORKDIR /app
COPY --from=builder /app/build ./build
# we copy the package json so that it knows the module type
COPY --from=builder /app/package.json ./package.json
# set NODE_ENV environment variable to production
ENV NODE_ENV=production
# run app
CMD ["node", "build"]
EXPOSE 80 docker-compose.yaml: services:
www:
container_name: www
build:
context: ./sites/www
dockerfile: Dockerfile
ports:
- 80:80
environment:
- PORT=80
- ORIGIN=http://YOUR_ORIGIN_HERE |
Describe the bug
I'm getting an error message about a cross-site request when submitting a form to a relative URL that's handled by an endpoint on the same server.
The error only occurs when running the production build with the node-adapter, not with the dev server.
Reproduction
https://github.com/asoltys/svelte-cross-site-repro
Logs
System Info
Severity
serious, but I can work around it
Additional Information
No response
The text was updated successfully, but these errors were encountered: