Fixed up so trying to read (from script) symlinks outside project folder result in error
This commit is contained in:
parent
9f24408a0b
commit
a1c9e16abe
3 changed files with 58 additions and 1 deletions
|
|
@ -314,6 +314,15 @@ func validateScriptFilePath(projectRoot, path string) (string, error) {
|
||||||
return "", fmt.Errorf("file access denied: path resolves outside project folder")
|
return "", fmt.Errorf("file access denied: path resolves outside project folder")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve symlinks to prevent symlink-based escape
|
||||||
|
realPath, err := filepath.EvalSymlinks(resolved)
|
||||||
|
if err == nil {
|
||||||
|
if !strings.HasPrefix(realPath, projectRootWithSep) && realPath != projectRoot {
|
||||||
|
return "", fmt.Errorf("file access denied: symlink target resolves outside project folder")
|
||||||
|
}
|
||||||
|
return realPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
return resolved, nil
|
return resolved, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -501,6 +501,50 @@ func TestValidateScriptFilePath_RejectsEmptyPath(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValidateScriptFilePath_RejectsSymlinkEscape(t *testing.T) {
|
||||||
|
projectRoot := t.TempDir()
|
||||||
|
|
||||||
|
// Symlink pointing outside the project root
|
||||||
|
outsideTarget := filepath.Join(projectRoot, "..", "outside.txt")
|
||||||
|
if err := os.WriteFile(outsideTarget, []byte("secret"), 0644); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
symlinkPath := filepath.Join(projectRoot, "evil_link")
|
||||||
|
if err := os.Symlink(outsideTarget, symlinkPath); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := validateScriptFilePath(projectRoot, "evil_link")
|
||||||
|
if err == nil {
|
||||||
|
t.Error("expected error for symlink escaping project root, got nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateScriptFilePath_AllowsSymlinkWithinProject(t *testing.T) {
|
||||||
|
projectRoot := t.TempDir()
|
||||||
|
|
||||||
|
// Create a file inside the project
|
||||||
|
targetPath := filepath.Join(projectRoot, "real_file.txt")
|
||||||
|
if err := os.WriteFile(targetPath, []byte("data"), 0644); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a symlink pointing inside the project
|
||||||
|
symlinkPath := filepath.Join(projectRoot, "link_to_real.txt")
|
||||||
|
if err := os.Symlink("real_file.txt", symlinkPath); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
got, err := validateScriptFilePath(projectRoot, "link_to_real.txt")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if got != targetPath {
|
||||||
|
t.Errorf("got %q, want %q", got, targetPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --- Tests for load_binary builtin ---
|
// --- Tests for load_binary builtin ---
|
||||||
|
|
||||||
func TestExecuteScript_LoadBinary(t *testing.T) {
|
func TestExecuteScript_LoadBinary(t *testing.T) {
|
||||||
|
|
|
||||||
6
main.go
6
main.go
|
|
@ -143,7 +143,11 @@ func compileOnly(inFile, outFile string, opt, optDebug, optC64 bool, optExcludes
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to resolve input file path: %w", err)
|
return fmt.Errorf("failed to resolve input file path: %w", err)
|
||||||
}
|
}
|
||||||
comp.Context().ProjectRoot = filepath.Dir(absInput)
|
projectRoot := filepath.Dir(absInput)
|
||||||
|
if canonicalRoot, err := filepath.EvalSymlinks(projectRoot); err == nil {
|
||||||
|
projectRoot = canonicalRoot
|
||||||
|
}
|
||||||
|
comp.Context().ProjectRoot = projectRoot
|
||||||
comp.CmdlineOpt = opt
|
comp.CmdlineOpt = opt
|
||||||
comp.CmdlineDebug = optDebug
|
comp.CmdlineDebug = optDebug
|
||||||
// Build I/O regions from CLI flags
|
// Build I/O regions from CLI flags
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue