Skip to content

Commit 1833470

Browse files
committed
Reject blank subprocess coordinator artifact roots
An empty string normalizes to the current directory, so it bypassed the empty-roots check and scanned the worker's working directory.
1 parent e8e1a8b commit 1833470

4 files changed

Lines changed: 22 additions & 10 deletions

File tree

‎task-sdk/src/airflow/sdk/coordinators/_bundle_metadata.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,13 @@ def convert_configured_roots(
113113
"""Normalize configured roots while rejecting explicitly empty values."""
114114
if isinstance(value, _UnsetArtifactRoots):
115115
return []
116-
roots = convert_roots(value)
117-
if not roots:
116+
values = [value] if isinstance(value, (str, os.PathLike)) else (value or [])
117+
if not values or any(not os.fspath(v).strip() for v in values):
118118
raise ValueError(
119-
"Artifact roots must contain at least one path when provided; "
119+
"Artifact roots must contain at least one path when provided, and each path must be non-empty; "
120120
"omit the option to use the task's Dag bundle."
121121
)
122-
return roots
122+
return convert_roots(value)
123123

124124

125125
def validate_schema_version(instance, _, value) -> str:

‎task-sdk/tests/task_sdk/coordinators/executable/test_coordinator.py‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -375,9 +375,13 @@ def test_executables_root_optional_defaults_to_empty(self):
375375
assert coordinator.executables_root == []
376376
assert coordinator.dag_bundle_name is None
377377

378-
@pytest.mark.parametrize("executables_root", [None, []], ids=["none", "empty-list"])
378+
@pytest.mark.parametrize(
379+
"executables_root",
380+
[None, [], "", " ", [""]],
381+
ids=["none", "empty-list", "empty-str", "blank-str", "list-of-empty-str"],
382+
)
379383
def test_explicit_empty_executables_root_raises(self, executables_root):
380-
with pytest.raises(ValueError, match="must contain at least one path when provided"):
384+
with pytest.raises(ValueError, match="and each path must be non-empty"):
381385
ExecutableCoordinator(executables_root=executables_root)
382386

383387
def test_root_and_dag_bundle_name_are_mutually_exclusive(self, tmp_path):

‎task-sdk/tests/task_sdk/coordinators/java/test_coordinator.py‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,9 +244,13 @@ def test_jars_root_optional_defaults_to_empty(self):
244244
assert coordinator.dag_bundle_name is None
245245
assert coordinator.main_class == ""
246246

247-
@pytest.mark.parametrize("jars_root", [None, []], ids=["none", "empty-list"])
247+
@pytest.mark.parametrize(
248+
"jars_root",
249+
[None, [], "", " ", [""]],
250+
ids=["none", "empty-list", "empty-str", "blank-str", "list-of-empty-str"],
251+
)
248252
def test_explicit_empty_jars_root_raises(self, jars_root):
249-
with pytest.raises(ValueError, match="must contain at least one path when provided"):
253+
with pytest.raises(ValueError, match="and each path must be non-empty"):
250254
JavaCoordinator(jars_root=jars_root)
251255

252256
def test_explicit_root_does_not_require_main_class(self, tmp_path):

‎task-sdk/tests/task_sdk/coordinators/node/test_coordinator.py‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,13 @@ def test_bundles_root_optional_defaults_to_empty(self):
8585
assert coordinator.bundles_root == []
8686
assert coordinator.dag_bundle_name is None
8787

88-
@pytest.mark.parametrize("bundles_root", [None, []], ids=["none", "empty-list"])
88+
@pytest.mark.parametrize(
89+
"bundles_root",
90+
[None, [], "", " ", [""]],
91+
ids=["none", "empty-list", "empty-str", "blank-str", "list-of-empty-str"],
92+
)
8993
def test_explicit_empty_bundles_root_raises(self, bundles_root):
90-
with pytest.raises(ValueError, match="must contain at least one path when provided"):
94+
with pytest.raises(ValueError, match="and each path must be non-empty"):
9195
NodeCoordinator(bundles_root=bundles_root)
9296

9397
def test_root_and_dag_bundle_name_are_mutually_exclusive(self):

0 commit comments

Comments
 (0)