pulp / pulp/pulpcore

ArtifactFileField.pre_save spuriously rejects uploads named 'artifact*' when MEDIA_ROOT is empty

Open
#8,041 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
598
Forks
168
Avg merge
1d 4h
Merged PRs (30d)
86

Description

Summary

ArtifactFileField.pre_save uses a fragile prefix check to decide whether an incoming file is already inside artifact storage:

https://github.com/pulp/pulpcore/blob/main/pulpcore/app/models/fields.py#L69-L73

is_in_artifact_storage = file.name.startswith(os.path.join(settings.MEDIA_ROOT, "artifact"))

When settings.MEDIA_ROOT is "" — which is the case for object-storage backends (azure, s3, etc.) — this collapses to:

file.name.startswith("artifact")

file.name for a fresh upload is the client-provided filename. Any uploaded file whose name begins with the substring artifact (e.g. artifact-foo-1.0-1.noarch.rpm) therefore matches, already_in_place is False, and pre_save raises:

ValueError: The file referenced by the Artifact is already present in Artifact storage.
Files must be stored outside this location prior to Artifact creation.

which surfaces to the client as a 500 Internal Server Error on POST /pulp/<domain>/api/v3/artifacts/.

Impact

Any user uploading an artifact whose filename starts with artifact to a deployment with an empty MEDIA_ROOT (object storage) gets a spurious 500. The bug is filename-dependent and backend-dependent, so it is easy to miss.

How it was discovered

A pulp_rpm functional test (test_domains.py::test_artifact_from_file) built an RPM named artifact-<hex>-1.0-1.noarch.rpm and uploaded it via the artifacts endpoint. It failed only on the azure job (empty MEDIA_ROOT); the sibling test using a content- prefix passed.

Suggested fix

The prefix check is meant to detect files that are already physically in artifact storage. It should not rely on a bare startswith against a possibly-empty settings.MEDIA_ROOT, and it arguably should consider the current domain's actual storage location rather than the global setting. Options:

  • Normalize/join paths and compare path components instead of doing a raw string prefix match.
  • Guard against an empty MEDIA_ROOT so the check does not degenerate to startswith("artifact").

Environment

  • Reproducible with any object-storage backend where MEDIA_ROOT is empty (azure/s3), including per-domain FileSystem storage where the global settings.MEDIA_ROOT is still empty.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in pulpcore/app/models/fields.py at the ArtifactFileField.pre_save prefix check, then review pulp_rpm's test_domains.py::test_artifact_from_file and its artifact-prefixed filename. Reproduce the failure with an empty MEDIA_ROOT and verify that the test succeeds for object-storage configurations without rejecting a fresh upload.

Written by the indexing model from the issue text.

Assessment

Tech stack
azure, python
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
70/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.