How to use 'unsafe-inline' Content-Security-Policy in Vaadin?

1.2k views Asked by At

I am developing an application with Vaadin and I use Content-Security-Policy in my BootstrapListener. When I test my application with OWASP ZAP, I have problem with script-src 'unsafe-inline' (medium risk). When I delete the 'unsafe-inline', my application doesn't work.

My code:

String csp = "";
String defaultSrc = "default-src 'none'";
String styleSrc = "style-src 'unsafe-inline' 'self'";
String fontSrc = "font-src 'self'";
String scriptSrc = "script-src 'unsafe-inline' 'unsafe-eval' 'self'";
String imgSrc = "img-src 'self'";
String connectSrc = "connect-src 'self'";
String frameAncestors = "frame-ancestors 'self'";
String formAction = "form-action 'self'";
csp = Arrays.asList(defaultSenter code hererc,styleSrc,fontSrc,scriptSrc,imgSrc,connectSrc,frameAncestors,formAction).stream().collect(Collectors.joining(";"));
                            
2

There are 2 answers

0
nemmondod On

As per Vaadin documentation using scriptSrc = "script-src 'unsafe-inline' 'unsafe-eval' 'self'"; is a known "limitation" or architectural choice of the devs that you can't change without major modifications in the framework:

The settings script-src 'unsafe-inline' 'unsafe-eval' and style-src 'unsafe-inline' are required during Vaadin application start, that is, the bootstrap process. The bootstrap process that starts the application loads the widget set which is the client-side engine part of the application. This consists of precompiled JavaScript logic, for example, for the communication protocol, DOM control, Buttons, Layouts, etc., but not the application code. The widget set is a static resource. After it is loaded, the client-side engine needs to be started using JavaScript.eval().

Hence, these settings are architectural limitations in Vaadin, so that the framework can start its client-side engine in the browser.

Reported as: Missing or insecure “Content-Security-Policy” header

XSS/Code injection securitywise, what you can do (or may already did) is using the built in escaping for outputs:

Div div = new Div();

// These are safe as they treat the content as plain text
div.setText("<b>This won't be bolded</b>");
div.getElement().setText("<b>This won't be bolded either</b>");
div.setTitle("<b>This won't be bolded either</b>");

// These are NOT safe
div.getElement().setProperty("innerHTML", "<b>This IS bolded</b>");
div.add(new Html("<b>This IS bolded</b>"));

new Checkbox().setLabelAsHtml("<b>This is bolded too</b>");

and sanitization:

String safeHtml = Jsoup.clean(dangerousText, Whitelist.relaxed());
new Checkbox().setLabelAsHtml(safeHtml);

Furthermore there is a reason why those are marked as "unsafe-", the problem is that if there is a flaw in the framework or you miss an escaping then CSP can't differentiate injected code from the original. You should always "tag" your own safe scripts by putting them in external files or using nonce.

0
appvad On

So if I use this code

scriptSrc = "script-src 'nonce-rAnd0m' 'unsafe-eval' 'self'";

It doesn't work. I have this error

Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'nonce-rAnd0m' 'unsafe-eval' 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-2+3KFFww9bjFUMmzU872aJ+b2DMgLMn/Hel8bO8Y9xg='), or a nonce ('nonce-...') is required to enable inline execution.