Recaptcha: Recaptcha should support strict CSP style-src rules.

Created on 18 May 2016  路  26Comments  路  Source: google/recaptcha

The documentation now advice developers to enable style-src='unsafe-inline'.

Should not Recaptcha give an alternative that does not require developers to lower their sites security?

widget

Most helpful comment

Good news - the service has been updated so style-src 'unsafe-inline' is not required. I've tried out a more restrictive CSP on csp-example branch where I'm essentially sending:

Content-Security-Policy:
  default-src 'self';
  script-src 'nonce-rand0m1shValue';
  img-src www.gstatic.com;
  frame-src www.google.com;
  object-src 'none';
  base-uri 'none';

The nonce value is the one being passed to reCAPTCHA in its tag:

<script src="https://www.google.com/recaptcha/api.js?render=your-site-key" nonce="rand0m1shValue"></script>

I'll leave this issue open for a little while in case there are any questions / comments and I'll also merge a separate CSP example onto master.

All 26 comments

is there any chance that this issue will be solved someday?

The reCaptcha FAQ claims that adding a noonce to the initial script tag will allow reCaptcha to work with CSP: link here.
However, my own testing has shown that while the external scripts are loaded correctly, the inline styles are still broken, and thus the widget becomes unusable.

After doing some research, it appears that inline styles _are_ valid in a strict CSP policy, but only if they were set by JavaScript. Link.

So while <div id='example-inline-style' style='color:blue;'></div> is invalid under a strict CSP policy,
<div id='example-inline-style'></div>
<script noonce='noonce'>
document.getElementById('example-inline-style').style.color = 'blue';</script>
achieves the same effect and is perfectly valid.
Could the reCaptcha styles be set this way?

FYI, this is still an issue. I'm using ASP.NET, and using NWebsec to create a nonce.

I can confirm that once my page loads, the nonce attribute has been added to the DOM element and the response headers contain that same nonce, but that rule does not apply to the style sheets that the api and recaptcha_en scripts try to load.

The unsafe-inline directive works, but my employer would never approve that. Will report back if I find a solution.

Nudging this issue. It sort of bums out Google's whole stance on security. I refuse to change my Content Security Policy - impacting my site's security, simply because Google refuses to get with the times.

@bradleyhodges Same here. I'm not allowing inline styles just for recaptcha. Last commit was in March (nine months ago at time of writing), so development seems to have all but died?

Absolutely.. project is definitely dead, but I鈥檓 pretty sure that this repo is for the PHP library alone; meaning that we鈥檇 have to find another way to get Google鈥檚 attention.

It鈥檚 still a massive disappointment to see that Google isn鈥檛 maintaining security across the entire project. There isn鈥檛 even a way to specify a nonce or CSP compliance policy with their Javascript library, and that documentation is on Google鈥檚 own website.

Any updates to this?

I'll try setting a CSP on the demo and see what happens.

I've been playing around locally and it would be useful to hear some feedback on what people are looking for here. You can take a quick look at the csp-example branch where I'm doing this:

$recaptchaNonce = base64_encode(openssl_random_pseudo_bytes(16));
$inlineNonce = base64_encode(openssl_random_pseudo_bytes(16));
$gaIncNonce = base64_encode(openssl_random_pseudo_bytes(16));
$gaCfgNonce = base64_encode(openssl_random_pseudo_bytes(16));

header("Content-Security-Policy: "
    ."script-src 'nonce-".$inlineNonce."' 'nonce-".$recaptchaNonce."' 'nonce-".$gaIncNonce."' 'nonce-".$gaCfgNonce."' 'strict-dynamic'; "
    ."object-src 'none'; "
    ."base-uri 'none'; "
);

To fire off a header:

Content-Security-Policy: script-src 'nonce-XGgRBiS8q/NL9/hMQaTUtQ==' 'nonce-6Hei0z/rbjQEvwHgCc7wXg==' 'nonce-5FQCJydN0DcsTkrGzCFU8g==' 'nonce-HS3M7LHHGSK6b5gxt01gmg==' 'strict-dynamic'; object-src 'none'; base-uri 'none';

Including the library with

<script src="https://www.google.com/recaptcha/api.js?render=<?php echo $siteKey; ?>" nonce="<?php echo $recaptchaNonce; ?>"></script>

Generating

<script src="https://www.google.com/recaptcha/api.js?render=6LdyC2cUAAAAACGuDKpXeDorzUDWXmdqeg-xy696" nonce="6Hei0z/rbjQEvwHgCc7wXg=="></script>

I appreciate this is a very simple example, so it would be helpful to see what you're putting in your actual policies to understand where this doesn't work.

@rowan-m, the reason your example works and ours don't is that we're setting style-src and not setting 'unsafe-inline'. The script itself runs, but the styling is broken and we get a bunch of CSP errors.

If you want to know why we're setting style-src, it's because third-party-css is not safe.

Though I haven't fully deployed it yet, I'm using a strict CSP (no inline JS or CSS) with the following hashes in style-src, with no CSP violations:

'sha256-MammJ3J+TGIHdHxYsGLjD6DzRU0ZmxXKZ2DvTePAF0o='
'sha256-6iA6WDOL1mgUULZ6GSs2OOfP4eMuu6iI5agxCjK2m2A='
'sha256-+zzuded9+DHoztKyASJeCkVU0gxvYNWMUIQM7x//CB4='
'sha256-ldCXMle1JJUAD9eAjLdSuPIgIBcTcBecWlaXs0A2y4M='
'sha256-WCg1a4AhMGgFRCQG5w+hgG+Q2j8Ygrbd+2dgjByIOIU='
'sha256-Awu6hl63MCY3jiYHaDclrL7Lic9KcEalXm2o/i3e0v8='

These are the hashed pieces of inline CSS generated by reCAPTCHA v2 checkbox version.

If you don't trust the above and want to create your own hashes, you can use Chrome's DevTools to grab hashed versions of any inline CSS (if you have CSP blocking inline styles).

@IanOliver Only problem with that is that if Google ever change their CSS, your hashes will no longer match. And Google change their stuff a lot...

@Sora2455 Yes, this is something I should have mentioned - very true.

As far as I'm aware, the CSS for reCAPTCHA hasn't changed in a long time, and hopefully if v3 is being concentrated on, maybe v2 will be left as-is. Maybe :)

@IanOliver Hi! I have tried your hashes, it's not working here... There are some works that spend time implementing nonce such as "material-ui" for react.. that's a bad design choice 馃憥

@arelaxend on my blog, the hashes are different too. You'd have to test with a Content-Security-Policy-Report-Only to determine yours.

@borisschapira thank you, i will test this later, since i don't know how to send headers via React

@arelaxend First, you don't send headers in React. You send them through whatever platform you're hosting React in - Node.JS, ASP MVC, ASP.NET, PHP, Ruby on Rails, etc.

Second, if the hashes are different for different people, Google might very well be delivering different CSS for different people, making hashing near-impossible.

@sora2455 yes indeed, i meant i don鈥檛 know how to add an http header in nodejs and to trigger this out in react, but anyway, I will find this out! By the way I choose to set a unsafe rule for my tests, since we have no info. about this from the re captcha team. For production, I might consider removing recaptcha.. I found that many people have the same issue. Either we are completely wrong about how it is supposed to work, or it鈥檚 a 芦聽bad聽禄 design choice. In the end, it creates for sure difficulties for many teams and this is not a good news, it won鈥檛 help people secure their apps.

On this topic, I have found somebody on stackoverflow that manages to create a hack to automatically create hash at load time and still it doesn鈥檛 work.

@rowan-m I kindly ask: Is there gonna be a solution for this issue? Please, developers don't want to lower their security levels.

@Virgomax Hilariously, despite this issue being the one getting all the attention, it's on the wrong repo. This is for the PHP library - there isn't one for the actual service/JavaScript.

@Sora2455 Oh thanks, I didn't notice.
@Virgomax I don't think there will be a solution, as there is also a bug on Chrome preventing the hashes from being recognized by the browser.

capture d ecran 2018-09-21 a 09 22 30

I also raised a bug with Chromium recently. The hashes I'd previously published worked perfectly in Chrome 68, and then were affected by this bug in Chrome 69: https://bugs.chromium.org/p/chromium/issues/detail?id=881847

@Sora2455 :O !!! You are right! I just landed here directly from the search engine and I didn't even see the Readme.md. Looks like I've been wrong my entire life. Thanks for opening my eyes. ;) I'll go to swear at some other repo.

@borisschapira that's awful. Guardian angel, where the hell are you?

Good news - the service has been updated so style-src 'unsafe-inline' is not required. I've tried out a more restrictive CSP on csp-example branch where I'm essentially sending:

Content-Security-Policy:
  default-src 'self';
  script-src 'nonce-rand0m1shValue';
  img-src www.gstatic.com;
  frame-src www.google.com;
  object-src 'none';
  base-uri 'none';

The nonce value is the one being passed to reCAPTCHA in its tag:

<script src="https://www.google.com/recaptcha/api.js?render=your-site-key" nonce="rand0m1shValue"></script>

I'll leave this issue open for a little while in case there are any questions / comments and I'll also merge a separate CSP example onto master.

Closing this off as I've popped up an example in examples/recaptcha-content-security-policy.php

Was this page helpful?
0 / 5 - 0 ratings