Skip to content

Support for Content Security Policy (CSP)Β #7213

@oxess

Description

@oxess

The Content Security Policy is important mechanizm for security and we have a popular lib NelmioSecurityBundle which allow to use CSP policy easy.

I propose secure way to support CSP in EasyAdminBundle base on NelmioSecurityBundle:

diff --git a/templates/layout.html.twig b/templates/layout.html.twig
--- templates/layout.html.twig
+++ templates/layout.html.twig
@@ -29,9 +29,12 @@
         <link rel="shortcut icon" href="{{ asset(ea.dashboardFaviconPath) }}">
     {% endblock %}
 
     {% block head_javascript %}
-        <script src="{{ asset('app.js', ea.assets.defaultAssetPackageName) }}"></script>
+        <script 
+            src="{{ asset('app.js', ea.assets.defaultAssetPackageName) }}"
+            {% guard function csp_nonce %}nonce="{{ csp_nonce('script') }}"{% endguard %}>
+        </script>
 
         {% block importmap %}
             {{ include('@EasyAdmin/includes/_importmap.html.twig', {assets: ea.assets.assetMapperAssets ?? []}, with_context: false) }}
         {% endblock %}
@@ -60,12 +63,14 @@
         data-ea-icon-set="{{ ea.assets.iconSet }}"
         data-ea-icon-prefix="{{ ea.assets.defaultIconPrefix }}"
     >
     {% block javascript_page_layout %}
-        <script src="{{ asset('page-layout.js', ea.assets.defaultAssetPackageName) }}"></script>
+        <script src="{{ asset('page-layout.js', ea.assets.defaultAssetPackageName) }}"
+            {% guard function csp_nonce %}nonce="{{ csp_nonce('script') }}"{% endguard %}></script>
     {% endblock javascript_page_layout %}
     {% block javascript_page_color_scheme %}
-        <script src="{{ asset('page-color-scheme.js', ea.assets.defaultAssetPackageName) }}"></script>
+        <script src="{{ asset('page-color-scheme.js', ea.assets.defaultAssetPackageName) }}"
+            {% guard function csp_nonce %}nonce="{{ csp_nonce('script') }}"{% endguard %}></script>
     {% endblock javascript_page_color_scheme %}
 
     {% block wrapper_wrapper %}
         {% block flash_messages %}
diff --git a/templates/includes/_js_assets.html.twig b/templates/includes/_js_assets.html.twig
--- templates/includes/_js_assets.html.twig
+++ templates/includes/_js_assets.html.twig
@@ -3,11 +3,13 @@
     {% if js_asset.preload %}
         {% guard function preload %}
             {% set src = asset(js_asset.value, js_asset.packageName) %}
             <script src="{{ preload(src, {as: 'script', nopush: js_asset.nopush}) }}" {{ js_asset.async ? 'async' }} {{ js_asset.defer ? 'defer' }}
-            {%- for attr, value in js_asset.htmlAttributes %} {{ attr }}="{{ value|e('html') }}"{% endfor %}></script>
+            {%- for attr, value in js_asset.htmlAttributes %} {{ attr }}="{{ value|e('html') }}"{% endfor %}
+            {% guard function csp_nonce %}nonce="{{ csp_nonce('script') }}"{% endguard %}></script>
         {% endguard %}
     {% else %}
         <script src="{{ asset(js_asset.value, js_asset.packageName) }}" {{ js_asset.async ? 'async' }} {{ js_asset.defer ? 'defer' }}
-        {%- for attr, value in js_asset.htmlAttributes %} {{ attr }}="{{ value|e('html') }}"{% endfor %}></script>
+        {%- for attr, value in js_asset.htmlAttributes %} {{ attr }}="{{ value|e('html') }}"{% endfor %}
+        {% guard function csp_nonce %}nonce="{{ csp_nonce('script') }}"{% endguard %}></script>
     {% endif %}
 {% endfor %}
diff --git a/templates/includes/_importmap.html.twig b/templates/includes/_importmap.html.twig
--- templates/includes/_importmap.html.twig
+++ templates/includes/_importmap.html.twig
@@ -1,4 +1,8 @@
 {# @var assets \EasyCorp\Bundle\EasyAdminBundle\Dto\AssetDto[] #}
 {% guard function importmap %}
-    {{ importmap(assets|map(asset => asset.value)) }}
+    {% guard function importmap %}
+        {{ importmap(assets|map(asset => asset.value), {'nonce': csp_nonce('script')}) }}
+    {% else %}
+        {{ importmap(assets|map(asset => asset.value)) }}
+    {% endguard %}
 {% endguard %}
diff --git a/templates/crud/edit.html.twig b/templates/crud/edit.html.twig
--- templates/crud/edit.html.twig
+++ templates/crud/edit.html.twig
@@ -12,9 +12,10 @@
 {% set ea_field_assets = ea.crud.fieldAssets(constant('EasyCorp\\Bundle\\EasyAdminBundle\\Config\\Crud::PAGE_EDIT')) %}
 
 {% block head_javascript %}
     {{ parent() }}
-    <script src="{{ asset('form.js', ea.assets.defaultAssetPackageName) }}"></script>
+    <script src="{{ asset('form.js', ea.assets.defaultAssetPackageName) }}"
+        {% guard function csp_nonce %}nonce="{{ csp_nonce('script') }}"{% endguard %}></script>
 {% endblock head_javascript %}
 
 {% block configured_head_contents %}
     {{ parent() }}
diff --git a/templates/crud/new.html.twig b/templates/crud/new.html.twig
--- templates/crud/new.html.twig
+++ templates/crud/new.html.twig
@@ -12,9 +12,10 @@
 {% set ea_field_assets = ea.crud.fieldAssets(constant('EasyCorp\\Bundle\\EasyAdminBundle\\Config\\Crud::PAGE_NEW')) %}
 
 {% block head_javascript %}
     {{ parent() }}
-    <script src="{{ asset('form.js', ea.assets.defaultAssetPackageName) }}"></script>
+    <script src="{{ asset('form.js', ea.assets.defaultAssetPackageName) }}"
+            {% guard function csp_nonce %}nonce="{{ csp_nonce('script') }}"{% endguard %}></script>
 {% endblock head_javascript %}
 
 {% block configured_head_contents %}
     {{ parent() }}
diff --git a/templates/page/login_minimal.html.twig b/templates/page/login_minimal.html.twig
--- templates/page/login_minimal.html.twig
+++ templates/page/login_minimal.html.twig
@@ -22,9 +22,10 @@
             <link rel="stylesheet" href="{{ asset('app.css', constant('EasyCorp\\Bundle\\EasyAdminBundle\\Asset\\AssetPackage::PACKAGE_NAME')) }}">
         {% endblock %}
 
         {% block head_javascript %}
-            <script src="{{ asset('app.js', constant('EasyCorp\\Bundle\\EasyAdminBundle\\Asset\\AssetPackage::PACKAGE_NAME')) }}"></script>
+            <script src="{{ asset('app.js', constant('EasyCorp\\Bundle\\EasyAdminBundle\\Asset\\AssetPackage::PACKAGE_NAME')) }}"
+            {% guard function csp_nonce %}nonce="{{ csp_nonce('script') }}"{% endguard %}></script>
         {% endblock head_javascript %}
     </head>
 
     <body id="{% block body_id %}{% endblock %}" class="ea {% block body_class %}{% endblock %}">

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions