mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix(agent/agentcontext): canonicalize scan root in symlink boundary check (#26175)
This commit is contained in:
@@ -61,7 +61,7 @@ func TestAPI_ListSourcesEmpty(t *testing.T) {
|
||||
func TestAPI_AddAndListSource(t *testing.T) {
|
||||
t.Parallel()
|
||||
wd := t.TempDir()
|
||||
src := t.TempDir()
|
||||
src := testutil.TempDirResolved(t)
|
||||
|
||||
srv, _ := newAPITestServer(t, agentcontext.ManagerOptions{
|
||||
WorkingDir: func() string { return wd },
|
||||
@@ -103,7 +103,7 @@ func TestAPI_AddSourceRejected(t *testing.T) {
|
||||
func TestAPI_GetAndDeleteSource(t *testing.T) {
|
||||
t.Parallel()
|
||||
wd := t.TempDir()
|
||||
src := t.TempDir()
|
||||
src := testutil.TempDirResolved(t)
|
||||
|
||||
srv, m := newAPITestServer(t, agentcontext.ManagerOptions{
|
||||
WorkingDir: func() string { return wd },
|
||||
|
||||
@@ -67,8 +67,8 @@ func TestManager_InitialSnapshotIsPopulated(t *testing.T) {
|
||||
|
||||
func TestManager_AddSourceTriggersResolve(t *testing.T) {
|
||||
t.Parallel()
|
||||
wd := t.TempDir()
|
||||
src := t.TempDir()
|
||||
wd := testutil.TempDirResolved(t)
|
||||
src := testutil.TempDirResolved(t)
|
||||
mustWriteFile(t, filepath.Join(src, "AGENTS.md"), "from source")
|
||||
|
||||
m := newTestManager(t, agentcontext.ManagerOptions{
|
||||
@@ -194,7 +194,7 @@ func TestManager_RemoveSource(t *testing.T) {
|
||||
func TestManager_HasSource(t *testing.T) {
|
||||
t.Parallel()
|
||||
wd := t.TempDir()
|
||||
src := t.TempDir()
|
||||
src := testutil.TempDirResolved(t)
|
||||
|
||||
m := newTestManager(t, agentcontext.ManagerOptions{
|
||||
WorkingDir: func() string { return wd },
|
||||
@@ -285,7 +285,7 @@ func TestManager_ResyncCanceledKeepsLiveSnapshot(t *testing.T) {
|
||||
func TestManager_InitialSourcesSeeded(t *testing.T) {
|
||||
t.Parallel()
|
||||
wd := t.TempDir()
|
||||
src := t.TempDir()
|
||||
src := testutil.TempDirResolved(t)
|
||||
mustWriteFile(t, filepath.Join(src, "AGENTS.md"), "from initial")
|
||||
|
||||
m := newTestManager(t, agentcontext.ManagerOptions{
|
||||
@@ -312,7 +312,7 @@ func TestManager_InitialSourcesSeeded(t *testing.T) {
|
||||
func TestManager_SeedSourcesLateBindsAfterManifest(t *testing.T) {
|
||||
t.Parallel()
|
||||
wd := t.TempDir()
|
||||
late := t.TempDir()
|
||||
late := testutil.TempDirResolved(t)
|
||||
mustWriteFile(t, filepath.Join(late, "AGENTS.md"), "late binding")
|
||||
|
||||
// AllowedRoots intentionally omits `late` so AddSource
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/coder/coder/v2/agent/agentcontext"
|
||||
"github.com/coder/coder/v2/testutil"
|
||||
)
|
||||
|
||||
// switchHomeEnv overrides the platform-specific environment
|
||||
@@ -99,7 +100,7 @@ func TestValidateSourcePath_RejectsParentSegments(t *testing.T) {
|
||||
|
||||
func TestValidateSourcePath_AllowsInsideRoot(t *testing.T) {
|
||||
t.Parallel()
|
||||
dir := t.TempDir()
|
||||
dir := testutil.TempDirResolved(t)
|
||||
child := filepath.Join(dir, "child")
|
||||
require.NoError(t, os.MkdirAll(child, 0o755))
|
||||
|
||||
|
||||
@@ -368,7 +368,16 @@ func resolveReadTarget(path string, info fs.FileInfo, scanRoot string) (readPath
|
||||
if err != nil {
|
||||
return "", nil, false, StatusUnreadable, fmt.Sprintf("symlink resolve: %v", err)
|
||||
}
|
||||
// Canonicalize scanRoot symmetrically with the target so the
|
||||
// boundary check survives platform-level symlinks in the scan
|
||||
// root prefix. macOS, for example, exposes /var as a symlink
|
||||
// to /private/var; EvalSymlinks on the target produces a
|
||||
// /private/var path while the caller's scanRoot may still be
|
||||
// /var, which would incorrectly trip the prefix check.
|
||||
rootClean := filepath.Clean(scanRoot)
|
||||
if resolved, err := filepath.EvalSymlinks(rootClean); err == nil {
|
||||
rootClean = resolved
|
||||
}
|
||||
if !pathHasPrefix(target, rootClean) {
|
||||
return "", nil, false, StatusInvalid, fmt.Sprintf("symlink target %q escapes scan root %q", target, scanRoot)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user