mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-19 10:33:29 +00:00
Harden update manager directory scans
This commit is contained in:
parent
82c8c08a3e
commit
4af6858405
3 changed files with 56 additions and 5 deletions
|
|
@ -151,6 +151,11 @@ update server bases must normalize to absolute HTTP(S) URLs without userinfo,
|
|||
and release API, feed, download, and checksum requests must resolve from
|
||||
validated URL objects instead of raw string concatenation or request creation
|
||||
from unchecked inputs.
|
||||
That same boundary also governs owned filesystem scans inside the update
|
||||
manager: when `internal/updates/manager.go` enumerates already-owned extract,
|
||||
temp, backup, or restore directories, it must rejoin discovered entry names
|
||||
through the shared storage-path helper instead of rebuilding raw
|
||||
`filepath.Join(dir, entry.Name())` paths.
|
||||
That same boundary also governs install.sh rollback restore targets:
|
||||
`adapter_installsh.go` may not hardcode `/etc/pulse` for rollback safety
|
||||
backups or config restore, and must derive the rollback config directory
|
||||
|
|
|
|||
|
|
@ -1681,8 +1681,16 @@ func (m *Manager) applyUpdateFiles(extractDir string) error {
|
|||
}
|
||||
// Copy agent binaries
|
||||
if strings.HasPrefix(name, "pulse-agent-") {
|
||||
srcPath := filepath.Join(binDir, name)
|
||||
destPath := filepath.Join(destBinDir, name)
|
||||
srcPath, err := securityutil.JoinStorageLeaf(binDir, name)
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Str("binary", name).Msg("Skipping invalid agent binary path")
|
||||
continue
|
||||
}
|
||||
destPath, err := securityutil.JoinStorageLeaf(destBinDir, name)
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Str("binary", name).Msg("Skipping invalid destination binary path")
|
||||
continue
|
||||
}
|
||||
cmd = exec.Command("cp", "-a", srcPath, destPath)
|
||||
if err := cmd.Run(); err != nil {
|
||||
log.Warn().Err(err).Str("binary", name).Msg("Failed to copy agent binary")
|
||||
|
|
@ -1855,7 +1863,11 @@ func (m *Manager) cleanupOldTempDirs() {
|
|||
continue
|
||||
}
|
||||
|
||||
fullPath := filepath.Join(dir, entry.Name())
|
||||
fullPath, err := securityutil.JoinStorageLeaf(dir, entry.Name())
|
||||
if err != nil {
|
||||
log.Debug().Err(err).Str("dir", dir).Str("entry", entry.Name()).Msg("Skipping invalid temp directory leaf")
|
||||
continue
|
||||
}
|
||||
info, err := os.Stat(fullPath)
|
||||
if err != nil {
|
||||
continue
|
||||
|
|
@ -1937,8 +1949,16 @@ func (m *Manager) copyDirSafe(src, dest string) error {
|
|||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
srcPath := filepath.Join(src, entry.Name())
|
||||
destPath := filepath.Join(dest, entry.Name())
|
||||
srcPath, err := securityutil.JoinStorageLeaf(src, entry.Name())
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Str("dir", src).Str("entry", entry.Name()).Msg("Skipping invalid source path during backup/restore")
|
||||
continue
|
||||
}
|
||||
destPath, err := securityutil.JoinStorageLeaf(dest, entry.Name())
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Str("dir", dest).Str("entry", entry.Name()).Msg("Skipping invalid destination path during backup/restore")
|
||||
continue
|
||||
}
|
||||
|
||||
// Get file info (using Lstat to detect symlinks)
|
||||
info, err := os.Lstat(srcPath)
|
||||
|
|
|
|||
|
|
@ -137,3 +137,29 @@ func TestManagerCopyDirSafe(t *testing.T) {
|
|||
t.Fatal("expected symlink to be skipped")
|
||||
}
|
||||
}
|
||||
|
||||
func TestManagerCopyDirSafe_SkipsInvalidLeafNames(t *testing.T) {
|
||||
manager := &Manager{}
|
||||
srcDir := filepath.Join(t.TempDir(), "src")
|
||||
destDir := filepath.Join(t.TempDir(), "dest")
|
||||
|
||||
if err := os.MkdirAll(srcDir, 0755); err != nil {
|
||||
t.Fatalf("mkdir src: %v", err)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(srcDir, "ok.txt"), []byte("ok"), 0600); err != nil {
|
||||
t.Fatalf("write ok: %v", err)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(srcDir, `bad\name.txt`), []byte("skip"), 0600); err != nil {
|
||||
t.Fatalf("write bad leaf: %v", err)
|
||||
}
|
||||
|
||||
if err := manager.copyDirSafe(srcDir, destDir); err != nil {
|
||||
t.Fatalf("copyDirSafe error: %v", err)
|
||||
}
|
||||
if _, err := os.ReadFile(filepath.Join(destDir, "ok.txt")); err != nil {
|
||||
t.Fatalf("expected ok.txt copied: %v", err)
|
||||
}
|
||||
if _, err := os.Lstat(filepath.Join(destDir, `bad\name.txt`)); err == nil {
|
||||
t.Fatal("expected invalid leaf to be skipped")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue