Mockup requires `unsafe-eval` for `script-src` rule when configuring CSP header
Opened this issue · 10 comments
This can be reproduced as follows:
- Create a
docker-compose.yml
with this contents:
version: '2'
services:
nginx:
container_name: nginx
image: nginx:latest
ports:
- "80:80"
volumes:
- ${PWD}/nginx.conf:/etc/nginx/conf.d/default.conf
network_mode: "host"
- Next to it, create a
nginx.conf
with this:
server {
listen 80;
server_name test_csp.plone.com;
add_header Content-Security-Policy "script-src 'self';";
location / {
limit_except GET POST { deny all; }
rewrite ^(.*)$ /VirtualHostBase/http/test_csp.plone.com:80/Plone/VirtualHostRoot$1 break;
proxy_pass http://127.0.0.1:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Authorization "";
}
}
- Edit your
/etc/hosts
and configuretest_csp.plone.com
to point at127.0.0.1
- Start a fresh Plone listening in
8080
and create an emptyClassic Plone site
- Where you put the
docker-compose.yml
andnginx.conf
rundocker compose up
At this point, you should be able to open your browser and point to http://test_csp.plone.com/ to reach your site. If you try to login by opening the login modal, you will not be able to, and you can see an error message in the developer tools
Uncaught EvalError: call to Function() blocked by CSP
dr Underscore
render modal.js:427
render modal.js:901
_show modal.js:971
ajaxXHR modal.js:616
jQuery 6
createAjaxModal modal.js:608
show modal.js:908
init modal.js:592
jQuery 8
init modal.js:589
d base.js:59
n base.js:105
c base.js:40
initPattern registry.js:119
scan registry.js:200
init registry.js:71
jQuery 9
init registry.js:64
17704 patterns.js:74
Webpack 5
template.js:87:13
dr Underscore
render modal.js:427
render modal.js:901
_show modal.js:971
ajaxXHR modal.js:616
jQuery 6
createAjaxModal modal.js:608
show modal.js:908
init modal.js:592
jQuery 8
init modal.js:589
d base.js:59
n base.js:105
c base.js:40
initPattern registry.js:119
scan registry.js:200
init registry.js:71
jQuery 9
init registry.js:64
17704 patterns.js:74
Webpack 5
Now, if you edit the nginx.conf
and change the line
add_header Content-Security-Policy "script-src 'self';";
To this
add_header Content-Security-Policy "script-src 'self' 'unsafe-eval';";
Then kill nginx
and run docker compose up
, you can now see the login modal and everything works fine.
This issue is related to jashkenas/underscore#906 and jashkenas/underscore#2273 (Which basically are the same issue).
I don't know if this can be exploited in any way, however it is an issue, being that unsafe-eval
completely blocks the usage of _.template
.
On the second issue, an alternative is proposed (https://github.com/silvermine/undertemplate), would moving to this be acceptable?
I had a similar problem directly in Patternslib:
Patternslib/Patterns@989fa9f
Patternslib/Patterns@e38f987
Patternslib/Patterns@78c544b
That's interesting, that underscore has the same problem.
It's necessary to fix this problem.
I didn't know about https://github.com/silvermine/undertemplate but I think it's fine to use it to get rid of the CSP error and move forward.
Sorry, I never had this one. But undertemplate looks good as we might get rid of underscore
completely then, because it's mainly used for templates since ES6 rewriting.
@thet Well, I started replacing _.template
with this undertemplate, however I found that there are templates that in fact do have some JS evaluation (for instance https://github.com/plone/mockup/blob/master/src/pat/relateditems/templates/toolbar.xml) so this cannot be simply replaced, sounds like I will need to refactor them... unless you have a better idea?
While migrating pat-select2
(unfinished #1295 🫣) we talked about replacing relateditems with a new pattern not using select2 anymore. @MrTango had an insteresting approach which we maybe should look more into it instead of fiddling around with the current implementation. but that's of course a larger task than simply refactor a template to undertemplate.
@frapell looks like undertemplate does not support conditional statements like <% if ...
.
That looks like a showstopper for undertemplate to me.
In that case another templating library would probably be better.
There is ejs, which looks similar in syntax, but I think it has the same CSP problem: https://github.com/mde/ejs
or moustache instead?
@thet Right, the problem is with evaluating JS code within the template, which you cannot do in undertemplate nor moustache, and yeah, ejs seems to have the same issue mde/ejs#468
I don't really see other way around than using a templating lib that doesn't allow JS evaluation, and do all our logic in code, and not the templates. That does remove flexibility into being able to change the template used for rendering the widget, but then again, is anyone really doing it?
@petschki Didn't know you were working on that, it could be a good opportunity to strip out _.template
usage...
but then again, is anyone really doing it?
I do 🫣 https://github.com/collective/collective.behavior.relatedmedia/blob/main/collective/behavior/relatedmedia/resources/relateditems_selection.xml ... sorry 😉
But that's all obsolete when we come up with a new relateditems solution, which I'm really lookging forward to!