From 1e06e1e375b182ea1f80d6cb9d4530774e592ffe Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Tue, 24 Mar 2026 00:46:30 +0100 Subject: [PATCH] Be stricter in index routes verifications Some verification was added in #722 but for slashes only. Taskcluster is actually way stricter than that with what it accepts as index keys and it doesn't prevent task creations when index routes are invalid (https://github.com/taskcluster/taskcluster/issues/6266). The regex comes from the service iteself at https://github.com/taskcluster/taskcluster/blob/62655d84d55680ffb8faa35e7deadee69f389efa/services/index/src/helpers.js#L8 Fixes #883 --- src/taskgraph/util/verify.py | 18 ++++++++++++------ test/test_util_verify.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/taskgraph/util/verify.py b/src/taskgraph/util/verify.py index 90402763f..30da0c55c 100644 --- a/src/taskgraph/util/verify.py +++ b/src/taskgraph/util/verify.py @@ -235,10 +235,14 @@ def verify_routes_notification_filters( ) +# https://docs.taskcluster.net/docs/reference/core/index#valid-characters +INDEX_NAMESPACE_RE = re.compile(r"^([a-zA-Z0-9_!~*'()%-]+\.)*[a-zA-Z0-9_!~*'()%-]+$") + + @verifications.add("full_task_graph") def verify_index_route(task, taskgraph, scratch_pad, graph_config, parameters): """ - This function ensures that routes do not contain forward slashes. + This function ensures that index routes would create valid taskcluster index paths """ if task is None: return @@ -247,11 +251,13 @@ def verify_index_route(task, taskgraph, scratch_pad, graph_config, parameters): route_prefix = "index." for route in routes: - # Check for invalid / in the index route - if route.startswith(route_prefix) and "/" in route: - raise Exception( - f"{task.label} has invalid route with forward slash: {route}" - ) + if route.startswith(route_prefix): + namespace = route[len(route_prefix) :] + if not INDEX_NAMESPACE_RE.match(namespace): + raise Exception( + f"{task.label} has invalid index route namespace: {route}. " + f"Namespace must match {INDEX_NAMESPACE_RE.pattern}" + ) @verifications.add("full_task_graph") diff --git a/test/test_util_verify.py b/test/test_util_verify.py index 542ba09b4..91eccf232 100644 --- a/test/test_util_verify.py +++ b/test/test_util_verify.py @@ -211,6 +211,17 @@ def make_task_treeherder(label, symbol, platform="linux/opt"): pytest.raises(DeprecationWarning), id="routes_notfication_filter: deprecated", ), + pytest.param( + "verify_index_route", + make_graph( + make_task( + "valid_route", + task_def={"routes": ["index.example.v2.latest.taskgraph.decision"]}, + ), + ), + does_not_raise(), + id="verify_index_route: valid route", + ), pytest.param( "verify_index_route", make_graph( @@ -226,6 +237,28 @@ def make_task_treeherder(label, symbol, platform="linux/opt"): pytest.raises(Exception), id="verify_index_route: invalid slash in route", ), + pytest.param( + "verify_index_route", + make_graph( + make_task( + "invalid_plus", + task_def={"routes": ["index.example.1.0+hotfix1.latest"]}, + ), + ), + pytest.raises(Exception), + id="verify_index_route: invalid plus in route", + ), + pytest.param( + "verify_index_route", + make_graph( + make_task( + "invalid_space", + task_def={"routes": ["index.example.some namespace.latest"]}, + ), + ), + pytest.raises(Exception), + id="verify_index_route: invalid space in route", + ), pytest.param( "verify_task_dependencies", make_graph(