XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 1
返回提交历史

XFEstudio/gpt4free

fix(security): resolve Zip Slip and unsafe archive symlink extraction in Go runtime

a2259e8b
Anand Mall <anand@example.com>
提交于

代码差异

2 个文件 +39 -0
Modified g4f-go/download.go +36 -0
@@ -297,6 +297,9 @@ func extractRuntime(binDir, cachePath string) error {
297 297 if err != nil {
298 298 return err
299 299 }
300 if strings.Contains(hdr.Name, "..") {
301 return fmt.Errorf("unsafe path in archive: %s", hdr.Name)
302 }
300 303 rel := hdr.Name
301 304 if top != "" {
302 305 rel = strings.TrimPrefix(rel, top+"/")
@@ -340,6 +343,10 @@ func extractRuntime(binDir, cachePath string) error {
340 343 return err
341 344 }
342 345 case tar.TypeSymlink:
346 // Ensure symlink and its target do not escape the destination directory
347 if !isSafeSymlink(dest, target, hdr.Linkname) {
348 continue
349 }
343 350 // Symlinks in pbs installs point within the tree; recreate them
344 351 // (libpython3.so -> libpython3.14.so etc).
345 352 if err := os.MkdirAll(filepath.Dir(target), 0o755); err != nil {
@@ -361,6 +368,35 @@ func extractRuntime(binDir, cachePath string) error {
361 368 return nil
362 369 }
363 370
371 // isSafeSymlink validates that candidate symlink target does not escape the destination directory
372 func isSafeSymlink(dest, target, linkname string) bool {
373 if filepath.IsAbs(linkname) {
374 return false
375 }
376 realDest, err := filepath.EvalSymlinks(filepath.Clean(dest))
377 if err != nil {
378 realDest = filepath.Clean(dest)
379 }
380 realTargetDir, err := filepath.EvalSymlinks(filepath.Dir(target))
381 if err != nil {
382 return false
383 }
384 targetRel, err := filepath.Rel(realDest, realTargetDir)
385 if err != nil || strings.HasPrefix(filepath.Clean(targetRel), "..") {
386 return false
387 }
388 resolvedLink := filepath.Join(realTargetDir, linkname)
389 realLink, err := filepath.EvalSymlinks(resolvedLink)
390 if err != nil {
391 realLink = filepath.Clean(resolvedLink)
392 }
393 linkRel, err := filepath.Rel(realDest, realLink)
394 if err != nil || strings.HasPrefix(filepath.Clean(linkRel), "..") {
395 return false
396 }
397 return true
398 }
399
364 400 // copySymlinkTarget attempts to copy a symlink's target for filesystems that
365 401 // reject symlinks (best effort).
366 402 func copySymlinkTarget(target, linkname string) error {
Modified g4f-go/process.go +3 -0
@@ -72,6 +72,9 @@ func extractZip(r io.ReaderAt, size int64, dest string) error {
72 72 }
73 73
74 74 for _, f := range zr.File {
75 if strings.Contains(f.Name, "..") {
76 return fmt.Errorf("unsafe path in archive: %s", f.Name)
77 }
75 78 rel := f.Name
76 79 if top != "" {
77 80 rel = strings.TrimPrefix(f.Name, top+"/")