RamblingRoss
The blog of Ross Fruen, a .NET consultant

Grav, CSP and inline scripts

The Grav codebase currently supports inlining of javascript via the addInlineJs method. A useful feature, but one that presents a problem when generating a suitably secure content security policy for your website - namely the avoidance of 'unsafe-inline'.

It would be great if this method could (optionally) include the inline javascript within the Asset Manager pipeline. If this was possible then inline scripts could still be included by the author within a web page but would be rendered by Grav as an external script. If all scripts are external then the CSP does not need to include 'unsafe-inline' within 'script-src'.

A simple change to the AssetManager adds this functionality. Open the file /src/Grav/Common/Assets.php and navigate to the function public function addInlineJs($asset, $priority = null, $group = null, $attributes = null).

We now need to modify this function so that it will honour instructions to add the inline javascript into the pipeline.

The original code block appears as:

    $key = md5($asset);
if ($asset && is_string($asset) && !array_key_exists($key, $this->inline_js)) {
$this->inline_js[$key] = $data;

We need to prepend this block with a check for the term 'pipeline' within the $data constructed from the function arguments. If the term 'pipeline' is found then write the inline javascript to a file and include that within the pipeline.

    if ($this->js_pipeline && isset($data['pipeline']) && strtolower($data['pipeline']) == 'true') {
$inlineFile = md5($asset) . '.js';

if (!file_exists($this->assets_dir . $inlineFile)) {
file_put_contents($this->assets_dir . $inlineFile, $asset);
}

$relative_path = "{$this->base_url}{$this->assets_url}/{$inlineFile}";

$this->addTo($this->js, $relative_path, $data['priority'], $data['pipeline'], null, $data['group']);
}
else {
$key = md5($asset);
if ($asset && is_string($asset) && !array_key_exists($key, $this->inline_js)) {
$this->inline_js[$key] = $data;
}
}

To include inline javascript in the pipeline provide an option with a name of 'pipeline' and value of 'true' as demonstrated below:

     {% do assets.addInlineJs('$.noop();', {'group':'bottom', 'pipeline':'true', 'priority' : '95' }) %} 

Add a comment

If you want your comment to appear on this page please complete the form below. Your name and email address are optional, although the latter will be required if you want a response. Your email address will not appear against your comment and will only be used to correspond with yourself (where appropriate).

Thanks!

Thank you for submitting your comment, it will appear here after moderation is complete.

Sorry

There was a problem sending your comment, please try again.