diff --git a/newsfragments/reject_non_list_security_opt.bugfix b/newsfragments/reject_non_list_security_opt.bugfix new file mode 100644 index 00000000..86263e48 --- /dev/null +++ b/newsfragments/reject_non_list_security_opt.bugfix @@ -0,0 +1,2 @@ +Reject a non-list ``security_opt`` in service definitions instead of silently +coercing a bare scalar into a one-element list. diff --git a/podman_compose.py b/podman_compose.py index fb8d31aa..8f578e62 100755 --- a/podman_compose.py +++ b/podman_compose.py @@ -2099,13 +2099,15 @@ def normalize_service(service: dict[str, Any], sub_dir: str = "") -> dict[str, A if "build" in service and "args" in service["build"]: if isinstance(build["args"], dict): build["args"] = norm_as_list(build["args"]) - for key in ("env_file", "security_opt", "volumes"): + for key in ("env_file", "volumes"): if key not in service: continue if isinstance(service[key], str): service[key] = [service[key]] if "security_opt" in service: sec_ls = service["security_opt"] + if not is_list(sec_ls): + raise PodmanComposeError("ERROR: security_opt must be a list") for ix, item in enumerate(sec_ls): if item in ("seccomp:unconfined", "apparmor:unconfined"): sec_ls[ix] = item.replace(":", "=") diff --git a/tests/unit/test_normalize_service.py b/tests/unit/test_normalize_service.py index 9907c84b..48aec98b 100644 --- a/tests/unit/test_normalize_service.py +++ b/tests/unit/test_normalize_service.py @@ -5,6 +5,7 @@ from parameterized import parameterized +from podman_compose import PodmanComposeError from podman_compose import normalize_service @@ -117,3 +118,17 @@ def test_command_like( expected_service = {} expected_service[key] = expected self.assertEqual(normalize_service(input_service), expected_service) + + @parameterized.expand([ + ("label=disable",), + ({"label": "disable"},), + ]) + def test_security_opt_must_be_a_list(self, value: Any) -> None: + with self.assertRaises(PodmanComposeError): + normalize_service({"security_opt": value}) + + def test_security_opt_list_is_normalized(self) -> None: + self.assertEqual( + normalize_service({"security_opt": ["seccomp:unconfined", "label=disable"]}), + {"security_opt": ["seccomp=unconfined", "label=disable"]}, + )