Privatebin: Content Security Policy blocks the use of 'eval' in JavaScript

Created on 13 Mar 2021  路  5Comments  路  Source: PrivateBin/PrivateBin


Hi, when setting up a local self-hosted copy I noticed issues with the CSP headers. The browser dev-tools is blocking some javascript because I do not use unsafe-eval as script-src.

Steps to reproduce

  1. Load
  2. Open browser console/dev-tools

What happens

Some unsecure javascript is blocking zlib-1.2.11.js from loading

What should happen

Additional information


Firefox:
image

Opera:
image

Edge:
image

Basic information


Server address:
N/A


Server OS:
Gentoo Linux 5.11.6


Webserver:
Apache 2.4.46


Browser:
Opera and FireFox


PrivateBin version:

I can reproduce this issue on https://privatebin.net: Yes

question

Most helpful comment

unsafe-eval is used for more then just wasm support, but also in the browser capability detection:
https://github.com/PrivateBin/PrivateBin/blob/5a9bcea3a919af84e275dc77c80ea270272a4663/cfg/conf.sample.php#L86-L90

You can disable compressed pastes using a configuration option, but note three things:

  • It will still load the zlib module, if your browser supports wasm, in case you try to open a compressed paste from before you turned compression off. It will just not store new pastes in compressed format.
  • Having wire compression support in the webserver or the filesystem compression enabled doesn't do much to reduce the pastes size, as their payload is encrypted. Encrypted content (without a key) can't be compressed, because it looks indistinguishable from random noise to a compression algorithm and it looks for patterns to deduplicate - hence we have to compress before encrypting. Due to our applications design, this has to happen on the client side, since the server only ever gets to see the encrypted content and doesn't have the key.
  • The reason we do offer to disable encryption is for certain security considerations. In some contexts compressing before encrypting has been shown to make the encrypted payload susceptible to side channel attacks. On the other hand, not compressing plain text before encrypting means the encrypted payload is roughly the same size as the clear text (rounded up to the next AES block size of 128 bits), so not compressing plain text leaks some information on the plain text message size. For example, the OpenVPN project switched from compression enabled by default to have it _disabled_ by default. Privatebin still has it enabled by default, because we assume that leaking information on the size of the plain text would be more harmful then the potential side channel opened by the zlib deflate compression. zlib's standard compression (as opposed to the raw deflate stream that we use in privatebin), always starts with the same 2 "magic" bytes and a trailing 4 bytes checksum. As we know from the case of the enigma, using the same sequence of letters in a certain spot of your message might make it simpler to decrypt without knowing the key.

All 5 comments

I saw in the code that zlib is only needed if I wanted compressed pastes. I don't because I use compressed filesystem and brotli/deflate output from apache. Is there a way to prevent the zlib.js/wasm files from being loaded from the webserver at all?

unsafe-eval is used for more then just wasm support, but also in the browser capability detection:
https://github.com/PrivateBin/PrivateBin/blob/5a9bcea3a919af84e275dc77c80ea270272a4663/cfg/conf.sample.php#L86-L90

You can disable compressed pastes using a configuration option, but note three things:

  • It will still load the zlib module, if your browser supports wasm, in case you try to open a compressed paste from before you turned compression off. It will just not store new pastes in compressed format.
  • Having wire compression support in the webserver or the filesystem compression enabled doesn't do much to reduce the pastes size, as their payload is encrypted. Encrypted content (without a key) can't be compressed, because it looks indistinguishable from random noise to a compression algorithm and it looks for patterns to deduplicate - hence we have to compress before encrypting. Due to our applications design, this has to happen on the client side, since the server only ever gets to see the encrypted content and doesn't have the key.
  • The reason we do offer to disable encryption is for certain security considerations. In some contexts compressing before encrypting has been shown to make the encrypted payload susceptible to side channel attacks. On the other hand, not compressing plain text before encrypting means the encrypted payload is roughly the same size as the clear text (rounded up to the next AES block size of 128 bits), so not compressing plain text leaks some information on the plain text message size. For example, the OpenVPN project switched from compression enabled by default to have it _disabled_ by default. Privatebin still has it enabled by default, because we assume that leaking information on the size of the plain text would be more harmful then the potential side channel opened by the zlib deflate compression. zlib's standard compression (as opposed to the raw deflate stream that we use in privatebin), always starts with the same 2 "magic" bytes and a trailing 4 bytes checksum. As we know from the case of the enigma, using the same sequence of letters in a certain spot of your message might make it simpler to decrypt without knowing the key.

Thanks for the detailed answer and I think it makes sense.

I enabled the CSP headers from the conf.php file but chrome still warns about the same thing.

image

I've also set less strict headers in Apache to test, but the result is the same.

Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-eval';"

The Chrome message is a bit misleading - it warns you about the usage of unsafe-eval (which is a bit silly as Chrome will only accept loading WASM dynamically when unsafe-eval is enabled, unlike Firefox which loads it just fine without that setting) and it implies that the script which loads the zlib WASM _would be affected_ if you were to disable it.

If you test your site using Chrome and create a paste, you can see in the JSON of the paste (in the network tab, it's the POST request sent after you hit the send button) that it indeed has the compression property set to "zlib" and not "none" (it's the key .adata[0][7] as per our API's JSON-LD schema), so Chrome does load the zlib WASM just fine and is able to use it.

I think this question has been answered and I am closing the issue. Please feel free to reply if you have follow-up questions or create a separate issue for different topics.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

HLeithner picture HLeithner  路  3Comments

elrido picture elrido  路  3Comments

ZerooCool picture ZerooCool  路  3Comments

jeyca picture jeyca  路  4Comments

pstray picture pstray  路  7Comments