directus
directus copied to clipboard
Self Hosted config options (helmet's adaptation)
Describe the Request
I think it would be nice to add at least:
OR
- a more precise docs for CONTENT_SECURITY_POLICY_*
- a doc page for how to setup livepreview for self hosted
because now (not some times ago) I had a CSP error with IFRAME.
So I spend hours to understand (not find it but I deducted it) that
CONTENT_SECURITY_POLICY_DIRECTIVES__FRAME_SRC="array:https://www.yourwebsite.com/"
In the .env file was the solution ^^
Maintainence Strategy
As often as the config option of CSP will change
Thanks. we need a document for this
Had the same problem. Here is my not-expert description:
Directus Default CSP
By default the configuration for CONTENT_SECURITY_POLICY is highly restrictive, and this is a feature, because it provides more security without effort. The default CSP Response Header is:
content-security-policy:
script-src 'self' 'unsafe-eval';
worker-src 'self' blob:;
child-src 'self' blob:;
img-src 'self' data: blob: https://raw.githubusercontent.com https://avatars.githubusercontent.com;media-src 'self';
connect-src 'self' https://* wss://*;
default-src 'self';
base-uri 'self';
font-src 'self' https: data:;
form-action 'self';
frame-ancestors 'self';
object-src 'none';
script-src-attr 'none';
style-src 'self' https: 'unsafe-inline'
This header is sent as an HTTP Response Header content-security-policy
for any Directus Admin page.
These directives define which domain/host a request can be sent to, by HTML elements present in the Directus Admin page. The CSP specs allows granular control, defining whitelist domains for every HTML element that can perform an HTTP request
<script src="..."/> => script-src
<iframe src="..."/> => frame-src
<object src="..."/> => object-src
<img src="..." /> => img-src
...
If a frame-src
directive is not defined, the fallback will be child-src
, but it's recommended to use frame-src
.
Like frame-src, every other directives, if not defined, will fallback to
child-src
as well, but THIS IS ONLY MY UNVERIFIED ASSUMPTION.
Directus Live Preview / Draft Mode
In Directus, to enable live preview mode, you go in Settings > Data Model > Select a Collection
and find an input where you defined the URL of the draft page. Directus will inject this URL as the src
attribute of the iframe
used for Live Preview.
Here is an example of that URL:
http://localhost:3000/draft/page
The domain entered here must be reachable by the CSP policy, so you must explicitly define it.
In this case you must define http://localhost:3000
.
Define CSP for Directus Admin
You must use Environment Variables for that (or any equivalent based on your env, like docker-compose )
# .env
# frame-src
CONTENT_SECURITY_POLICY_DIRECTIVES__FRAME_SRC="array:http://localhost:3000/"
# child-src
CONTENT_SECURITY_POLICY_DIRECTIVES__CHILD_SRC="array:http://localhost:3000/"
...
Why this strange syntax ?
Directus uses helmet inside the Web Server so these env var will be passed to helmet.
This is how in an express app you define global helmet configration
app.use(
helmet({
contentSecurityPolicy: {
directives: {
"frame-src": ["'self'", "http://localhost:3000", "instagram.com"],
"script-src": ["'self'", "http://localhost:3000"],
},
},
})
);
Directus parse the env var, looks for the tail i.e. DIRECTIVES__FRAME_SRC
and inject the value in the helmet config.
# .env
CONTENT_SECURITY_POLICY_DIRECTIVES__FRAME_SRC="array:'self',http://localhost:3000/,instagram.com" # array syntax 1
CONTENT_SECURITY_POLICY_DIRECTIVES__IMG_SRC="'self',http://localhost:3000/,instagram.com" # array syntax 2
# helmet config
app.use(
helmet({
contentSecurityPolicy: {
directives: {
"frame-src": ["'self'", "http://localhost:3000", "instagram.com"],
"img-src": ["'self'", "http://localhost:3000", "instagram.com"],
},
},
})
);
NOTE: 'self' refers the the actual page, and must be
'self'
and notself
. This is why it has double quotes.