#3021·task

SmartJoin incorrectly treats relative paths containing special variable names as special paths

Author: znnnnnnn-wilCreated Sep 7, 2026Updated Sep 7, 2026
Labelsarea: exec

Description

SmartJoin incorrectly treats ordinary relative paths containing special variable names such as .ROOT_DIR as absolute/special paths, causing them to bypass the base-directory join.

What did you do?

I called SmartJoin with a normal relative path whose directory name happens to contain one of the special variable names:

go
SmartJoin(base, filepath.Join("project.ROOT_DIR", "file.txt"))

A minimal regression test demonstrating the issue is:

go
func TestSmartJoinRelativePathContainingSpecialVariableName(t *testing.T) {
	base := filepath.Join("base", "dir")
	path := filepath.Join("project.ROOT_DIR", "file.txt")

	got := SmartJoin(base, path)
	want := filepath.Join(base, path)

	if got != want {
		t.Fatalf("SmartJoin() = %q, want %q", got, want)
	}
}

It can be run with:

bash
go test ./internal/filepathext -run TestSmartJoinRelativePathContainingSpecialVariableName -count=1

What did you expect to happen?

The path should be treated as a normal relative path and joined with base.

In other words:

go
SmartJoin(base, filepath.Join("project.ROOT_DIR", "file.txt"))

should return the same result as:

go
filepath.Join(base, "project.ROOT_DIR", "file.txt")

What happened instead?

SmartJoin returns the input relative path unchanged instead of joining it with base.

The same behavior also appears to affect relative path components containing:

  • .ROOT_DIR
  • .TASKFILE_DIR
  • .USER_WORKING_DIR

From looking at the implementation, this may be caused by isSpecialDir using strings.Contains to detect special variables. As a result, an ordinary directory name containing one of these strings can be matched even when the variable is not actually part of a {{ ... }} template expression.

This can cause normal relative paths to bypass the base-directory join and potentially be resolved relative to an unintended location, including paths used for task directories, includes, dotenv files, or fingerprint-related logic.

Version

main (385e5ad92af02877b6d7cf9dcc963b5ed916e70a)

Operating system

Windows amd64, Go 1.26.5

Experiments Enabled

None