8

When developing for the web, I often find myself wanting to pass a few variables from the server scripts to my javascript - data pulled from a database, and set differently on different pages running basically the same code. (Typically, this is something along the lines of example.com/slideshows/1 needing to know that that slideshow 1 has 8 images, and what their urls are, but that's just a random example; I'm looking for a general answer.)

My normal approach is to include a short block of inline javascript that sets a few global variables or calls some initializer functions, which is straightforward and effective. It is not, however, Content Security Policy-friendly, since inline javascript is blocked by default, and not without reason. (I know the policy can be set to allow inline javascript if you have access to it, but even if you do that opens potential security issues.) I need a strategy that plays nicely with proper CSPs.

I know that it could be done with an ajax call, but that's overkill for something that only needs to be set once, and adds an extra call that slows down the page load. In some cases, like the slideshow I mentioned, this could be handled by having the javascript examine other dynamically-constructed page elements to reconstruct the desired data, which is fine, but not a very general solution. What's the best way to handle this?

(I almost posted this question on SO, but it seems kind of subjective; I can think of ways to do this, I just don't like any of them.)

2 Answers 2

3

You could use a hash. If you had an inline script like this:

<script>alert('Hello, world.');</script>

You can hash it and specifiy it in your Content-Security-Policy header.

Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='

There's also a mechanism for using a nonce:

<script nonce=EDNnf03nceIOfn39fn3e9h3sdfa>
Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa' 

Examples taken from: http://www.html5rocks.com/en/tutorials/security/content-security-policy/

If you really don't even want that, you don't have many options, but you could:

3
  • I don't find the usage of data tags gross for this. We are passing data in a data-tag. Seems like a perfect fit in a simple and straight forward manner, Commented Aug 31, 2015 at 6:53
  • I've considered using hidden form elements with values containing the data, be that a string or JSON... although I run into issues due to escapement etc. Do you know if data-tags suffer the same shortfalls? In my similar case I'm passing an 'object' or PHP associate array to the on page JS using the PHP JSON encode function. Otherwise I guess the most sensible way is to use hash/nonce...
    – hozza
    Commented Oct 10, 2016 at 13:29
  • How about inline JSON inside a script tag?
    – Tobi G.
    Commented Aug 2, 2019 at 23:40
0

If you only need to pass along a simple string from the server-side to the JavaScript, at load time, with a standard inline blocking CSP in place, I imagine using a HTML5 data-tag is the most 'official' way as Newtang answered... although, if you want a more general approach which could include other types of data such as array/object the following may help...

Server-side Language Set CSP (<meta> tag or Header)

If you are using a 'Content Security Policy' in a <meta> tag or header set by the server-side programming language, rather than a header being set by the server itself and assuming, as in your case, the script/styles can't really be moved into a static external file and are too impractical to request by AJAX. You'll need to resort to a hash exception...

Since you are already reading the data and outputting into JavaScript syntax on the server-side, it's quite straightforward to store all the JavaScript code (populated with the data e.g. strings, JSON etc. and excluding the actual script tags) in a string, hash using SHA algorithm then output the resulting hash into the CSP meta tag along with the actual JavaScript code (now with script tags) 'later on' in the document.

This has the added benefit (over a nonce) of ensuring the JS code is intact and unmodified within the newly whitelisted script tag, as the hash would not match if this script content was modified in transit.

For example, in PHP:

<?php echo "<meta http-equiv=\"Content-Security-Policy\" content=\"default-src 'self' 'sha256-".base64_encode(hash('sha256', $JavaScript_code, true))."'\">"; ?>

the true in hash() is to ensure the output is in binary as the default lowercase hexits will not work.

And then, 'later on' in the document output the actual JavaScript, paying close attention to whitespace (e.g. spaces, tabs, formatting) which will alter the hash.

<?php echo '<script type="text/javascript">'.$JavaScript_code.'</script>'; ?>

httpd Server Set CSP (Header)

It would be a little less strait forward if the CSP is set in a header via the httpd server directly (as is preferred)...

You would need to modify the server sent CSP header with an additional hash or nonce before it is sent to the client (not as easy) and simply setting a new <meta> tag with the hash/nonce generated by server-side code does not take precedent over the already set header. (reference in the 'Syntax and Delivery' section, although I'm sure there is a more official reference somewhere).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.