You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Is your issue present in the latest beta/pre-release?
I'm too lazy to test
Describe the Bug
Pairing a Moonlight client via the web UI's PIN Pairing page (/pin) always fails with a "CSRF Protection Error" toast, even though csrf_allowed_origins in sunshine.conf already lists the exact origin being used to access the UI.
I confirmed this is not an origin allow-list problem. Using the browser's dev tools, I instrumented window.fetch on the /pin page and captured the exact request the "Send" button issues:
POST ./api/pin
Headers: { "Content-Type": "application/json" }
Body: {"pin":"1234","name":"test-device"}
There is no X-CSRF-Token header, and the page never calls GET /api/csrf-token beforehand to obtain one. The server correctly rejects this with {"error":"Missing CSRF token","status":false,"status_code":400}.
I confirmed the CSRF mechanism itself works fine server-side: manually fetching a token and attaching it as X-CSRF-Token on the same POST /api/pin request succeeds (200, {"status":true}). So the bug is specifically that the PIN Pairing page's own frontend code never fetches or attaches the CSRF token before submitting.
Expected Behavior
Entering a valid PIN and Device Name and clicking "Send" should successfully pair the Moonlight client, the same way manually attaching a fetched X-CSRF-Token to the same request does.
Additional Context
Steps to reproduce:
Configure csrf_allowed_origins in sunshine.conf to include the exact origin used to access the web UI (ruling out an origin-allowlist problem).
Navigate to /pin, enter any PIN and device name, click Send.
Observe the "CSRF Protection Error" toast (added in CSRF failures are not apparent to users #4855 / v2026.516.143833) and a 400 response from POST /api/pin with body {"error":"Missing CSRF token",...}.
Workaround that confirms the CSRF mechanism itself is fine: call GET /api/csrf-token (Basic Auth) to obtain a token, then POST /api/pin with that token in an X-CSRF-Token header. That request succeeds normally. It's specifically the /pin page's own frontend code that never performs step 1 of that flow.
Related but distinct issues I found while searching before filing this: #4855 (about the error being invisible to users, fixed by making the toast appear - which is how I could see this error at all) and #5059 (a feature request to disable CSRF entirely for LAN/dynamic-IP use, not this bug). Neither covers the frontend not sending the token in the first place.
Happy to test a fix or provide more info - this is on a fresh Flatpak install with only sunshine.conf hand-edited for csrf_allowed_origins, nothing else customized.Pairing a Moonlight client via the web UI's PIN Pairing page (/pin) always fails with a "CSRF Protection Error" toast, even though csrf_allowed_origins in sunshine.conf already lists the exact origin being used to access the UI.
I confirmed this is not an origin allow-list problem. Using the browser's dev tools, I instrumented window.fetch on the /pin page and captured the exact request the "Send" button issues:
POST ./api/pin
Headers: { "Content-Type": "application/json" }
Body: {"pin":"1234","name":"test-device"}
There is no X-CSRF-Token header, and the page never calls GET /api/csrf-token beforehand to obtain one. The server correctly rejects this with {"error":"Missing CSRF token","status":false,"status_code":400}.
I confirmed the CSRF mechanism itself works fine server-side: manually fetching a token and attaching it as X-CSRF-Token on the same POST /api/pin request succeeds (200, {"status":true}). So the bug is specifically that the PIN Pairing page's own frontend code never fetches or attaches the CSRF token before submitting.
[2026-08-01 11:01:13.275]: Info: Sunshine version: 2026.516.143833 commit: 14ffa6fdaa53f7b51512be2b3d24f3939695403c
[2026-08-01 11:01:13.275]: Info: Package Publisher: LizardByte
[2026-08-01 11:01:13.275]: Info: Publisher Website: https://app.lizardbyte.dev
[2026-08-01 11:01:13.275]: Info: Get support: https://app.lizardbyte.dev/support
[2026-08-01 11:01:13.275]: Info: config: 'csrf_allowed_origins' = [redacted]
[2026-08-01 11:01:13.275]: Error: Couldn't load cuda: -1[2026-08-01 11:01:13.275]: Info: [wayland] Found display [wayland-0][2026-08-01 11:01:13.276]: Info: [wayland] Found interface: zxdg_output_manager_v1(32) version 3[2026-08-01 11:01:13.276]: Info: [wayland] Found interface: zwp_linux_dmabuf_v1(57) version 5[2026-08-01 11:01:13.276]: Info: [wayland] Found interface: wl_output(64) version 4[2026-08-01 11:01:13.276]: Warning: [wlgrab] Missing Wayland wire for wlr-export-dmabuf[2026-08-01 11:01:13.276]: Error: Failed to gain CAP_SYS_ADMIN[2026-08-01 11:01:13.276]: Info: /dev/dri/card0 -> amdgpu[2026-08-01 11:01:13.278]: Info: [wayland] Found display [wayland-0][2026-08-01 11:01:13.278]: Info: [wayland] Found display [wayland-0][2026-08-01 11:01:13.278]: Info: [wayland] Found interface: zxdg_output_manager_v1(32) version 3[2026-08-01 11:01:13.278]: Info: [wayland] Found interface: zwp_linux_dmabuf_v1(57) version 5[2026-08-01 11:01:13.278]: Info: [wayland] Found interface: wl_output(64) version 4[2026-08-01 11:01:13.278]: Info: [wayland] Resolution: 1920x1080[2026-08-01 11:01:13.278]: Info: [wayland] Offset: 0x0[2026-08-01 11:01:13.279]: Info: [wayland] Logical size: 1920x1080[2026-08-01 11:01:13.279]: Info: [wayland] Name: eDP-1[2026-08-01 11:01:13.279]: Info: [wayland] Found monitor: Thermotrex Corporation eDP-1-TL070FVXS01-0[2026-08-01 11:01:13.279]: Info: -------- Start of KMS monitor list --------[2026-08-01 11:01:13.279]: Warning: Mismatch on expected Resolution compared to actual resolution: 0x0 vs 1920x1080[2026-08-01 11:01:13.279]: Info: Monitor 0 is eDP-1: Thermotrex Corporation eDP-1-TL070FVXS01-0[2026-08-01 11:01:13.279]: Info: --------- End of KMS monitor list ---------[2026-08-01 11:01:13.279]: Info: [portalgrab] Loaded portal restore token from disk[2026-08-01 11:01:13.295]: Info: [wayland] Found display [wayland-0][2026-08-01 11:01:13.295]: Info: [wayland] Found interface: zxdg_output_manager_v1(32) version 3[2026-08-01 11:01:13.295]: Info: [wayland] Found interface: zwp_linux_dmabuf_v1(57) version 5[2026-08-01 11:01:13.295]: Info: [wayland] Found interface: wl_output(64) version 4[2026-08-01 11:01:13.295]: Info: [wayland] Resolution: 1920x1080[2026-08-01 11:01:13.295]: Info: [wayland] Offset: 0x0[2026-08-01 11:01:13.295]: Info: [wayland] Logical size: 1920x1080[2026-08-01 11:01:13.295]: Info: [wayland] Name: eDP-1[2026-08-01 11:01:13.295]: Info: [wayland] Found monitor: Thermotrex Corporation eDP-1-TL070FVXS01-0[2026-08-01 11:01:13.295]: Warning: [portalgrab] Falling back to position 0x0 for stream with resolution 1920x1080on pipewire node 108[2026-08-01 11:01:13.297]: Info: [portalgrab] Found stream for display id/name: 'eDP-1' position: 0x0 resolution: 1920x1080[2026-08-01 11:01:13.314]: Warning: Gamepad ds5 is disabled due to Permission denied[2026-08-01 11:01:13.314]: Info: // Testing for available encoders, this may generate errors. You can safely ignore those errors. //[2026-08-01 11:01:13.314]: Info: Trying encoder [nvenc][2026-08-01 11:01:13.314]: Info: Screencasting with XDG portal[2026-08-01 11:01:13.314]: Info: [pipewire] Requested frame rate [60/1, approx. 60 fps][2026-08-01 11:01:13.314]: Info: [wayland] Found display [wayland-0][2026-08-01 11:01:13.330]: Info: [portalgrab] Loaded portal restore token from disk[2026-08-01 11:01:13.343]: Info: [wayland] Found display [wayland-0][2026-08-01 11:01:13.343]: Info: [wayland] Found interface: zxdg_output_manager_v1(32) version 3[2026-08-01 11:01:13.343]: Info: [wayland] Found interface: zwp_linux_dmabuf_v1(57) version 5[2026-08-01 11:01:13.343]: Info: [wayland] Found interface: wl_output(64) version 4[2026-08-01 11:01:13.343]: Info: [wayland] Resolution: 1920x1080[2026-08-01 11:01:13.343]: Info: [wayland] Offset: 0x0[2026-08-01 11:01:13.343]: Info: [wayland] Logical size: 1920x1080[2026-08-01 11:01:13.343]: Info: [wayland] Name: eDP-1[2026-08-01 11:01:13.343]: Info: [wayland] Found monitor: Thermotrex Corporation eDP-1-TL070FVXS01-0[2026-08-01 11:01:13.343]: Warning: [portalgrab] Falling back to position 0x0 for stream with resolution 1920x1080on pipewire node 108[2026-08-01 11:01:13.345]: Info: [[2026-08-01 11:08:57.882]: Info: Web UI: [192.168.0.80] -- not authorized[2026-08-01 11:10:08.420]: Error: Web UI: [192.168.0.80] -- CSRF protection blocked request from origin: https://192.168.0.40:47990[2026-08-01 11:10:08.420]: Error: Web UI: To allow this origin, add it to the 'csrf_allowed_origins' option in your Sunshine configuration[2026-08-01 11:10:18.764]: Error: Web UI: [192.168.0.80] -- CSRF protection blocked request from origin: https://192.168.0.40:47990[2026-08-01 11:10:18.764]: Error: Web UI: To allow this origin, add it to the 'csrf_allowed_origins' option in your Sunshine configuration[2026-08-01 11:11:23.828]: Info: Web UI: [192.168.0.80] -- not authorized[2026-08-01 11:11:50.561]: Error: Web UI: [192.168.0.80] -- CSRF protection blocked request from origin: https://sunshine.home.arpa:47990[2026-08-01 11:11:50.561]: Error: Web UI: To allow this origin, add it to the 'csrf_allowed_origins' option in your Sunshine configuration[2026-08-01 11:13:32.696]: Info: Web UI: [192.168.0.80] -- not authorized[2026-08-01 11:13:32.722]: Info: Web UI: [192.168.0.80] -- not authorized[2026-08-01 11:13:32.745]: Info: Web UI: [192.168.0.80] -- not authorized[2026-08-01 11:14:23.846]: Error: Web UI: [192.168.0.80] -- CSRF protection blocked request from origin: https://sunshine.home.arpa:47990[2026-08-01 11:14:23.846]: Error: Web UI: To allow this origin, add it to the 'csrf_allowed_origins' option in your Sunshine configuration[2026-08-01 11:14:43.730]: Error: Web UI: [192.168.0.80] -- CSRF protection blocked request from origin: https://sunshine.home.arpa:47990[2026-08-01 11:14:43.730]: Error: Web UI: To allow this origin, add it to the 'csrf_allowed_origins' option in your Sunshine configuration[2026-08-01 11:14:48.982]: Info: Web UI: [192.168.0.80] -- not authorized[2026-08-01 11:14:58.773]: Info: Web UI: [192.168.0.80] -- not authorized[2026-08-01 11:15:54.450]: Error: Web UI: [192.168.0.80] -- CSRF protection blocked request from origin: https://sunshine.home.arpa:47990[2026-08-01 11:15:54.450]: Error: Web UI: To allow this origin, add it to the 'csrf_allowed_origins' option in your Sunshine configuration[2026-08-01 11:16:08.213]: Error: Web UI: [192.168.0.80] -- CSRF protection blocked request from origin: https://sunshine.home.arpa:47990[2026-08-01 11:16:08.213]: Error: Web UI: To allow this origin, add it to the 'csrf_allowed_origins' option in your Sunshine configuration[2026-08-01 11:18:57.052]: Error: Web UI: [192.168.0.80] -- CSRF protection blocked request from origin: https://192.168.0.40:47990[2026-08-01 11:18:57.053]: Error: Web UI: To allow this origin, add it to the 'csrf_allowed_origins' option in your Sunshine configuration[2026-08-01 11:19:11.575]: Error: Web UI: [192.168.0.80] -- CSRF protection blocked request from origin: https://192.168.0.40:47990[2026-08-01 11:19:11.575]: Error: Web UI: To allow this origin, add it to the 'csrf_allowed_origins' option in your Sunshine configuration[2026-08-01 11:19:26.695]: Error: Web UI: [192.168.0.80] -- CSRF protection blocked request from origin: https://192.168.0.40:47990[2026-08-01 11:19:26.695]: Error: Web UI: To allow this origin, add it to the 'csrf_allowed_origins' option in your Sunshine configuration[2026-08-01 11:21:35.346]: Error: Web UI: [192.168.0.80] -- CSRF protection blocked request from origin: https://192.168.0.40:47990[2026-08-01 11:21:35.346]: Error: Web UI: To allow this origin, add it to the 'csrf_allowed_origins' option in your Sunshine configurationet: 0x0[2026-08-01 11:01:14.898]: Info: [wayland] Logical size: 1920x1080[2026-08-01 11:01:14.898]: Info: [wayland] Name: eDP-1[2026-08-01 11:01:14.898]: Info: [wayland] Found monitor: Thermotrex Corporation eDP-1-TL070FVXS01-0[2026-08-01 11:01:14.900]: Info: [pipewire] Connected to pipewire version 1.6.4[2026-08-01 11:01:14.917]: Info: [pipewire] Pipewire Error, id:2 seq:13 message: no more input formats[2026-08-01 11:01:16.414]: Info: Creating encoder [h264_vulkan][2026-08-01 11:01:16.414]: Info: Color coding: SDR (Rec. 601)[2026-08-01 11:01:16.414]: Info: Color depth: 8-bit[2026-08-01 11:01:16.414]: Info: Color range: JPEG[2026-08-01 11:01:16.462]: Info: Streaming bitrate is 1000000[2026-08-01 11:01:16.462]: Info: Vulkan encode using GPU: AMD Ryzen Z1 Extreme (RADV PHOENIX)[2026-08-01 11:01:16.474]: Info: Creating encoder [hevc_vulkan][2026-08-01 11:01:16.474]: Info: Color coding: SDR (Rec. 601)[2026-08-01 11:01:16.474]: Info: Color depth: 8-bit[2026-08-01 11:01:16.474]: Info: Color range: JPEG[2026-08-01 11:01:16.514]: Info: Streaming bitrate is 1000000[2026-08-01 11:01:16.515]: Info: Vulkan encode using GPU: AMD Ryzen Z1 Extreme (RADV PHOENIX)[2026-08-01 11:01:16.526]: Info: Creating encoder [av1_vulkan][2026-08-01 11:01:16.526]: Info: Color coding: SDR (Rec. 601)[2026-08-01 11:01:16.526]: Info: Color depth: 8-bit[2026-08-01 11:01:16.526]: Info: Color range: JPEG[2026-08-01 11:01:16.565]: Info: Streaming bitrate is 1000000[2026-08-01 11:01:16.566]: Info: Vulkan encode using GPU: AMD Ryzen Z1 Extreme (RADV PHOENIX)[2026-08-01 11:01:16.575]: Info: Screencasting with XDG portal[2026-08-01 11:01:16.575]: Info: [pipewire] Requested frame rate [60/1, approx. 60 fps][2026-08-01 11:01:16.575]: Info: [wayland] Found display [wayland-0][2026-08-01 11:01:16.583]: Info: [portalgrab] Loaded portal restore token from disk[2026-08-01 11:01:16.598]: Info: [wayland] Found display [wayland-0][2026-08-01 11:01:16.599]: Info: [wayland] Found interface: zxdg_output_manager_v1(32) version 3[2026-08-01 11:01:16.599]: Info: [wayland] Found interface: zwp_linux_dmabuf_v1(57) version 5[2026-08-01 11:01:16.599]: Info: [wayland] Found interface: wl_output(64) version 4[2026-08-01 11:01:16.599]: Info: [wayland] Resolution: 1920x1080[2026-08-01 11:01:16.599]: Info: [wayland] Offset: 0x0[2026-08-01 11:01:16.599]: Info: [wayland] Logical size: 1920x1080[2026-08-01 11:01:16.599]: Info: [wayland] Name: eDP-1[2026-08-01 11:01:16.599]: Info: [wayland] Found monitor: Thermotrex Corporation eDP-1-TL070FVXS01-0[2026-08-01 11:01:16.599]: Warning: [portalgrab] Falling back to position 0x0 for stream with resolution 1920x1080on pipewire node 108[2026-08-01 11:01:16.601]: Info: [portalgrab] Using first available stream as no matching stream was found for: ''[2026-08-01 11:01:16.601]: Info: [pipewire] Streaming display '' offset: 0x0 resolution: 1920x1080[2026-08-01 11:01:16.601]: Info: [wayland] Found display [wayland-0][2026-08-01 11:01:16.601]: Info: [wayland] Found interface: zxdg_output_manager_v1(32) version 3[2026-08-01 11:01:16.601]: Info: [wayland] Found interface: zwp_linux_dmabuf_v1(57) version 5[2026-08-01 11:01:16.601]: Info: [wayland] Found interface: wl_output(64) version 4[2026-08-01 11:01:16.601]: Info: [wayland] Resolution: 1920x1080[2026-08-01 11:01:16.601]: Info: [wayland] Offset: 0x0[2026-08-01 11:01:16.601]: Info: [wayland] Logical size: 1920x1080[2026-08-01 11:01:16.601]: Info: [wayland] Name: eDP-1[2026-08-01 11:01:16.601]: Info: [wayland] Found monitor: Thermotrex Corporation eDP-1-TL070FVXS01-0[2026-08-01 11:01:16.603]: Info: [pipewire] Connected to pipewire version 1.6.4[2026-08-01 11:01:16.621]: Info: [pipewire] Pipewire Error, id:2 seq:13 message: no more input formats[2026-08-01 11:01:18.115]: Info: Creating encoder [hevc_vulkan][2026-08-01 11:01:18.115]: Info: Color coding: SDR (Rec. 709)[2026-08-01 11:01:18.115]: Info: Color depth: 10-bit[2026-08-01 11:01:18.115]: Info: Color range: JPEG[2026-08-01 11:01:18.164]: Info: Streaming bitrate is 1000000[2026-08-01 11:01:18.166]: Info: Vulkan encode using GPU: AMD Ryzen Z1 Extreme (RADV PHOENIX)[2026-08-01 11:01:18.181]: Info: Creating encoder [av1_vulkan][2026-08-01 11:01:18.181]: Info: Color coding: SDR (Rec. 709)[2026-08-01 11:01:18.181]: Info: Color depth: 10-bit[2026-08-01 11:01:18.181]: Info: Color range: JPEG[2026-08-01 11:01:18.218]: Info: Streaming bitrate is 1000000[2026-08-01 11:01:18.219]: Info: Vulkan encode using GPU: AMD Ryzen Z1 Extreme (RADV PHOENIX)[2026-08-01 11:01:18.230]: Info: [2026-08-01 11:01:18.230]: Info: // Ignore any errors mentioned above, they are not relevant. //[2026-08-01 11:01:18.230]: Info: [2026-08-01 11:01:18.230]: Info: Found H.264 encoder: h264_vulkan [vulkan][2026-08-01 11:01:18.230]: Info: Found HEVC encoder: hevc_vulkan [vulkan][2026-08-01 11:01:18.230]: Info: Found AV1 encoder: av1_vulkan [vulkan][2026-08-01 11:01:18.231]: Info: Starting system tray[2026-08-01 11:01:18.231]: Fatal: Couldn't bind RTSP server to port [48010], Endereço já em uso
[2026-08-01 11:01:18.232]: Error: Failed to create client: Daemon not running
[2026-08-01 11:01:18.258]: Info: System tray created
[2026-08-01 11:01:18.258]: Info: Starting main loop
Is there an existing issue for this?
Is your issue described in the documentation?
Is your issue present in the latest beta/pre-release?
I'm too lazy to test
Describe the Bug
Pairing a Moonlight client via the web UI's PIN Pairing page (/pin) always fails with a "CSRF Protection Error" toast, even though
csrf_allowed_originsin sunshine.conf already lists the exact origin being used to access the UI.I confirmed this is not an origin allow-list problem. Using the browser's dev tools, I instrumented
window.fetchon the /pin page and captured the exact request the "Send" button issues:POST ./api/pin
Headers: { "Content-Type": "application/json" }
Body: {"pin":"1234","name":"test-device"}
There is no
X-CSRF-Tokenheader, and the page never calls GET /api/csrf-token beforehand to obtain one. The server correctly rejects this with{"error":"Missing CSRF token","status":false,"status_code":400}.I confirmed the CSRF mechanism itself works fine server-side: manually fetching a token and attaching it as X-CSRF-Token on the same POST /api/pin request succeeds (200,
{"status":true}). So the bug is specifically that the PIN Pairing page's own frontend code never fetches or attaches the CSRF token before submitting.Expected Behavior
Entering a valid PIN and Device Name and clicking "Send" should successfully pair the Moonlight client, the same way manually attaching a fetched X-CSRF-Token to the same request does.
Additional Context
Steps to reproduce:
Workaround that confirms the CSRF mechanism itself is fine: call GET /api/csrf-token (Basic Auth) to obtain a token, then POST /api/pin with that token in an X-CSRF-Token header. That request succeeds normally. It's specifically the /pin page's own frontend code that never performs step 1 of that flow.
Related but distinct issues I found while searching before filing this: #4855 (about the error being invisible to users, fixed by making the toast appear - which is how I could see this error at all) and #5059 (a feature request to disable CSRF entirely for LAN/dynamic-IP use, not this bug). Neither covers the frontend not sending the token in the first place.
Happy to test a fix or provide more info - this is on a fresh Flatpak install with only sunshine.conf hand-edited for csrf_allowed_origins, nothing else customized.Pairing a Moonlight client via the web UI's PIN Pairing page (/pin) always fails with a "CSRF Protection Error" toast, even though
csrf_allowed_originsin sunshine.conf already lists the exact origin being used to access the UI.I confirmed this is not an origin allow-list problem. Using the browser's dev tools, I instrumented
window.fetchon the /pin page and captured the exact request the "Send" button issues:POST ./api/pin
Headers: { "Content-Type": "application/json" }
Body: {"pin":"1234","name":"test-device"}
There is no
X-CSRF-Tokenheader, and the page never calls GET /api/csrf-token beforehand to obtain one. The server correctly rejects this with{"error":"Missing CSRF token","status":false,"status_code":400}.I confirmed the CSRF mechanism itself works fine server-side: manually fetching a token and attaching it as X-CSRF-Token on the same POST /api/pin request succeeds (200,
{"status":true}). So the bug is specifically that the PIN Pairing page's own frontend code never fetches or attaches the CSRF token before submitting.Host Operating System
Linux
Operating System Version
SteamOS 3.8.16 (build 20260716.1) on ROG Ally X
Architecture
amd64/x86_64
Package
Linux - flathub/flatpak
GPU Type
AMD
GPU Model
AMD Radeon 780M (integrated, Ryzen Z1 Extreme APU, Phoenix1)
GPU Driver/Mesa Version
Mesa 25.3.0.213835.radeonsi_25.3.0 (radeonsi)
Capture Method
None
Apps
Log output
Online logs
No response