From 57c149dd8d690d371395ba3a5a14509600aa13a7 Mon Sep 17 00:00:00 2001 From: Akshay Pant Date: Mon, 9 Mar 2026 19:39:58 +0530 Subject: [PATCH] fix(resolve): restore relative task path resolution for repository paths Commit 6e366209 broke relative task path resolution for repository file paths by only allowing HTTP(S) URLs. This caused paths containing '..' to be passed unresolved to the GitHub API, which rejects them with "path must not contain '..' due to auth vulnerability issue". This fix restores the original behavior by allowing both HTTP(S) URLs and repository file paths (e.g., .tekton/pipelines/build.yaml) to have their relative paths resolved, while still excluding catalog/hub references (catalog://, hub://). Fixes: #2549 Jira: https://redhat.atlassian.net/browse/SRVKP-11021 Signed-off-by: Akshay Pant --- pkg/resolve/remote.go | 7 +++++-- pkg/resolve/remote_test.go | 4 ++-- test/gitea_test.go | 7 ++++--- ...ope_token_to_list_of_private_public_repos_test.go | 7 ++++--- test/testdata/pipeline_in_tektondir.yaml | 4 ++++ .../pipelinerun_remote_task_annotations.yaml | 1 + test/testdata/task2_referenced_internally.yaml | 12 ++++++++++++ 7 files changed, 32 insertions(+), 10 deletions(-) create mode 100644 test/testdata/task2_referenced_internally.yaml diff --git a/pkg/resolve/remote.go b/pkg/resolve/remote.go index 3b97caa20b..6986a53d24 100644 --- a/pkg/resolve/remote.go +++ b/pkg/resolve/remote.go @@ -33,11 +33,14 @@ func assembleTaskFQDNs(pipelineURL string, tasks []string) ([]string, error) { return tasks, nil // no pipeline URL, return tasks as is } - // Only HTTP(S) URLs can serve as base for relative task resolution. + // Only HTTP(S) URLs and repository file paths can serve as base for relative task resolution. // Hub catalog references (e.g., "catalog://resource:version") use a // different scheme where relative paths are meaningless. lowered := strings.ToLower(pipelineURL) - if !strings.HasPrefix(lowered, "http://") && !strings.HasPrefix(lowered, "https://") { + isHTTP := strings.HasPrefix(lowered, "http://") || strings.HasPrefix(lowered, "https://") + isRepoPath := strings.Contains(lowered, "/") && !strings.Contains(lowered, "://") + + if !isHTTP && !isRepoPath { return tasks, nil } diff --git a/pkg/resolve/remote_test.go b/pkg/resolve/remote_test.go index ec67e12269..c14f039e76 100644 --- a/pkg/resolve/remote_test.go +++ b/pkg/resolve/remote_test.go @@ -562,10 +562,10 @@ func TestAssembleTaskFQDNs(t *testing.T) { expected: []string{"https://example.com/repo/task.yaml"}, }, { - name: "repository file path URL returns tasks unchanged", + name: "repository file path URL resolves relative tasks", pipelineURL: "share/pipelines/build.yaml", tasks: []string{"../tasks/t.yaml", "tasks/other-task.yaml"}, - expected: []string{"../tasks/t.yaml", "tasks/other-task.yaml"}, + expected: []string{"share/tasks/t.yaml", "share/pipelines/tasks/other-task.yaml"}, }, } for _, tt := range tests { diff --git a/test/gitea_test.go b/test/gitea_test.go index 093b099aa5..991e57938d 100644 --- a/test/gitea_test.go +++ b/test/gitea_test.go @@ -54,9 +54,10 @@ func TestGiteaPullRequestTaskAnnotations(t *testing.T) { Regexp: successRegexp, TargetEvent: triggertype.PullRequest.String(), YAMLFiles: map[string]string{ - ".tekton/pipeline.yaml": "testdata/pipeline_in_tektondir.yaml", - ".other-tasks/task-referenced-internally.yaml": "testdata/task_referenced_internally.yaml", - ".tekton/pr.yaml": "testdata/pipelinerun_remote_task_annotations.yaml", + ".tekton/pipeline.yaml": "testdata/pipeline_in_tektondir.yaml", + ".other-tasks/task-referenced-internally.yaml": "testdata/task_referenced_internally.yaml", + ".other-tasks/task2-referenced-internally.yaml": "testdata/task2_referenced_internally.yaml", + ".tekton/pr.yaml": "testdata/pipelinerun_remote_task_annotations.yaml", }, CheckForStatus: "success", ExtraArgs: map[string]string{ diff --git a/test/github_scope_token_to_list_of_private_public_repos_test.go b/test/github_scope_token_to_list_of_private_public_repos_test.go index 7f451a1df4..65325e5e48 100644 --- a/test/github_scope_token_to_list_of_private_public_repos_test.go +++ b/test/github_scope_token_to_list_of_private_public_repos_test.go @@ -96,9 +96,10 @@ func verifyGHTokenScope(t *testing.T, remoteTaskURL, remoteTaskName string, data defer configmap.ChangeGlobalConfig(ctx, t, runcnx, "pipelines-as-code", data)() entries, err := payload.GetEntries(map[string]string{ - ".tekton/pr.yaml": "testdata/pipelinerun_remote_task_annotations.yaml", - ".tekton/pipeline.yaml": "testdata/pipeline_in_tektondir.yaml", - ".other-tasks/task-referenced-internally.yaml": "testdata/task_referenced_internally.yaml", + ".tekton/pr.yaml": "testdata/pipelinerun_remote_task_annotations.yaml", + ".tekton/pipeline.yaml": "testdata/pipeline_in_tektondir.yaml", + ".other-tasks/task-referenced-internally.yaml": "testdata/task_referenced_internally.yaml", + ".other-tasks/task2-referenced-internally.yaml": "testdata/task2_referenced_internally.yaml", }, targetNS, options.MainBranch, triggertype.PullRequest.String(), map[string]string{ "RemoteTaskURL": remoteTaskURL, "RemoteTaskName": remoteTaskName, diff --git a/test/testdata/pipeline_in_tektondir.yaml b/test/testdata/pipeline_in_tektondir.yaml index 9f4f3a7a9f..6773304f40 100644 --- a/test/testdata/pipeline_in_tektondir.yaml +++ b/test/testdata/pipeline_in_tektondir.yaml @@ -21,3 +21,7 @@ spec: - name: task-referenced-internally taskRef: name: task-referenced-internally + + - name: task2-referenced-internally + taskRef: + name: task2-referenced-internally diff --git a/test/testdata/pipelinerun_remote_task_annotations.yaml b/test/testdata/pipelinerun_remote_task_annotations.yaml index 5f42d630c2..0bb29492dc 100644 --- a/test/testdata/pipelinerun_remote_task_annotations.yaml +++ b/test/testdata/pipelinerun_remote_task_annotations.yaml @@ -10,6 +10,7 @@ metadata: pipelinesascode.tekton.dev/task: "[.other-tasks/task-referenced-internally.yaml]" pipelinesascode.tekton.dev/task-1: "[\\ .RemoteTaskURL //]" pipelinesascode.tekton.dev/task-2: "default://pylint" + pipelinesascode.tekton.dev/task-3: "[../.other-tasks/task2-referenced-internally.yaml]" spec: pipelineRef: name: pipeline-in-tekton-dir diff --git a/test/testdata/task2_referenced_internally.yaml b/test/testdata/task2_referenced_internally.yaml new file mode 100644 index 0000000000..2a11da506e --- /dev/null +++ b/test/testdata/task2_referenced_internally.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: tekton.dev/v1beta1 +kind: Task +metadata: + name: task2-referenced-internally +spec: + steps: + - name: task2-remote + image: gcr.io/distroless/python3:nonroot + script: | + #!/usr/bin/python3 + print("Hello Task Referenced Internally")