CVE-2024-30248: Insufficient Information (NVD-CWE-noinfo)
value: Piccolo Admin is an admin interface/content management system for Python, built on top of Piccolo. Piccolo's admin panel allows media files to be uploaded. As a default, SVG is an allowed file type for upload. An attacker can upload an SVG which when loaded can allow arbitrary access to the admin page. This vulnerability was patched in version 1.3.2.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2024-04-02T15:15Z
Repository: https://github.com/piccolo-orm/piccolo_admin
Language: Python
Files changed: piccolo_admin/endpoints.py, requirements/requirements.txt
Commit date: 2024-03-30 13:18:29 +0000
Commit message: Merge pull request from GHSA-pmww-v6c9-7p83

* feat: add csp headers on media routes

* feat: use CSPMiddleware instead

* chore: bump piccolo API version

---------

Co-authored-by: skelmis <ethanmkh2@gmail.com>
Diff: diff --git a/piccolo_admin/endpoints.py b/piccolo_admin/endpoints.py
index 0bf8b19..58c7a17 100644
--- a/piccolo_admin/endpoints.py
+++ b/piccolo_admin/endpoints.py
@@ -28,10 +28,11 @@ from piccolo.table import Table
 from piccolo.utils.warnings import Level, colored_warning
 from piccolo_api.change_password.endpoints import change_password
 from piccolo_api.crud.endpoints import OrderBy, PiccoloCRUD
 from piccolo_api.crud.hooks import Hook
 from piccolo_api.crud.validators import Validators
+from piccolo_api.csp.middleware import CSPMiddleware, CSPConfig
 from piccolo_api.csrf.middleware import CSRFMiddleware
 from piccolo_api.fastapi.endpoints import FastAPIKwargs, FastAPIWrapper
 from piccolo_api.media.base import MediaStorage
 from piccolo_api.media.local import LocalMediaStorage
 from piccolo_api.openapi.endpoints import swagger_ui
@@ -665,15 +666,21 @@ class AdminRouter(FastAPI):
                 for (
                     column,
                     media_storage,
                 ) in table_config.media_columns.items():
                     if isinstance(media_storage, LocalMediaStorage):
+                        # We apply a restrictive CSP here to mitigate SVG
+                        # files being used maliciously when viewed by admins
                         private_app.mount(
-                            path=f"/media-files/{column._meta.table._meta.tablename}/{column._meta.name}/",  # noqa: E501
-                            app=StaticFiles(
-                                directory=media_storage.media_path
-                            ),
+                            path=f"/media-files/{column._meta.table._meta.tablename}/{column._meta.name}/",
+                            # noqa: E501
+                            app=CSPMiddleware(
+                                StaticFiles(
+                                    directory=media_storage.media_path
+                                ),
+                                config=CSPConfig(default_src="none")
+                            )
                         )
 
         #######################################################################
 
         public_app = FastAPI(
diff --git a/requirements/requirements.txt b/requirements/requirements.txt
index 6eb3f23..7ee2e23 100644
--- a/requirements/requirements.txt
+++ b/requirements/requirements.txt
@@ -1,7 +1,7 @@
 piccolo>=1.5.0
-piccolo_api>=1.1.0
+piccolo_api>=1.3.1
 uvicorn
 aiofiles>=0.5.0
 Hypercorn
 targ>=0.1.9
 fastapi>=0.100.0

Vulnerable code:                             path=f"/media-files/{column._meta.table._meta.tablename}/{column._meta.name}/",  # noqa: E501
                            app=StaticFiles(
                                directory=media_storage.media_path
                            ),
piccolo_api>=1.1.0
Fixed code: from piccolo_api.csp.middleware import CSPMiddleware, CSPConfig
                        # We apply a restrictive CSP here to mitigate SVG
                        # files being used maliciously when viewed by admins
                            path=f"/media-files/{column._meta.table._meta.tablename}/{column._meta.name}/",
                            # noqa: E501
                            app=CSPMiddleware(
                                StaticFiles(
                                    directory=media_storage.media_path
                                ),
                                config=CSPConfig(default_src="none")
                            )
piccolo_api>=1.3.1