-
-
Notifications
You must be signed in to change notification settings - Fork 285
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
feat: add Content-Security-Policy Header, allows setting frame-ancestor domains and moved font local #975
base: develop
Are you sure you want to change the base?
Conversation
47b9161
to
6ca4177
Compare
bbb46b9
to
75651f6
Compare
Ah, i think you already had an existing configuration and then the new setting is missing and wont be displayed.. wasnt aware there isnt a migration for that. |
@ThomasVicot I have checked, the setting doesnt require a migration, if the field doesnt appear, you did something wrong. |
The todo is not the steps to checkout prs. Thats for the PR authors todos... to checkout prs you do: |
…or domains and moved font local fix Fallenbagel#455
75651f6
to
6019d98
Compare
This pull request has merge conflicts. Please resolve the conflicts so the PR can be successfully reviewed and merged. |
…rame-ancestor-domains
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am unsure if we should complexity remove the SameSite attribute or leave it with the condition when Frame-Ancestor Domains is unset like i have done currently.
IMHO I think it's ok the way you've done it. @M0NsTeRRR may have a more stronger opinion on the subject.
@@ -44,6 +44,9 @@ const messages = defineMessages('components.Settings.SettingsMain', { | |||
csrfProtectionTip: 'Set external API access to read-only (requires HTTPS)', | |||
csrfProtectionHoverTip: | |||
'Do NOT enable this setting unless you understand what you are doing!', | |||
cspFrameAncestorDomains: 'Frame-Ancestor Domains', | |||
cspFrameAncestorDomainsTip: | |||
'Domains to allow embedding Jellyseer as iframe, object or embed. Incompatible with CSRF-Protection', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't you specify here that this is a space-separated list of domains?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are more possibilities to setting this than just space separated as this is directly put into the header.
But maybe we could link to the specification: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh ok. That's a good idea yes
*:disabled { | ||
opacity: 0.7; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before, the text-box wasnt visibly disabled apart from not being able to interact with it, so this makes it a bit more visible
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you check that this does not have any other unexpected behavior? It could have undesired effects on some text fields. and other fields too*
We usually do styling using TailwindCSS, inside the class
attribute of the elements
import Head from 'next/head'; | ||
import { useEffect, useState } from 'react'; | ||
import { IntlProvider } from 'react-intl'; | ||
import { ToastProvider } from 'react-toast-notifications'; | ||
import { SWRConfig } from 'swr'; | ||
const inter = Inter({ subsets: ['latin'] }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe you could add a newline after the imports?
Fully agree
Fully agree
Not exactly. CSRF protection shouldn't affect the CSP header, but it does in this case because it isn't configured properly. CSRF protection is meant to prevent logged-in users from unknowingly executing actions (such as via a JavaScript fetch when they visit a webpage). Ideally, CSRF protection should only apply to form pages and shouldn't impact iframes, as iframes are used only for displaying data not form. If we don't want to disable CSRF for CSP (we should do that), we need to fix the CSRF system in this way. |
Yeah i worded that too broadly, CSP in general is fine, but CSP ancestor-domains/iframes in combination with SameSite is incompatible. So the CSRF cookie would simply need SameSite none. So i guess we can change Lines 157 to 174 in 257cab3
sameSite: true to 'none' ?
Another thing should probably then be to be able to bypass CSRF protection with API-keys to have read/write API, but protected for user-actions, but thats for the future. |
Jellyseerr is a stateless application that uses signed double submit cookies to prevent CSRF attacks. According to the proposed standard, we should set the
Yes |
Yeah i havent thought this through fully. So maybe using the signed-token approach via header or somewhere an attacker cannot obtain it and/or get the browser to submit it via Cross-Origin. I think for now we can implement this PRs iframe-support with disabling the current cookie-based CSRF-protection and then gradually move towards a more compatible system? |
As I mentioned before, CSRF protection should be disabled for non-action requests. By 'action,' I mean any operation that updates the application, like POST, PATCH, or DELETE requests. GET requests don't require CSRF protection, which would allow us to use iframes without encountering this issue. Regarding
There is no API to read initial page HTTP response header.
That’s up to the maintainer, but in my opinion, I disagree. Adding a 'feature' (iframe) that disables security, potentially allowing unauthorized admin access via an HTTP POST request on the create user endpoint, could lead to serious issues. I previously submitted a CVE for network equipment that had this vulnerability (about 20 lines of code) and was rated as a 8.8 CVE. |
As the maintainer, I would like to avoid security vulnerabilities/CVEs as much as possible, so I'm with @M0NsTeRRR on this. |
This pull request has merge conflicts. Please resolve the conflicts so the PR can be successfully reviewed and merged. |
Description
I have added Content-Security-Policy Header in a very moderate mode not to break any current features.
Through Content-Security-Policy we can allow specific origins or "Frame-Ancestors" to embed jellyseer as e.g. iframe.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors
Currently, correct usage in an iframe is blocked by strict or lax setting of SameSite on the session- and, if enabled, the csrf-cookie, which results in the cookie not getting send in a request which originates from a cross-origin.
jellyseerr/server/index.ts
Lines 163 to 175 in edfd804
This setting is incompatible with CSRF-Protection as its not possible to have the protection without SameSite strict.
I am unsure if we should complexity remove the SameSite attribute or leave it with the condition when Frame-Ancestor Domains is unset like i have done currently.
As my setup of Content-Security-Policy also blocked the google-fonts request, i simply moved it to local with the additional benefit of speed and privacy.
If you rather want to, we can remove most of the Content-Security-Policy not to hinder future features, but its a good thing for security usually to block anything we dont expect like loading external javascript.
Screenshot (if UI-related)
The setting is a space-separated string of domains.
When the browser blocks the request, it looks something like this:
And here when having added the domain:
To-Dos
pnpm build
pnpm i18n:extract
Issues Fixed or Closed