mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-22 15:43:49 +01:00
204 lines
5.6 KiB
Go
204 lines
5.6 KiB
Go
package api
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"strings"
|
|
)
|
|
|
|
func TestInTrustedRoot(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
path string
|
|
trustedRoot string
|
|
wantErr bool
|
|
errMsg string
|
|
}{
|
|
{
|
|
name: "path directly in trusted root",
|
|
path: "/home/user/screenshots/image.jpg",
|
|
trustedRoot: "/home/user/screenshots",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "path with nested directories in trusted root",
|
|
path: "/home/user/screenshots/2024/image.jpg",
|
|
trustedRoot: "/home/user/screenshots",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "path outside trusted root",
|
|
path: "/home/user/other/image.jpg",
|
|
trustedRoot: "/home/user/screenshots",
|
|
wantErr: true,
|
|
errMsg: "path is outside of trusted root",
|
|
},
|
|
{
|
|
name: "path attempting directory traversal",
|
|
path: "/home/user/screenshots/../../../etc/passwd",
|
|
trustedRoot: "/home/user/screenshots",
|
|
wantErr: true,
|
|
errMsg: "path is outside of trusted root",
|
|
},
|
|
{
|
|
name: "root directory comparison",
|
|
path: "/home/user/screenshots/image.jpg",
|
|
trustedRoot: "/",
|
|
wantErr: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := inTrustedRoot(tt.path, tt.trustedRoot)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("inTrustedRoot() error = %v, wantErr %v", err, tt.wantErr)
|
|
}
|
|
if err != nil && tt.errMsg != "" && err.Error() != tt.errMsg {
|
|
t.Errorf("inTrustedRoot() error message = %v, want %v", err.Error(), tt.errMsg)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestVerifyPath(t *testing.T) {
|
|
// Create temporary directory structure for testing
|
|
tmpDir := t.TempDir()
|
|
safeDir := filepath.Join(tmpDir, "safe")
|
|
unsafeDir := filepath.Join(tmpDir, "unsafe")
|
|
|
|
if err := os.MkdirAll(safeDir, 0755); err != nil {
|
|
t.Fatalf("Failed to create test directory: %v", err)
|
|
}
|
|
if err := os.MkdirAll(unsafeDir, 0755); err != nil {
|
|
t.Fatalf("Failed to create test directory: %v", err)
|
|
}
|
|
|
|
// Create subdirectory in safe directory
|
|
nestedDir := filepath.Join(safeDir, "subdir")
|
|
if err := os.MkdirAll(nestedDir, 0755); err != nil {
|
|
t.Fatalf("Failed to create nested directory: %v", err)
|
|
}
|
|
|
|
// Create actual test files
|
|
safeFile := filepath.Join(safeDir, "image.jpg")
|
|
if err := os.WriteFile(safeFile, []byte("test"), 0644); err != nil {
|
|
t.Fatalf("Failed to create test file: %v", err)
|
|
}
|
|
|
|
nestedFile := filepath.Join(nestedDir, "image.jpg")
|
|
if err := os.WriteFile(nestedFile, []byte("test"), 0644); err != nil {
|
|
t.Fatalf("Failed to create nested test file: %v", err)
|
|
}
|
|
|
|
unsafeFile := filepath.Join(unsafeDir, "image.jpg")
|
|
if err := os.WriteFile(unsafeFile, []byte("test"), 0644); err != nil {
|
|
t.Fatalf("Failed to create unsafe test file: %v", err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
path string
|
|
trustedRoot string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "valid path in trusted directory",
|
|
path: safeFile,
|
|
trustedRoot: safeDir,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "valid nested path in trusted directory",
|
|
path: nestedFile,
|
|
trustedRoot: safeDir,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "path outside trusted directory",
|
|
path: unsafeFile,
|
|
trustedRoot: safeDir,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "path with .. traversal attempt",
|
|
path: filepath.Join(safeDir, "..", "unsafe", "image.jpg"),
|
|
trustedRoot: safeDir,
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result, err := verifyPath(tt.path, tt.trustedRoot)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("verifyPath() error = %v, wantErr %v", err, tt.wantErr)
|
|
}
|
|
if !tt.wantErr && result == "" {
|
|
t.Errorf("verifyPath() result should not be empty on success")
|
|
}
|
|
if !tt.wantErr && !strings.HasPrefix(result, tt.trustedRoot) {
|
|
t.Errorf("verifyPath() result = %s does not start with trustedRoot = %s", result, tt.trustedRoot)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestVerifyPathWithSymlinks(t *testing.T) {
|
|
// Skip on systems where symlinks might not work
|
|
tmpDir := t.TempDir()
|
|
safeDir := filepath.Join(tmpDir, "safe")
|
|
outsideDir := filepath.Join(tmpDir, "outside")
|
|
|
|
if err := os.MkdirAll(safeDir, 0755); err != nil {
|
|
t.Fatalf("Failed to create test directory: %v", err)
|
|
}
|
|
if err := os.MkdirAll(outsideDir, 0755); err != nil {
|
|
t.Fatalf("Failed to create test directory: %v", err)
|
|
}
|
|
|
|
// Create a file outside the safe directory
|
|
outsideFile := filepath.Join(outsideDir, "outside.jpg")
|
|
if err := os.WriteFile(outsideFile, []byte("outside"), 0644); err != nil {
|
|
t.Fatalf("Failed to create outside file: %v", err)
|
|
}
|
|
|
|
// Try to create a symlink pointing outside (this might fail on some systems)
|
|
symlinkPath := filepath.Join(safeDir, "link.jpg")
|
|
if err := os.Symlink(outsideFile, symlinkPath); err != nil {
|
|
t.Skipf("Symlinks not supported on this system: %v", err)
|
|
}
|
|
|
|
// Verify that symlink pointing outside is detected
|
|
_, err := verifyPath(symlinkPath, safeDir)
|
|
if err == nil {
|
|
t.Errorf("verifyPath() should reject symlink pointing outside trusted root")
|
|
}
|
|
}
|
|
|
|
func BenchmarkVerifyPath(b *testing.B) {
|
|
tmpDir := b.TempDir()
|
|
safeDir := filepath.Join(tmpDir, "safe")
|
|
if err := os.MkdirAll(safeDir, 0755); err != nil {
|
|
b.Fatalf("Failed to create test directory: %v", err)
|
|
}
|
|
|
|
testPath := filepath.Join(safeDir, "test.jpg")
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_, _ = verifyPath(testPath, safeDir)
|
|
}
|
|
}
|
|
|
|
func BenchmarkInTrustedRoot(b *testing.B) {
|
|
testPath := "/home/user/screenshots/2024/01/image.jpg"
|
|
trustedRoot := "/home/user/screenshots"
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_ = inTrustedRoot(testPath, trustedRoot)
|
|
}
|
|
}
|