Skip to content

Commit 8c99d03

Browse files
committed
add check for symlinks, disallow all symlinks
1 parent dd1f2f2 commit 8c99d03

File tree

3 files changed

+45
-2
lines changed

3 files changed

+45
-2
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ module github.com/nginx/agent/v3
22

33
go 1.23.7
44

5-
toolchain go1.24.4
5+
toolchain go1.23.10
66

77
require (
88
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.4-20250130201111-63bb56e20495.1

internal/config/types.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,11 +436,23 @@ func isAllowedDir(path string, allowedDirs []string) bool {
436436
slog.Debug("File path detected, checking parent directory is allowed", "path", directoryPath)
437437
}
438438

439-
_, err = os.Stat(directoryPath)
439+
fInfo, err := os.Stat(directoryPath)
440440
if err != nil {
441441
slog.Warn("Path error", "path", path, "error", err)
442442
}
443443

444+
if fInfo != nil {
445+
//check if it contains a symlink
446+
lInfo, err := os.Lstat(directoryPath)
447+
if err != nil {
448+
slog.Warn("Lstat error", "path", path, "error", err)
449+
}
450+
if lInfo != nil && lInfo.Mode()&os.ModeSymlink != 0 {
451+
slog.Warn("Path is a symlink, not allowed", "path", path)
452+
return false
453+
}
454+
}
455+
444456
for _, allowedDirectory := range allowedDirs {
445457
// Check if the directoryPath starts with the allowedDirectory
446458
// This allows for subdirectories within the allowed directories.

internal/config/types_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
package config
77

88
import (
9+
"github.com/stretchr/testify/require"
10+
"os"
911
"testing"
1012

1113
"github.com/stretchr/testify/assert"
@@ -74,4 +76,33 @@ func TestTypes_isAllowedDir(t *testing.T) {
7476
assert.Equal(t, test.allowed, result)
7577
})
7678
}
79+
80+
t.Run("Symlink in allowed directory", func(t *testing.T) {
81+
allowedDirs := []string{"/etc/nginx"}
82+
filePath := "file.conf"
83+
symlinkPath := "file_link"
84+
85+
// Create a temp directory for the symlink
86+
tempDir, err := os.MkdirTemp("", "symlink_test")
87+
assert.NoError(t, err)
88+
defer os.RemoveAll(tempDir) // Clean up the temp directory after the test
89+
90+
// Ensure the temp directory is in the allowedDirs
91+
allowedDirs = append(allowedDirs, tempDir)
92+
93+
//create filePath
94+
filePath = tempDir + "/" + filePath
95+
defer os.RemoveAll(filePath)
96+
err = os.WriteFile(filePath, []byte("test content"), 0644)
97+
require.NoError(t, err)
98+
99+
// Create a symlink for testing
100+
symlinkPath = tempDir + "/" + symlinkPath
101+
defer os.Remove(symlinkPath)
102+
err = os.Symlink(filePath, symlinkPath)
103+
assert.NoError(t, err)
104+
105+
result := isAllowedDir(symlinkPath, allowedDirs)
106+
assert.False(t, result, "Symlink in allowed directory should return false")
107+
})
77108
}

0 commit comments

Comments
 (0)