diff --git a/CHANGES/9392.bugfix b/CHANGES/9392.bugfix new file mode 100644 index 000000000..10096ce06 --- /dev/null +++ b/CHANGES/9392.bugfix @@ -0,0 +1,2 @@ +For certain repos which use a rare feature of RPM metadata, "mirroring" would lead to a broken repo. We now reject syncing these repos with mirroring enabled. +(backported from #9328) diff --git a/pulp_rpm/app/tasks/synchronizing.py b/pulp_rpm/app/tasks/synchronizing.py index f91d9e3af..956d23e9a 100644 --- a/pulp_rpm/app/tasks/synchronizing.py +++ b/pulp_rpm/app/tasks/synchronizing.py @@ -104,9 +104,9 @@ pkgid_to_location_href = collections.defaultdict(dict) -XML_BASE_AND_MIRROR_INCOMPATIBLE_ERR_MSG = ( - "Repositories which provide an 'xml:base' parameter (location_base) in their " - "metadata are incompatible with 'mirror mode'." +MIRROR_INCOMPATIBLE_REPO_ERR_MSG = ( + "This repository uses features which are incompatible with 'mirror' sync. " + "Please sync without mirroring enabled." ) @@ -643,8 +643,8 @@ async def run_repomdrecord_download(name, location_href, downloader): checksum_types[record.type] = record_checksum_type record.checksum_type = record_checksum_type - if self.mirror and record.location_base: - raise ValueError(XML_BASE_AND_MIRROR_INCOMPATIBLE_ERR_MSG) + if self.mirror and record.location_base or ".." in record.location_href: + raise ValueError(MIRROR_INCOMPATIBLE_REPO_ERR_MSG) if not self.mirror and record.type not in types_to_download: continue @@ -1032,8 +1032,8 @@ async def on_package(pkg): Args: pkg (createrepo_c.Package): A completed createrepo_c package. """ - if self.mirror and pkg.location_base: - raise ValueError(XML_BASE_AND_MIRROR_INCOMPATIBLE_ERR_MSG) + if self.mirror and pkg.location_base or ".." in pkg.location_href: + raise ValueError(MIRROR_INCOMPATIBLE_REPO_ERR_MSG) package = Package(**Package.createrepo_to_dict(pkg)) base_url = pkg.location_base or self.remote_url diff --git a/pulp_rpm/tests/functional/api/test_sync.py b/pulp_rpm/tests/functional/api/test_sync.py index 465ad82ed..7c8b30b92 100644 --- a/pulp_rpm/tests/functional/api/test_sync.py +++ b/pulp_rpm/tests/functional/api/test_sync.py @@ -33,6 +33,7 @@ PULP_TYPE_PACKAGE, PULP_TYPE_REPOMETADATA, REPO_WITH_XML_BASE_URL, + REPO_WITH_EXTERNAL_LOCATION_HREF_URL, RPM_ADVISORY_CONTENT_NAME, RPM_ADVISORY_COUNT, RPM_ADVISORY_DIFFERENT_PKGLIST_URL, @@ -1247,11 +1248,25 @@ def test_sync_packages_with_unsupported_checksum_type(self): ) def test_mirror_with_xml_base_fails(self): - """Test that if a repository that uses xml:base is synced in mirror-mode, it fails.""" + """Test that syncing a repository that uses xml:base in mirror mode fails.""" error = self.do_test(REPO_WITH_XML_BASE_URL, mirror=True) self.assertIn( - "xml:base", + "features which are incompatible with 'mirror' sync", + error, + ) + + def test_mirror_with_external_location_href_fails(self): + """ + Test that syncing a repository that uses contains an external location_href fails. + + External location_href refers to a location_href that points outside of the repo, + e.g. ../../Packages/blah.rpm + """ + error = self.do_test(REPO_WITH_EXTERNAL_LOCATION_HREF_URL, mirror=True) + + self.assertIn( + "features which are incompatible with 'mirror' sync", error, ) diff --git a/pulp_rpm/tests/functional/constants.py b/pulp_rpm/tests/functional/constants.py index f7434520f..f69b4fec1 100644 --- a/pulp_rpm/tests/functional/constants.py +++ b/pulp_rpm/tests/functional/constants.py @@ -616,7 +616,9 @@ EPEL8_MIRRORLIST_URL = "https://mirrors.fedoraproject.org/mirrorlist?repo=epel-8&arch=x86_64" EPEL8_PLAYGROUND_KICKSTART_URL = "http://mirrors.sonic.net/epel/playground/8/Everything/x86_64/os/" REPO_WITH_XML_BASE_URL = "https://harbottle.gitlab.io/harbottle-main/8/x86_64/" - +REPO_WITH_EXTERNAL_LOCATION_HREF_URL = ( + "https://packages.rundeck.com/pagerduty/rundeck/rpm_any/rpm_any/x86_64/" +) PULP_TYPE_ADVISORY = "rpm.advisory" PULP_TYPE_DISTRIBUTION_TREE = "rpm.distribution_tree"