diff --git a/pdm.lock b/pdm.lock
index e40d73c468e64fb34e85aa0c6c2a75aca70ddd24..1ebc77d7e4bff3efb9fe7069ad59a0e5c6ed2553 100644
--- a/pdm.lock
+++ b/pdm.lock
@@ -2,10 +2,10 @@
 # It is not intended for manual editing.
 
 [metadata]
-groups = ["default", "dev", "lint", "local", "static-analysis", "typing", "watchfiles"]
+groups = ["default", "dev", "django-csp", "lint", "local", "static-analysis", "typing", "watchfiles"]
 strategy = ["inherit_metadata"]
 lock_version = "4.5.0"
-content_hash = "sha256:af6518bad6a153127d484181441f930ee00c15c1d0f704ea906e0fc5b4d15282"
+content_hash = "sha256:1e5c1e57c2e2a93e38b0b129351d7efb840b97cca3e7b69b9277b9766e03f521"
 
 [[metadata.targets]]
 requires_python = "==3.13.*"
@@ -472,6 +472,19 @@ files = [
     {file = "django_cors_headers-4.6.0.tar.gz", hash = "sha256:14d76b4b4c8d39375baeddd89e4f08899051eeaf177cb02a29bd6eae8cf63aa8"},
 ]
 
+[[package]]
+name = "django-csp"
+version = "3.8"
+summary = "Django Content Security Policy support."
+groups = ["default"]
+dependencies = [
+    "Django>=3.2",
+]
+files = [
+    {file = "django_csp-3.8-py3-none-any.whl", hash = "sha256:19b2978b03fcd73517d7d67acbc04fbbcaec0facc3e83baa502965892d1e0719"},
+    {file = "django_csp-3.8.tar.gz", hash = "sha256:ef0f1a9f7d8da68ae6e169c02e9ac661c0ecf04db70e0d1d85640512a68471c0"},
+]
+
 [[package]]
 name = "django-debug-toolbar"
 version = "4.4.6"
diff --git a/pyproject.toml b/pyproject.toml
index 9e4c869dfb62b52555721b72e47dabcd21e1f01c..48c77b34fe935b379b4349371f87cb985329fb47 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -44,6 +44,7 @@ dependencies = [
     "gunicorn>=23.0.0",
     "pydantic>=2.9.2",
     "django-rich>=1.13.0",
+    "django-csp>=3.8",
     "rules>=3.5",
 ]
 requires-python = "==3.13.*"
diff --git a/requirements.dev.txt b/requirements.dev.txt
index 7da485862cf49823ec2ef5f4c4e06a8dde9d9218..93aee3222cd3181cf681427344935cf3a125e245 100644
--- a/requirements.dev.txt
+++ b/requirements.dev.txt
@@ -31,6 +31,7 @@ distlib==0.3.9
 django==5.1.2
 django-bootstrap5==24.3
 django-cors-headers==4.6.0
+django-csp==3.8
 django-debug-toolbar==4.4.6
 django-environ==0.11.2
 django-modeltranslation==0.18.13
diff --git a/requirements.txt b/requirements.txt
index 1467aba9ded099d2bcff8dfce66cd482ac459f7b..f74cfcd121fb438008f1261a2006d3d645bbce29 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -20,6 +20,7 @@ distlib==0.3.9
 django==5.1.2
 django-bootstrap5==24.3
 django-cors-headers==4.6.0
+django-csp==3.8
 django-debug-toolbar==4.4.6
 django-environ==0.11.2
 django-modeltranslation==0.18.13
diff --git a/src/hub/settings/base.py b/src/hub/settings/base.py
index 1c4d6482e7febf1f186368b549712a29e4884c34..234f57d16e5d2cf402ba2e5f4b67d362acb3ed6f 100644
--- a/src/hub/settings/base.py
+++ b/src/hub/settings/base.py
@@ -123,6 +123,19 @@ env = environ.FileAwareEnv(
     API_USERS=(list, []),
     DISABLE_REQUEST_LOGGING=(bool, False),
     MOLLY_GUARD=(bool, True),
+    CSP_DEFAULT_SRC=(list, ["'self'"]),
+    CSP_SCRIPT_SRC=(list, ["'self'"]),
+    CSP_STYLE_SRC=(list, ["'self'", "'unsafe-inline'"]),
+    CSP_IMG_SRC=(list, ["'self'", 'data:']),
+    CSP_CONNECT_SRC=(list, ["'self'"]),
+    CSP_FONT_SRC=(list, ["'self'"]),
+    CSP_OBJECT_SRC=(list, ["'none'"]),
+    CSP_FRAME_SRC=(list, ["'none'"]),
+    CSP_MEDIA_SRC=(list, ["'self'"]),
+    CSP_FRAME_ANCESTORS=(list, ["'none'"]),
+    CSP_FORM_ACTION=(list, ["'self'"]),
+    CSP_BASE_URI=(list, ["'self'"]),
+    CSP_INCLUDE_NONCE_IN=(list, ['script-src']),
 )
 
 
@@ -195,6 +208,7 @@ INSTALLED_APPS = [
     'rest_framework',
     'rest_framework.authtoken',
     'django_rich',
+    'csp',
     'rules',
     # our apps
     'core',
@@ -211,6 +225,7 @@ MIDDLEWARE = [
     'django.middleware.csrf.CsrfViewMiddleware',
     'django.contrib.auth.middleware.AuthenticationMiddleware',
     'django.contrib.messages.middleware.MessageMiddleware',
+    'csp.middleware.CSPMiddleware',
     'core.middleware.TimezoneMiddleware',
     # TODO drĂ¼ber nachdenken ob wir die brauchen (ist default an in Django)
     # 'django.middleware.clickjacking.XFrameOptionsMiddleware',  # noqa: ERA001
@@ -229,6 +244,7 @@ TEMPLATES = [
                 'django.contrib.auth.context_processors.auth',
                 'django.contrib.messages.context_processors.messages',
                 'django.template.context_processors.i18n',
+                'csp.context_processors.nonce',
             ],
         },
     },
@@ -293,6 +309,21 @@ CSRF_COOKIE_NAME = env('CSRF_COOKIE_NAME', default=SESSION_COOKIE_NAME.replace('
 CSRF_COOKIE_PATH = SESSION_COOKIE_PATH
 CSRF_COOKIE_SECURE = SESSION_COOKIE_SECURE
 
+# Content Security Policy
+CSP_DEFAULT_SRC = env('CSP_DEFAULT_SRC')
+CSP_SCRIPT_SRC = env('CSP_SCRIPT_SRC')
+CSP_STYLE_SRC = env('CSP_STYLE_SRC')
+CSP_IMG_SRC = env('CSP_IMG_SRC')
+CSP_CONNECT_SRC = env('CSP_CONNECT_SRC')
+CSP_FONT_SRC = env('CSP_FONT_SRC')
+CSP_OBJECT_SRC = env('CSP_OBJECT_SRC')
+CSP_FRAME_SRC = env('CSP_FRAME_SRC')
+CSP_MEDIA_SRC = env('CSP_MEDIA_SRC')
+CSP_FRAME_ANCESTORS = env('CSP_FRAME_ANCESTORS')
+CSP_FORM_ACTION = env('CSP_FORM_ACTION')
+CSP_BASE_URI = env('CSP_BASE_URI')
+CSP_INCLUDE_NONCE_IN = env('CSP_INCLUDE_NONCE_IN')
+
 # OAuth2 configuration
 OAUTH2_PROVIDER_APPLICATION_MODEL = 'core.Application'
 OAUTH2_PROVIDER = {
diff --git a/src/hub/settings/default.py b/src/hub/settings/default.py
index f7c1ee2ba33cd603c778d9cf26a0ce3034a4f5ed..086f23d434f2fbd5ce55c3f4b7c17807b4619b62 100644
--- a/src/hub/settings/default.py
+++ b/src/hub/settings/default.py
@@ -138,6 +138,7 @@ if IS_FRONTEND:
                     'django.template.context_processors.request',
                     'django.contrib.auth.context_processors.auth',
                     'django.contrib.messages.context_processors.messages',
+                    'csp.context_processors.nonce',
                 ],
                 'environment': 'plainui.jinja2.environment',
             },