From f319209061681f074e1de31dea3dfe4457a16535 Mon Sep 17 00:00:00 2001 From: Vladimir Saraikin Date: Mon, 13 Jul 2026 19:47:46 +0200 Subject: [PATCH] fix: escape regex metacharacters in WildcardMatch A task whose name contains a regex metacharacter breaks task matching for the whole Taskfile. WildcardMatch built a pattern from the raw task name, so a task named "c++" panicked in MustCompile and a task named "a.b" matched "axb". Escape the name with QuoteMeta before turning "*" back into the wildcard group, and skip the regex entirely when the name has no wildcard. --- task_test.go | 20 ++++++++++++++++++++ taskfile/ast/task.go | 5 ++++- testdata/wildcards/Taskfile.yml | 9 +++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/task_test.go b/task_test.go index 540e7ba8de..2f180235c5 100644 --- a/task_test.go +++ b/task_test.go @@ -3417,6 +3417,26 @@ func TestWildcard(t *testing.T) { call: "wildcard-foo-bar", expectedOutput: "Hello foo-bar\n", }, + { + name: "regex metacharacters are matched literally", + call: "c++", + expectedOutput: "Building c++\n", + }, + { + name: "regex metacharacters do not match as a pattern", + call: "cxx", + wantErr: true, + }, + { + name: "a dot matches itself", + call: "deploy.prod", + expectedOutput: "Deploying prod\n", + }, + { + name: "a dot is not a wildcard", + call: "deploy-prod", + wantErr: true, + }, } for _, test := range tests { diff --git a/taskfile/ast/task.go b/taskfile/ast/task.go index 9465c77770..75b2815154 100644 --- a/taskfile/ast/task.go +++ b/taskfile/ast/task.go @@ -87,7 +87,10 @@ func (t *Task) WildcardMatch(name string) (bool, []string) { names := append([]string{t.Task}, t.Aliases...) for _, taskName := range names { - regexStr := fmt.Sprintf("^%s$", strings.ReplaceAll(taskName, "*", "(.*)")) + // Escape the task name so a name like "c++" or "a.b" is matched literally + // and does not panic in MustCompile, then turn the escaped "*" back into + // the wildcard group + regexStr := fmt.Sprintf("^%s$", strings.ReplaceAll(regexp.QuoteMeta(taskName), `\*`, "(.*)")) regex := regexp.MustCompile(regexStr) wildcards := regex.FindStringSubmatch(name) diff --git a/testdata/wildcards/Taskfile.yml b/testdata/wildcards/Taskfile.yml index 0ec2ae2895..e152876c01 100644 --- a/testdata/wildcards/Taskfile.yml +++ b/testdata/wildcards/Taskfile.yml @@ -25,3 +25,12 @@ tasks: SERVICE: "{{index .MATCH 0}}" cmds: - echo "Starting {{.SERVICE}}" + + # Regex metacharacters in a task name must be matched literally + c++: + cmds: + - echo "Building c++" + + deploy.prod: + cmds: + - echo "Deploying prod"