8000 CSRF verification failed (403) when using self-hosted PostHog and /i/v0/e/ endpoint · Issue #32108 · PostHog/posthog · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

CSRF verification failed (403) when using self-hosted PostHog and /i/v0/e/ endpoint #32108

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

Open
Felipoe opened this issue May 9, 2025 · 13 comments

Comments

@Felipoe
Copy link
Felipoe commented May 9, 2025

I recently deployed a self-hosted PostHog instance, and I'm encountering an issue when trying to capture events manually using fetch from the frontend.

Every time I attempt to send an event, I get the following error:

arduino
Copiar
Editar
POST https://posthog.bne.com.br/i/v0/e/ 403 (Forbidden) - CSRF verification failed. Request aborted.
Here’s a summary of my setup:

I am using a self-hosted PostHog deployment (running in Docker).

I have configured the PostHog instance with an API key (POSTHOG_PROJECT_API_ACCESS_TOKEN).

I'm using the standard PostHog JavaScript snippet to initialize posthog-js on the frontend.

I tried sending events using fetch directly to /capture/ and it works, but the default posthog-js SDK still tries to hit /i/v0/e/ and returns 403 errors.

I attempted patching middleware.py as suggested in previous discussions to include /i/v0/e/ in ALWAYS_ALLOWED_ENDPOINTS, but the issue persists.

Example of my manual fetch request (which works):

javascript
Copiar
Editar
fetch('https://posthog.bne.com.br/capture/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
api_key: 'MY_API_KEY',
event: 'page_view',
distinct_id: 'user_12345',
properties: {
utm_source: 'google',
utm_medium: 'cpc'
}
})
})
.then(response => response.json())
.then(data => console.log('Success:', data))
.catch(error => console.error('Error:', error));
But when I let posthog-js send events automatically, it tries to post to /i/v0/e/ and fails with 403.

Questions:

Is there any updated recommended way to handle CSRF verification for /i/v0/e/ in self-hosted setups?

Is there an official configuration to force posthog-js to post to /capture/ instead of /i/v0/e/?

Should I update or patch my PostHog instance differently to fix this properly?

Additional Information:

Docker setup: Yes

API Key correctly set: Yes

Traffic is HTTPS (SSL configured).

Thank you very much for your help.
Looking forward to your guidance!

Best regards,

@Lantianyou
Copy link

I am having same problem

@SynceeDev
Copy link

Same here, could you please fix it?

@Saboor-Hakimi
Copy link

I'm facing exact same issue here, can anybody help?

@sudo-eugene
Copy link

I'm also getting this issue.

@Felipoe is this (https://posthog.com/questions/forbidden-403-csrf-verification-failed-request-aborted) also you?

I've been following this issue at #28804 and it seems like @pauldambra needs more information on how to reproduce this. If we can help gather some data hopefully we can help them to resolve this

Here is a snippet of my docker logs for web-1
Assuming mypublicsite.com is the site I have the HTML snippet installed on, and posthog.myprivatesite.co is my posthog instance:

web-1              | 2025-05-19T16:28:55.867154Z [warning  ] Forbidden (Origin checking failed - https://mypublicsite.com does not match any trusted origins.): /i/v0/e/ [django.security.csrf] container_hostname=8046e11dae23 host=posthog.myprivatesite.co pid=394 team_id=1 tid=124643485051200 x_forwarded_for=2.49.199.114
web-1              | 2025-05-19T16:28:55.867292Z [warning  ] Forbidden (Origin checking failed - https://mypublicsite.com does not match any trusted origins.): /i/v0/e/ [django.security.csrf] container_hostname=8046e11dae23 host=posthog.myprivatesite.co pid=394 team_id=1 tid=124643485051200 x_forwarded_for=2.49.199.114
web-1              | 2025-05-19T16:28:55.868502Z [info     ] request_finished               [django_structlog.middlewares.request] code=403 container_hostname=8046e11dae23 host=posthog.myprivatesite.co ip=2.49.199.114 pid=394 request=<WSGIRequest: POST '/i/v0/e/?ip=1&_=1747672134875&ver=1.242.3&compression=gzip-js'> request_id=c73718b1-6912-4d82-9f15-9567a581429d team_id=1 tid=124643485051200 user_id=None x_forwarded_for=2.49.199.114
web-1              | 2025-05-19T16:28:55.966064Z [info     ] request_started                [django_structlog.middlewares.request] container_hostname=8046e11dae23 host=posthog.myprivatesite.co ip=197.0.0.0 pid=394 request=<WSGIRequest: GET '/api/environments/1/session_recordings?kind=RecordingsQuery&order=start_time&date_from=-30d&properties=%5B%5D&events=%5B%5D&actions=%5B%5D&console_log_filters=%5B%5D&having_predicates=%5B%7B%22type%22%3A%22recording%22%2C%22key%22%3A%22active_seconds%22%2C%22value%22%3A5%2C%22operator%22%3A%22gt%22%7D%5D&filter_test_accounts=false&operand=AND&person_uuid=&limit=20'> request_id=5b19eff4-bdf0-40e8-a78d-6fd79d04a54b team_id=1 tid=124643485051200 user_agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 x_forwarded_for=197.0.0.0
web-1              | 2025-05-19T16:28:57.447708Z [info     ] request_started                [django_structlog.middlewares.request] container_hostname=8046e11dae23 host=posthog.myprivatesite.co ip=2600:3000:2710:300::83 pid=372 request=<WSGIRequest: GET '/.well-known/acme-challenge/JRDdMHGWBL-rqcw55-By9i4bi134mB-T621S9UNBdco'> request_id=1ed22787-1d09-4a64-aa76-6ceb40f9d623 team_id=1 tid=124643485051200 token=phc_KOF99bsqKgJlwuXpUPNJlDWCqlgtJyOBC3mK6x0eK1H user_agent=Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org) x_forwarded_for=2600:3000:2710:300::83
web-1              | 2025-05-19T16:28:57.680224Z [info     ] request_finished               [django_structlog.middlewares.request] code=302 container_hostname=8046e11dae23 host=posthog.myprivatesite.co ip=2600:3000:2710:300::83 pid=372 request=<WSGIRequest: GET '/.well-known/acme-challenge/JRDdMHGWBL-rqcw55-By9i4bi134mB-T621S9UNBdco'> request_id=1ed22787-1d09-4a64-aa76-6ceb40f9d623 team_id=1 tid=124643485051200 token=phc_KOF99bsqKgJlwuXpUPNJlDWCqlgtJyOBC3mK6x0eK1H user_id=None x_forwarded_for=2600:3000:2710:300::83
web-1              | 2025-05-19T16:28:57.878087Z [info     ] request_finished               [django_structlog.middlewares.request] code=200 container_hostname=8046e11dae23 host=posthog.myprivatesite.co ip=197.0.0.0 pid=394 request=<WSGIRequest: GET '/api/environments/1/session_recordings?kind=RecordingsQuery&order=start_time&date_from=-30d&properties=%5B%5D&events=%5B%5D&actions=%5B%5D&console_log_filters=%5B%5D&having_predicates=%5B%7B%22type%22%3A%22recording%22%2C%22key%22%3A%22active_seconds%22%2C%22value%22%3A5%2C%22operator%22%3A%22gt%22%7D%5D&filter_test_accounts=false&operand=AND&person_uuid=&limit=20'> request_id=5b19eff4-bdf0-40e8-a78d-6fd79d04a54b team_id=1 tid=124643485051200 user_id=1 x_forwarded_for=197.0.0.0
web-1              | 2025-05-19T16:28:58.823356Z [info     ] request_started                [django_structlog.middlewares.request] container_hostname=8046e11dae23 host=posthog.myprivatesite.co ip=2600:3000:2710:300::83 pid=394 request=<WSGIRequest: GET '/login?next=/.well-known/acme-challenge/JRDdMHGWBL-rqcw55-By9i4bi134mB-T621S9UNBdco'> request_id=07feab0c-de7e-489f-b7b2-331626a5e9f2 team_id=1 tid=124643485051200 user_agent=Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org) x_forwarded_for=2600:3000:2710:300::83
web-1              | 2025-05-19T16:28:58.968916Z [info     ] request_finished               [django_structlog.middlewares.request] code=200 container_hostname=8046e11dae23 host=posthog.myprivatesite.co ip=2600:3000:2710:300::83 pid=394 request=<WSGIRequest: GET '/login?next=/.well-known/acme-challenge/JRDdMHGWBL-rqcw55-By9i4bi134mB-T621S9UNBdco'> request_id=07feab0c-de7e-489f-b7b2-331626a5e9f2 team_id=1 tid=124643485051200 user_id=None x_forwarded_for=2600:3000:2710:300::83
web-1              | 2025-05-19T16:29:00.187166Z [info     ] request_started                [django_structlog.middlewares.request] container_hostname=8046e11dae23 host=posthog.myprivatesite.co ip=2.49.199.114 pid=394 request=<WSGIRequest: POST '/i/v0/e/?ip=1&_=1747672139796&ver=1.242.3&compression=gzip-js'> request_id=4dbd5b6a-767e-4c11-b8c8-c47b45b4ffa7 team_id=1 tid=124643485051200 user_agent=Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/28.0 Chrome/130.0.0.0 Mobile Safari/537.36 x_forwarded_for=2.49.199.114
web-1              | 2025-05-19T16:29:00.194540Z [warning  ] Forbidden (Origin checking failed - https://mypublicsite.com does not match any trusted origins.): /i/v0/e/ [django.security.csrf] container_hostname=8046e11dae23 host=posthog.myprivatesite.co pid=394 team_id=1 tid=124643485051200 x_forwarded_for=2.49.
8000
199.114
web-1              | 2025-05-19T16:29:00.194706Z [warning  ] Forbidden (Origin checking failed - https://mypublicsite.com does not match any trusted origins.): /i/v0/e/ [django.security.csrf] container_hostname=8046e11dae23 host=posthog.myprivatesite.co pid=394 team_id=1 tid=124643485051200 x_forwarded_for=2.49.199.114
web-1              | 2025-05-19T16:29:00.196302Z [info     ] request_finished               [django_structlog.middlewares.request] code=403 container_hostname=8046e11dae23 host=posthog.myprivatesite.co ip=2.49.199.114 pid=394 request=<WSGIRequest: POST '/i/v0/e/?ip=1&_=1747672139796&ver=1.242.3&compression=gzip-js'> request_id=4dbd5b6a-767e-4c11-b8c8-c47b45b4ffa7 team_id=1 tid=124643485051200 user_id=None x_forwarded_for=2.49.199.114
web-1              | 2025-05-19T16:29:00.787561Z [info     ] request_started                [django_structlog.middlewares.request] container_hostname=8046e11dae23 host=posthog.myprivatesite.co ip=197.0.0.0 pid=394 request=<WSGIRequest: GET '/static/ActivityScene-6V2USHFN.js'> request_id=57d4a769-02ed-477c-9cef-1a44193a3a40 team_id=1 tid=124643485051200 user_agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 x_forwarded_for=197.0.0.0
web-1              | 2025-05-19T16:29:00.789409Z [info     ] request_finished               [django_structlog.middlewares.request] code=200 container_hostname=8046e11dae23 host=posthog.myprivatesite.co ip=197.0.0.0 pid=394 request=<WSGIRequest: GET '/static/ActivityScene-6V2USHFN.js'> request_id=57d4a769-02ed-477c-9cef-1a44193a3a40 team_id=1 tid=124643485051200 x_forwarded_for=197.0.0.0
web-1              | 2025-05-19T16:29:00.926488Z [info     ] request_started                [django_structlog.middlewares.request] container_hostname=8046e11dae23 host=posthog.myprivatesite.co ip=197.0.0.0 pid=394 request=<WSGIRequest: POST '/api/environments/1/query/'> request_id=5e6139d4-1f20-4032-9dc0-198c98d0269e team_id=1 tid=124643485051200 user_agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 x_forwarded_for=197.0.0.0
web-1              | 2025-05-19T16:29:01.581124Z [info     ] request_finished               [django_structlog.middlewares.request] code=200 container_hostname=8046e11dae23 host=posthog.myprivatesite.co ip=197.0.0.0 pid=394 request=<WSGIRequest: POST '/api/environments/1/query/'> request_id=5e6139d4-1f20-4032-9dc0-198c98d0269e team_id=1 tid=124643485051200 user_id=1 x_forwarded_for=197.0.0.0
web-1              | 2025-05-19T16:29:01.777363Z [info     ] request_started                [django_structlog.middlewares.request] container_hostname=8046e11dae23 host=posthog.myprivatesite.co ip=197.0.0.0 pid=394 request=<WSGIRequest: GET '/static/assets/posthog-icon-BU4PVLFJ.svg'> request_id=617cc174-cb4a-44d0-8dc4-5a2507c3d1c5 team_id=1 tid=124643485051200 user_agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 x_forwarded_for=197.0.0.0
web-1              | 2025-05-19T16:29:01.777940Z [info     ] request_finished               [django_structlog.middlewares.request] code=200 container_hostname=8046e11dae23 host=posthog.myprivatesite.co ip=197.0.0.0 pid=394 request=<WSGIRequest: GET '/static/assets/posthog-icon-BU4PVLFJ.svg'> request_id=617cc174-cb4a-44d0-8dc4-5a2507c3d1c5 team_id=1 tid=124643485051200 x_forwarded_for=197.0.0.0
web-1              | 2025-05-19T16:29:08.891748Z [info     ] request_started                [django_structlog.middlewares.request] container_hostname=8046e11dae23 host=posthog.myprivatesite.co ip=197.0.0.0 pid=416 request=<WSGIRequest: POST '/s/?ip=1&_=1747672148515&ver=1.229.2&compression=gzip-js'> request_id=0cc7f103-7d83-4fa4-ac05-66eba3cbf95f team_id=1 tid=124643485051200 token=phc_KOF99bsqKgJlwuXpUPNJlDWCqlgtJyOBC3mK6x0eK1H user_agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 x_forwarded_for=197.0.0.0
web-1              | 2025-05-19T16:29:08.898598Z [info     ] request_finished               [django_structlog.middlewares.request] code=200 container_hostname=8046e11dae23 host=posthog.myprivatesite.co ip=197.0.0.0 pid=416 request=<WSGIRequest: POST '/s/?ip=1&_=1747672148515&ver=1.229.2&compression=gzip-js'> request_id=0cc7f103-7d83-4fa4-ac05-66eba3cbf95f tid=124643485051200 token=phc_KOF99bsqKgJlwuXpUPNJlDWCqlgtJyOBC3mK6x0eK1H x_forwarded_for=197.0.0.0
web-1              | 2025-05-19T16:29:08.984461Z [info     ] request_started                [django_structlog.middlewares.request] container_hostname=8046e11dae23 host=posthog.myprivatesite.co ip=197.0.0.0 pid=416 request=<WSGIRequest: GET '/static/array.js'> request_id=6c0d7686-23ae-4bbb-a4f2-70fc417d7c82 tid=124643485051200 token=phc_KOF99bsqKgJlwuXpUPNJlDWCqlgtJyOBC3mK6x0eK1H user_agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 x_forwarded_for=197.0.0.0
web-1              | 2025-05-19T16:29:08.985393Z [info     ] request_finished               [django_structlog.middlewares.request] code=200 container_hostname=8046e11dae23 host=posthog.myprivatesite.co ip=197.0.0.0 pid=416 request=<WSGIRequest: GET '/static/array.js'> request_id=6c0d7686-23ae-4bbb-a4f2-70fc417d7c82 tid=124643485051200 token=phc_KOF99bsqKgJlwuXpUPNJlDWCqlgtJyOBC3mK6x0eK1H x_forwarded_for=197.0.0.0
web-1              | 2025-05-19T16:29:09.121916Z [info     ] request_started                [django_structlog.middlewares.request] container_hostname=8046e11dae23 host=posthog.myprivatesite.co ip=197.0.0.0 pid=416 request=<WSGIRequest: POST '/decide/?v=4&ip=1&_=1747672148826&ver=1.242.3&compression=base64'> request_id=d33aa8e2-5d5e-478f-9f17-b89f6fd783df tid=124643485051200 token=phc_KOF99bsqKgJlwuXpUPNJlDWCqlgtJyOBC3mK6x0eK1H user_agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 x_forwarded_for=197.0.0.0
web-1              | 2025-05-19T16:29:09.122128Z [info     ] request_started                [django_structlog.middlewares.request] container_hostname=8046e11dae23 host=posthog.myprivatesite.co ip=197.0.0.0 pid=394 request=<WSGIRequest: GET '/array/phc_KOF99bsqKgJlwuXpUPNJlDWCqlgtJyOBC3mK6x0eK1H/config.js'> request_id=b3567cbb-afee-4b51-b384-daa5327bcfb2 team_id=1 tid=124643485051200 user_agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 x_forwarded_for=197.0.0.0

My /e/ requests works, but /i/v0/e/ gets forbidden.

@pauldambra in the docker config that you are using, are you propagationg through a domain via an A record?

@pauldambra
Copy link
Member

@sudo-eugene I haven't changed any settings or config, so if you follow the default install then you don't get this (or rather I followed default and don't get this)

i think it's correct that i/v0/e gets forbidden as it should be served via the new rust capture endpoints and not the django app

so somewhere you all have picked up incorrect config but I don't know where from

@sudo-eugene
Copy link
sudo-eugene commented May 20, 2025

@pauldambra After running /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/posthog/posthog/HEAD/bin/upgrade-hobby)" yesterday, I double checked my local docker-compose.base.yml against https://github.com/PostHog/posthog/blob/master/docker-compose.base.yml and there was no difference

I also checked my local docker-compose.yml against https://github.com/PostHog/posthog/blob/master/docker-compose.hobby.yml and the only difference were that the .env values were hardcoded.

Are you suggesting that the issue potentially lies within the /posthog directory in the project root that the install script downloaded? See screenshots

Image

Image

@dannyjhall
Copy link

I also have this issue (on a fresh install).

I tried to set NEW_CAPTURE_ENDPOINT as suggested previously in #28804 but it didn't help.

So I modified the Caddyfile to rewrite these requests, which is working for now:

your-domain.com {
    encode gzip zstd

    @posthog_old_endpoint path /i/v0/e/*
    uri strip_prefix /i/v0/e
    rewrite @posthog_old_endpoint /capture

    reverse_proxy http://web:8000
    reverse_proxy http://livestream:8666
}

@pauldambra
Copy link
Member

@dannyjhall fixing my mess just like the good old days 🥇

we're working to remove the old capture so this should disappear at some point, will ping the folk that know this part of the system better than me though

@pauldambra
Copy link
Member

@dannyjhall you should apply to come and work at PostHog and fix this from the inside 😍😘

@pauldambra
Copy link
Member
pauldambra commented May 23, 2025

oh, wild 🤯

i just went to check my self-hosted install (which tracks the three readers of pauldambra.dev) before I said "this doesn't happen for me" and this has started happening even though it 100% wasn't a week or so ago, and I didn't change anything

that's odd...

ah, no, i broke it testing #32001 ignore me

@SynceeDev
Copy link

@dannyjhall

It works, thank you!!

@pawelbajgrowicz
Copy link

@dannyjhall you save my day

@Tiggu
Copy link
Tiggu commented Jun 13, 2025

I have not the slightest idea why it works or what @posthog_old_endpoint even means ... but it seems to work. Thank you @dannyjhall

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants
0