From 281045bbad22cb7ca3061e0e4961b05a7497c603 Mon Sep 17 00:00:00 2001
From: Lucas Brandstaetter <lucas@brandstaetter.tech>
Date: Thu, 28 Nov 2024 02:11:13 +0100
Subject: [PATCH] Add CSP nonce to all inline scripts

Fixes #600
---
 .../templates/backoffice/activitylog_card.html     |  2 +-
 .../templates/backoffice/assembly_event.html       |  2 +-
 .../templates/backoffice/assembly_events.html      |  2 +-
 .../templates/backoffice/assembly_list.html        |  2 +-
 .../backoffice/assembly_room_wa_linterblock.html   |  2 +-
 .../backoffice/conferences/publication_edit.html   |  2 +-
 .../backoffice/conferences/registration_edit.html  |  2 +-
 .../templates/backoffice/event/list.html           |  2 +-
 .../templates/backoffice/map_floor_list.html       |  2 +-
 .../templates/backoffice/map_poi_list.html         |  2 +-
 .../backoffice/moderation_assembly-list.html       |  2 +-
 .../backoffice/moderation_badge-list.html          |  2 +-
 .../templates/backoffice/moderation_base.html      |  2 +-
 .../backoffice/moderation_board-list.html          |  2 +-
 .../templates/backoffice/moderation_user-list.html |  2 +-
 .../templates/backoffice/moderation_wiki-list.html |  2 +-
 .../templates/backoffice/project/create_edit.html  |  2 +-
 .../templates/backoffice/project/list.html         |  2 +-
 src/backoffice/templates/backoffice/sos.html       |  4 ++--
 .../templates/backoffice/sos_create_edit.html      |  2 +-
 .../templates/backoffice/wa-map-detail.html        |  2 +-
 .../templates/backoffice/wa-map-list.html          |  2 +-
 .../templates/backoffice/wiki_lock_list.html       |  2 +-
 src/core/templates/core/map.html                   |  2 +-
 .../oauth2_provider/out-of-band-display-token.html |  2 +-
 src/plainui/jinja2/plainui/base.html.j2            |  4 ++--
 .../jinja2/plainui/components/integrations.html.j2 |  2 +-
 src/plainui/jinja2/plainui/components/map.html.j2  |  2 +-
 src/plainui/jinja2/plainui/public_fahrplan.html.j2 |  2 +-
 .../jinja2/plainui/static_page_edit.html.j2        | 14 +++++++++-----
 30 files changed, 40 insertions(+), 36 deletions(-)

diff --git a/src/backoffice/templates/backoffice/activitylog_card.html b/src/backoffice/templates/backoffice/activitylog_card.html
index c3309797c..7e4d50eb5 100644
--- a/src/backoffice/templates/backoffice/activitylog_card.html
+++ b/src/backoffice/templates/backoffice/activitylog_card.html
@@ -112,7 +112,7 @@
   </div>
 {% endif %}
 
-<script>
+<script nonce="{{ request.csp_nonce }}">
   alc_div = document.getElementById("logentries_{{ alc_ident }}");
   // make "visible log entries" selector visible and click the "w/ msg only" one
   document.getElementById("visible_logentries_{{ alc_ident }}").classList.remove("d-none");
diff --git a/src/backoffice/templates/backoffice/assembly_event.html b/src/backoffice/templates/backoffice/assembly_event.html
index fba3d006b..ccbd41d97 100644
--- a/src/backoffice/templates/backoffice/assembly_event.html
+++ b/src/backoffice/templates/backoffice/assembly_event.html
@@ -12,7 +12,7 @@
 {% endblock title %}
 {% block scripts %}
   <script src="{% static "backoffice/modal.js" %}"></script>
-  <script>
+  <script nonce="{{ request.csp_nonce }}">
   $(document).ready(() => {
     showModal = registerModal()
     publishEvent = document.getElementById('publishEvent');
diff --git a/src/backoffice/templates/backoffice/assembly_events.html b/src/backoffice/templates/backoffice/assembly_events.html
index 3229cb926..103bc5842 100644
--- a/src/backoffice/templates/backoffice/assembly_events.html
+++ b/src/backoffice/templates/backoffice/assembly_events.html
@@ -13,7 +13,7 @@
 
 {% block scripts %}
   <script src="{% static 'vendor/datatables/datatables.min.js' %}"></script>
-  <script>
+  <script nonce="{{ request.csp_nonce }}">
       $(document).ready(function() {
           $('#events').DataTable({
             pageLength: 100,
diff --git a/src/backoffice/templates/backoffice/assembly_list.html b/src/backoffice/templates/backoffice/assembly_list.html
index 7943e7a39..6afad8c85 100644
--- a/src/backoffice/templates/backoffice/assembly_list.html
+++ b/src/backoffice/templates/backoffice/assembly_list.html
@@ -10,7 +10,7 @@
 
 {% block scripts %}
   <script src="{% static 'vendor/datatables/datatables.min.js' %}"></script>
-  <script>
+  <script nonce="{{ request.csp_nonce }}">
       $(document).ready(function() {
           $('#assemblies').DataTable({
             pageLength: 100,
diff --git a/src/backoffice/templates/backoffice/assembly_room_wa_linterblock.html b/src/backoffice/templates/backoffice/assembly_room_wa_linterblock.html
index 3bae576a7..4fdf75579 100644
--- a/src/backoffice/templates/backoffice/assembly_room_wa_linterblock.html
+++ b/src/backoffice/templates/backoffice/assembly_room_wa_linterblock.html
@@ -43,7 +43,7 @@
   <script src="{% static 'vendor/d3/d3.js' %}"></script>
   <script src="{% static 'vendor/d3/d3-graphviz.js' %}"></script>
   <div id="exitgraph"></div>
-  <script>
+  <script nonce="{{ request.csp_nonce }}">
  d3.select("#exitgraph")
    .graphviz()
    .dot("{{ wa_linter.exitGraph | escapejs }}")
diff --git a/src/backoffice/templates/backoffice/conferences/publication_edit.html b/src/backoffice/templates/backoffice/conferences/publication_edit.html
index 6675e1e67..358766000 100644
--- a/src/backoffice/templates/backoffice/conferences/publication_edit.html
+++ b/src/backoffice/templates/backoffice/conferences/publication_edit.html
@@ -11,7 +11,7 @@
 {% endblock title %}
 {% block scripts %}
   <script src="{% static "backoffice/modal.js" %}"></script>
-  <script>
+  <script nonce="{{ request.csp_nonce }}">
   $(document).ready(() => {
     showModal = registerModal()
     publishConference = document.getElementById('publishConference');
diff --git a/src/backoffice/templates/backoffice/conferences/registration_edit.html b/src/backoffice/templates/backoffice/conferences/registration_edit.html
index 0fd704f43..9b3c5aa49 100644
--- a/src/backoffice/templates/backoffice/conferences/registration_edit.html
+++ b/src/backoffice/templates/backoffice/conferences/registration_edit.html
@@ -11,7 +11,7 @@
 {% endblock title %}
 {% block scripts %}
   <script src="{% static "backoffice/modal.js" %}"></script>
-  <script>
+  <script nonce="{{ request.csp_nonce }}">
   $(document).ready(() => {
     showModal = registerModal()
     publishConference = document.getElementById('publishConference');
diff --git a/src/backoffice/templates/backoffice/event/list.html b/src/backoffice/templates/backoffice/event/list.html
index 4ce972dd2..14df4bad6 100644
--- a/src/backoffice/templates/backoffice/event/list.html
+++ b/src/backoffice/templates/backoffice/event/list.html
@@ -10,7 +10,7 @@
 
 {% block scripts %}
   <script src="{% static 'vendor/datatables/datatables.min.js' %}"></script>
-  <script>{% include "backoffice/event/components/list_script.js" %}</script>
+  <script nonce="{{ request.csp_nonce }}">{% include "backoffice/event/components/list_script.js" %}</script>
 {% endblock scripts %}
 
 {% block content %}
diff --git a/src/backoffice/templates/backoffice/map_floor_list.html b/src/backoffice/templates/backoffice/map_floor_list.html
index 3fb085ee9..53f15955a 100644
--- a/src/backoffice/templates/backoffice/map_floor_list.html
+++ b/src/backoffice/templates/backoffice/map_floor_list.html
@@ -10,7 +10,7 @@
 
 {% block scripts %}
   <script src="{% static 'vendor/datatables/datatables.min.js' %}"></script>
-  <script>
+  <script nonce="{{ request.csp_nonce }}">
       $(document).ready(function() {
           $('#pois').DataTable({
             pageLength: 100,
diff --git a/src/backoffice/templates/backoffice/map_poi_list.html b/src/backoffice/templates/backoffice/map_poi_list.html
index fe3088da3..f8560e6f1 100644
--- a/src/backoffice/templates/backoffice/map_poi_list.html
+++ b/src/backoffice/templates/backoffice/map_poi_list.html
@@ -10,7 +10,7 @@
 
 {% block scripts %}
   <script src="{% static 'vendor/datatables/datatables.min.js' %}"></script>
-  <script>
+  <script nonce="{{ request.csp_nonce }}">
       $(document).ready(function() {
           $('#pois').DataTable({
             pageLength: 100,
diff --git a/src/backoffice/templates/backoffice/moderation_assembly-list.html b/src/backoffice/templates/backoffice/moderation_assembly-list.html
index 20bc65dbb..909e2c49c 100644
--- a/src/backoffice/templates/backoffice/moderation_assembly-list.html
+++ b/src/backoffice/templates/backoffice/moderation_assembly-list.html
@@ -10,7 +10,7 @@
 
 {% block scripts %}
   <script src="{% static 'vendor/datatables/datatables.min.js' %}"></script>
-  <script>
+  <script nonce="{{ request.csp_nonce }}">
       $(document).ready(function() {
           $('#assemblies').DataTable({
             pageLength: 100,
diff --git a/src/backoffice/templates/backoffice/moderation_badge-list.html b/src/backoffice/templates/backoffice/moderation_badge-list.html
index 170d5823f..7ee761343 100644
--- a/src/backoffice/templates/backoffice/moderation_badge-list.html
+++ b/src/backoffice/templates/backoffice/moderation_badge-list.html
@@ -10,7 +10,7 @@
 
 {% block scripts %}
   <script src="{% static 'vendor/datatables/datatables.min.js' %}"></script>
-  <script>
+  <script nonce="{{ request.csp_nonce }}">
       $(document).ready(function() {
           $('#badges').DataTable({
             pageLength: 100,
diff --git a/src/backoffice/templates/backoffice/moderation_base.html b/src/backoffice/templates/backoffice/moderation_base.html
index ac969027d..549b8a105 100644
--- a/src/backoffice/templates/backoffice/moderation_base.html
+++ b/src/backoffice/templates/backoffice/moderation_base.html
@@ -4,7 +4,7 @@
 
 {% block scripts %}
   <script src="{% static "backoffice/modal.js" %}"></script>
-  <script>
+  <script nonce="{{ request.csp_nonce }}">
   $(document).ready(() => {
     showModal = registerModal()
 
diff --git a/src/backoffice/templates/backoffice/moderation_board-list.html b/src/backoffice/templates/backoffice/moderation_board-list.html
index 986750ecf..f8ea68958 100644
--- a/src/backoffice/templates/backoffice/moderation_board-list.html
+++ b/src/backoffice/templates/backoffice/moderation_board-list.html
@@ -10,7 +10,7 @@
 
 {% block scripts %}
   <script src="{% static 'vendor/datatables/datatables.min.js' %}"></script>
-  <script>
+  <script nonce="{{ request.csp_nonce }}">
       $(document).ready(function() {
           $('#entries').DataTable({
             pageLength: 100,
diff --git a/src/backoffice/templates/backoffice/moderation_user-list.html b/src/backoffice/templates/backoffice/moderation_user-list.html
index 8d82c41fe..2f9359646 100644
--- a/src/backoffice/templates/backoffice/moderation_user-list.html
+++ b/src/backoffice/templates/backoffice/moderation_user-list.html
@@ -10,7 +10,7 @@
 
 {% block scripts %}
   <script src="{% static 'vendor/datatables/datatables.min.js' %}"></script>
-  <script>
+  <script nonce="{{ request.csp_nonce }}">
       $(document).ready(function() {
           $('#users').DataTable({
             pageLength: 100,
diff --git a/src/backoffice/templates/backoffice/moderation_wiki-list.html b/src/backoffice/templates/backoffice/moderation_wiki-list.html
index d30fe275b..30252e582 100644
--- a/src/backoffice/templates/backoffice/moderation_wiki-list.html
+++ b/src/backoffice/templates/backoffice/moderation_wiki-list.html
@@ -10,7 +10,7 @@
 
 {% block scripts %}
   <script src="{% static 'vendor/datatables/datatables.min.js' %}"></script>
-  <script>
+  <script nonce="{{ request.csp_nonce }}">
       $(document).ready(function() {
           $('#pages').DataTable({
             pageLength: 100,
diff --git a/src/backoffice/templates/backoffice/project/create_edit.html b/src/backoffice/templates/backoffice/project/create_edit.html
index aa15146a2..f88aa7700 100644
--- a/src/backoffice/templates/backoffice/project/create_edit.html
+++ b/src/backoffice/templates/backoffice/project/create_edit.html
@@ -13,7 +13,7 @@
 {% block scripts %}
   <script src="{% static "backoffice/form-add.js" %}"></script>
   <script src="{% static "backoffice/modal.js" %}"></script>
-  <script>
+  <script nonce="{{ request.csp_nonce }}">
   $(document).ready(() => {
     showModal = registerModal()
     publishProject = document.getElementById('publishProject');
diff --git a/src/backoffice/templates/backoffice/project/list.html b/src/backoffice/templates/backoffice/project/list.html
index 72ecd1ad1..868c9b2f7 100644
--- a/src/backoffice/templates/backoffice/project/list.html
+++ b/src/backoffice/templates/backoffice/project/list.html
@@ -16,7 +16,7 @@
 
 {% block scripts %}
   <script src="{% static 'vendor/datatables/datatables.min.js' %}"></script>
-  <script>{% include "backoffice/project/components/list_script.js" %}</script>
+  <script nonce="{{ request.csp_nonce }}">{% include "backoffice/project/components/list_script.js" %}</script>
 {% endblock scripts %}
 
 {% block content %}
diff --git a/src/backoffice/templates/backoffice/sos.html b/src/backoffice/templates/backoffice/sos.html
index ca441a001..1dcb9f2c3 100644
--- a/src/backoffice/templates/backoffice/sos.html
+++ b/src/backoffice/templates/backoffice/sos.html
@@ -13,8 +13,8 @@
 
 {% block scripts %}
   <script src="{% static 'vendor/datatables/datatables.min.js' %}"></script>
-  <script>{% include "backoffice/event/components/list_script.js" %}</script>
-  <script>{% include "backoffice/project/components/list_script.js" %}</script>
+  <script nonce="{{ request.csp_nonce }}">{% include "backoffice/event/components/list_script.js" %}</script>
+  <script nonce="{{ request.csp_nonce }}">{% include "backoffice/project/components/list_script.js" %}</script>
 {% endblock scripts %}
 
 {% block content %}
diff --git a/src/backoffice/templates/backoffice/sos_create_edit.html b/src/backoffice/templates/backoffice/sos_create_edit.html
index 266929458..33d7a9d3c 100644
--- a/src/backoffice/templates/backoffice/sos_create_edit.html
+++ b/src/backoffice/templates/backoffice/sos_create_edit.html
@@ -12,7 +12,7 @@
 {% endblock title %}
 {% block scripts %}
   <script src="{% static "backoffice/modal.js" %}"></script>
-  <script>
+  <script nonce="{{ request.csp_nonce }}">
   $(document).ready(() => {
     showModal = registerModal()
     publishEvent = document.getElementById('publishEvent');
diff --git a/src/backoffice/templates/backoffice/wa-map-detail.html b/src/backoffice/templates/backoffice/wa-map-detail.html
index add7aac05..741acf214 100644
--- a/src/backoffice/templates/backoffice/wa-map-detail.html
+++ b/src/backoffice/templates/backoffice/wa-map-detail.html
@@ -3,7 +3,7 @@
 {% load i18n %}
 
 {% block scripts %}
-  <script>
+  <script nonce="{{ request.csp_nonce }}">
 $(function() {
   function changeEdit(id) {
     $(id).attr('disabled', function(i, v) { return !v; });
diff --git a/src/backoffice/templates/backoffice/wa-map-list.html b/src/backoffice/templates/backoffice/wa-map-list.html
index 2d7a0f159..95e2c94ee 100644
--- a/src/backoffice/templates/backoffice/wa-map-list.html
+++ b/src/backoffice/templates/backoffice/wa-map-list.html
@@ -9,7 +9,7 @@
 
 {% block scripts %}
   <script src="{% static 'vendor/datatables/datatables.min.js' %}"></script>
-  <script>
+  <script nonce="{{ request.csp_nonce }}">
       $(document).ready(function() {
           $('#wa-maps').DataTable({
             pageLength: 100,
diff --git a/src/backoffice/templates/backoffice/wiki_lock_list.html b/src/backoffice/templates/backoffice/wiki_lock_list.html
index 2d0213a6c..0b04fd024 100644
--- a/src/backoffice/templates/backoffice/wiki_lock_list.html
+++ b/src/backoffice/templates/backoffice/wiki_lock_list.html
@@ -5,7 +5,7 @@
 
 {% block scripts %}
   <script src="{% static "backoffice/modal.js" %}"></script>
-  <script>
+  <script nonce="{{ request.csp_nonce }}">
   $(document).ready(() => {
     showModal = registerModal()
 
diff --git a/src/core/templates/core/map.html b/src/core/templates/core/map.html
index 5f038ccef..8b976f4f8 100644
--- a/src/core/templates/core/map.html
+++ b/src/core/templates/core/map.html
@@ -7,7 +7,7 @@
     <div id="{{ mapid }}" style="width: 100%; min-height: 35em;"></div>
   </div>
   {% with mapstyleid=mapid|add:"_style" %}{{ map_config.style|json_script:mapstyleid }}{% endwith %}
-  <script>
+  <script nonce="{{ request.csp_nonce }}">
     window.addEventListener("load", function () {
       const initial_floor_idx = {% if floor_id %}document.getElementById('{{ floor_id }}').value{% else %}null{% endif %};
 
diff --git a/src/core/templates/oauth2_provider/out-of-band-display-token.html b/src/core/templates/oauth2_provider/out-of-band-display-token.html
index 69075acc8..c728f6a8f 100644
--- a/src/core/templates/oauth2_provider/out-of-band-display-token.html
+++ b/src/core/templates/oauth2_provider/out-of-band-display-token.html
@@ -27,7 +27,7 @@
             #token { font-family: monospace; }
             .hidden { display: none; }
     </style>
-    <script>
+    <script nonce="{{ request.csp_nonce }}">
             document.addEventListener("DOMContentLoaded", function(){
                 document.querySelector('#token').innerHTML = new URLSearchParams(window.location.hash.slice(1)).get("access_token");
 
diff --git a/src/plainui/jinja2/plainui/base.html.j2 b/src/plainui/jinja2/plainui/base.html.j2
index 28224f4ef..56ffe2bec 100644
--- a/src/plainui/jinja2/plainui/base.html.j2
+++ b/src/plainui/jinja2/plainui/base.html.j2
@@ -25,7 +25,7 @@
     <script src="{{ static('vendor/map/leaflet.js') }}"></script>
     <link href="{{ static('vendor/map/leaflet.draw.css') }}" rel='stylesheet' />
     <script src="{{ static('vendor/map/leaflet.draw.js') }}"></script>
-    <script>
+    <script nonce="{{request.csp_nonce}}">
             document.addEventListener('DOMContentLoaded', (e) => {
                 document.querySelector('html').classList.remove('no-js');
                 document.querySelector('html').classList.add('js');
@@ -119,7 +119,7 @@
   </body>
   <script async
           src="{{ static('plainui/vendor/bootstrap5/bootstrap.bundle.min.js') }}" /></script>
-  <script>
+  <script nonce="{{request.csp_nonce}}">
         setTimeout(() => {
             var options = {
                 html: true,
diff --git a/src/plainui/jinja2/plainui/components/integrations.html.j2 b/src/plainui/jinja2/plainui/components/integrations.html.j2
index fadb32755..4d00e5b7f 100644
--- a/src/plainui/jinja2/plainui/components/integrations.html.j2
+++ b/src/plainui/jinja2/plainui/components/integrations.html.j2
@@ -1,7 +1,7 @@
 {% macro vocPlayer(playerId='player', vocStream=None, vocLecture=None) -%}
   <div id="{{ playerId }}" class="hub_voc_player"></div>
 
-  <script>
+  <script nonce="{{ request.csp_nonce }}">
         new VOCPlayer.Player({
             {% if vocStream -%}
             vocStream: "{{ vocStream }}",
diff --git a/src/plainui/jinja2/plainui/components/map.html.j2 b/src/plainui/jinja2/plainui/components/map.html.j2
index 8c1f7d8bb..ee3960cd4 100644
--- a/src/plainui/jinja2/plainui/components/map.html.j2
+++ b/src/plainui/jinja2/plainui/components/map.html.j2
@@ -3,7 +3,7 @@
   {% set map_start_pos = map_config["start"] %}
 
   <div id="{{ map_container_id }}" style="width: 100%; min-height: 20em;"></div>
-  <script>
+  <script nonce="{{ request.csp_nonce }}">
     const style = {{ map_config.style|tojson|safe }};
 
     const map = new maplibregl.Map({
diff --git a/src/plainui/jinja2/plainui/public_fahrplan.html.j2 b/src/plainui/jinja2/plainui/public_fahrplan.html.j2
index 269151d90..81e484660 100644
--- a/src/plainui/jinja2/plainui/public_fahrplan.html.j2
+++ b/src/plainui/jinja2/plainui/public_fahrplan.html.j2
@@ -16,7 +16,7 @@
     <meta name="viewport" content="width=device-width, initial-scale=1">
     {% block head %}
     {% endblock head %}
-    <script>
+    <script nonce="{{ request.csp_nonce }}">
             document.addEventListener('DOMContentLoaded', (e) => {
                 document.querySelector('html').classList.remove('no-js');
                 document.querySelector('html').classList.add('js');
diff --git a/src/plainui/jinja2/plainui/static_page_edit.html.j2 b/src/plainui/jinja2/plainui/static_page_edit.html.j2
index 740c85f12..4a092a612 100644
--- a/src/plainui/jinja2/plainui/static_page_edit.html.j2
+++ b/src/plainui/jinja2/plainui/static_page_edit.html.j2
@@ -36,14 +36,15 @@
     {% endif %}
     {% if preview_body is defined %}
       <article class="pb-11 my-4 hub-card">
-        <h2 class="hub-section-title">{{ _('Preview') }}</h2>
+        <h2 class="hub-section-title">{{ _("Preview") }}</h2>
 
         {{ markdownMacro.markdown(markdown=preview_body | safe, customClass="p-2 rounded") }}
       </article>
     {% endif %}
-    <form method="post" class="hub-card"
+    <form method="post"
+          class="hub-card"
           action="{{ url('plainui:static_page_edit', page_slug=page_slug) }}{{ '?rev=' + revision if revision else '' }}">
-      <h2 class="hub-section-title">{{ _('Wiki__edit') }}</h2>
+      <h2 class="hub-section-title">{{ _("Wiki__edit") }}</h2>
 
       {%- if not_latest_revision %}
         {% call alert.warning() %}
@@ -63,7 +64,10 @@
               {{ _("Save") }}
               {% if page.is_localized %}({{ get_language() }}){% endif %}
             </button>
-            <button type="submit" name="preview" value="true" class="btn btn-secondary mx-1">{{ _("Preview") }}</button>
+            <button type="submit"
+                    name="preview"
+                    value="true"
+                    class="btn btn-secondary mx-1">{{ _("Preview") }}</button>
           {%- endif %}
         </div>
         <div class="col d-flex justify-content-end">
@@ -77,7 +81,7 @@
 
 {% block jstools %}
   {% if page_slug and lock_id %}
-    <script>
+    <script nonce="{{ request.csp_nonce }}">
   const data = new URLSearchParams();
   data.append('page_slug', {{ page_slug | tojson }});
   data.append('lock_id', {{ lock_id | tojson }});
-- 
GitLab