Cross-site POST form submissions are forbidden
Asked Answered
A

6

33

My sveltekit app has a form which sends a POST request to server. The app is working fine on dev server but when I build and run the app it fails to send the form data via POST request. It shows the following error in the browser:

Cross-site POST form submissions are forbidden

Audient answered 20/9, 2022 at 18:7 Comment(0)
A
32

You have to set the the ORIGIN env var like this

ORIGIN=http://localhost:3000 node build/index.js

https://github.com/sveltejs/kit/tree/master/packages/adapter-node#origin-protocol_header-and-host_header

Annulet answered 23/9, 2022 at 0:33 Comment(7)
Thank you, this worked. Also for anyone who's setting enviroment variables in powershell, $env:ORIGIN = "http://127.0.0.1" and run node build/index.js on the next line, because for some reason, powershell does not notice the change in env var when the env var is changed and the build command is run on the same line.Audient
What about import adapter from '@sveltejs/adapter-auto'; ? how to fix this error with adapter-auto..Emilio
You can also set an environment variable ORIGIN when you deploy your app (for example when using Docker). Note that it is important whether you use https://example.com or https://www.example.com when setting the origin.Jaimie
you may need to benefit from node-adaptor if you are using sveltekit with latest version kit.svelte.dev/docs/adapter-nodeKlecka
I have a .com site and a .org site. Using nginx to point both to the same app. Should I be redirecting to one or the other instead? Because if I specify ORIGIN to be one domain, POST requests won't be available on the other domainAlexia
hey @Alexia how did you fix this ? I have a similar situationKktp
@Kktp Unfortunately not, don't think it's possible. I ended up setting csrf to false like that other answer suggested. Later on I made one domain redirect to the other and re-enabled csrf. I'd still be interested if a solution exists though.Alexia
P
16

This is a built-in protection against cross-site request forgery attacks in Sveltekit. Set csrf to false in svelte.config.js to allow cross-site post requests.

See csrf in the Sveltekit configuration docs

import adapter from '@sveltejs/adapter-node'

const config = {
  kit: {
    adapter: adapter(),
    csrf: {
      checkOrigin: false,
    }
  },
}

export default config
Pyuria answered 21/9, 2022 at 13:25 Comment(2)
I would not advise to do this! CSRF attacks are a real thing and its important to have a protection against them. See the answer below by evan for the correct way to do it - you have to tell the sveltekit server about the actual origin domain when you start your sveltekit application.Ephram
Can this be done for a single route?Psf
L
5

If you are using PM2 as process manager, it is similar with:

ORIGIN=https://yourapp.com pm2 restart /var/www/build/index.js --name 'yourapp' --update-env
Laux answered 24/5, 2023 at 13:44 Comment(0)
K
4

This works: node -r dotenv/config build after including your new variable in .env ORIGIN=https://yourwebsite.com (please install it with npm install dotenv command as pointed out here)

Klecka answered 24/12, 2022 at 19:6 Comment(2)
Now it doesn't after updating it. Something may go wrong and it doesn't restart the serever, thus not loading origin as your domainKlecka
After several days, checked .env variables if they are loaded correctly, seems origin is undefined: process.env.ORIGIN. Check all of them console.log(process.env)Klecka
R
1

My Svelte app is deployed in Docker so, I just needed to add the ORIGIN environment variable to the Dockerfile, by adding the following line:

ENV ORIGIN https://mywebsite.com

This environment variable can also be added on the docker-compose.yml file, by doing the following:

environment:
  - ORIGIN=https://mywebsite.com
Rachelrachele answered 15/11, 2023 at 23:58 Comment(0)
M
0

Just in case anyone else arrives here after all this time, there's a slightly simpler solution, for cases like mine anyway: the csrf check will not be invoked if the submission doesn't have a Content-Type header that looks like a form. From the code, this function needs to return true to enable the check:

function is_form_content_type(request) {
  return is_content_type(
    request,
    "application/x-www-form-urlencoded",
    "multipart/form-data",
    "text/plain"
  );
}

In my case I am working on a backend server api, so setting Content-Type to application/json allowed the request to proceed.

Note this is SvelteKit server code, and is not dependant on the adapter you're using.

Manometer answered 13/12, 2023 at 15:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.