Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES/+cve-2026-84232.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Insures that `Content-Disposition`, `Content-Security-Policy`, and `X-Content-Type-Options`
are set consistently in the content-app. This addresses CVE-2026-84232.
11 changes: 11 additions & 0 deletions pulpcore/content/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,7 @@ async def _match_and_stream(self, path, request):
)
ca = ContentArtifact(relative_path=original_rel_path)
ra = RemoteArtifact(remote=remote, url=url, content_artifact=ca)
self._set_secure_headers(os.path.basename(ca.relative_path), headers)
try:
return await self._stream_remote_artifact(
request,
Expand Down Expand Up @@ -941,6 +942,12 @@ def _save_artifact(self, download_result, remote_artifact, request=None):
content_artifact.save()
return artifact

def _set_secure_headers(self, filename, headers):
content_disposition = f"attachment;filename={filename}"
headers["Content-Disposition"] = content_disposition
headers["Content-Security-Policy"] = "default-src 'none'; sandbox"
headers["X-Content-Type-Options"] = "nosniff"

async def _serve_content_artifact(self, content_artifact, headers, request):
"""
Handle response for a Content Artifact with the file present.
Expand Down Expand Up @@ -978,6 +985,7 @@ def _set_params_from_headers(hdrs, storage_domain):
domain = get_domain()
storage = domain.get_storage()

self._set_secure_headers(os.path.basename(content_artifact.relative_path), headers)
if domain.storage_class == "pulpcore.app.models.storage.FileSystem":
path = storage.path(artifact_name)
if not os.path.exists(path):
Expand Down Expand Up @@ -1049,6 +1057,9 @@ async def _stream_remote_artifact(self, request, response, remote_artifact, save
size = remote_artifact.size or "*"
raise HTTPRequestRangeNotSatisfiable(headers={"Content-Range": f"bytes */{size}"})

self._set_secure_headers(
os.path.basename(remote_artifact.content_artifact.relative_path), response.headers
)
actual_content_length = None

if range_start or range_stop:
Expand Down
Loading