diff --git a/agent/app/service/file.go b/agent/app/service/file.go index fb92569b7..51a4614eb 100644 --- a/agent/app/service/file.go +++ b/agent/app/service/file.go @@ -907,6 +907,10 @@ func (f *FileService) ChangeName(req request.FileRename) error { func (f *FileService) Wget(w request.FileWget) (string, error) { fo := files.NewFileOp() + destination, err := files.ResolveDownloadDestination(w.Path, w.Name) + if err != nil { + return "", err + } key := "file-wget-" + common.GetUuid() options := files.DownloadOptions{ IgnoreCertificate: w.IgnoreCertificate, @@ -925,7 +929,7 @@ func (f *FileService) Wget(w request.FileWget) (string, error) { Password: systemProxy.Password, } } - return key, fo.DownloadFileWithProcess(w.Url, filepath.Join(w.Path, w.Name), key, options) + return key, fo.DownloadFileWithProcess(w.Url, destination, key, options) } func logFileTaskSources(t *task.Task, sources []string) { diff --git a/agent/utils/files/download_target.go b/agent/utils/files/download_target.go new file mode 100644 index 000000000..d41769e6f --- /dev/null +++ b/agent/utils/files/download_target.go @@ -0,0 +1,42 @@ +package files + +import ( + "os" + "path/filepath" + "strings" + "unicode" + "unicode/utf8" + + "github.com/1Panel-dev/1Panel/agent/buserr" +) + +func validDownloadFilename(name string) bool { + return strings.TrimSpace(name) != "" && name != "." && name != ".." && len(name) <= 255 && utf8.ValidString(name) && + !strings.ContainsAny(name, "/\\:") && strings.IndexFunc(name, unicode.IsControl) < 0 +} + +func ResolveDownloadDestination(directory, name string) (string, error) { + if strings.TrimSpace(directory) == "" || !validDownloadFilename(name) { + return "", buserr.New("ErrInvalidParams") + } + parent, err := filepath.EvalSymlinks(directory) + if err != nil { + return "", err + } + parent, err = filepath.Abs(parent) + if err != nil { + return "", err + } + info, err := os.Stat(parent) + if err != nil { + return "", err + } + if !info.IsDir() { + return "", buserr.New("ErrInvalidParams") + } + destination := filepath.Join(parent, name) + if filepath.Dir(destination) != parent { + return "", buserr.New("ErrInvalidParams") + } + return destination, nil +} diff --git a/agent/utils/files/file_op.go b/agent/utils/files/file_op.go index 3caf3a6ae..d426f42ba 100644 --- a/agent/utils/files/file_op.go +++ b/agent/utils/files/file_op.go @@ -29,8 +29,6 @@ import ( "sync" "syscall" "time" - "unicode" - "unicode/utf8" "github.com/1Panel-dev/1Panel/agent/buserr" @@ -399,8 +397,7 @@ func downloadResponseFilename(header string) string { return "" } name := strings.TrimSpace(params["filename"]) - if name == "" || name == "." || name == ".." || len(name) > 255 || !utf8.ValidString(name) || - strings.ContainsAny(name, "/\\:") || strings.IndexFunc(name, unicode.IsControl) >= 0 { + if !validDownloadFilename(name) { return "" } return name