返回提交历史
Modified
g4f-go/download.go
+36
-0
Modified
g4f-go/process.go
+3
-0
XFEstudio/gpt4free
fix(security): resolve Zip Slip and unsafe archive symlink extraction in Go runtime
a2259e8b
代码差异
2 个文件
+39
-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 {
@@ -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+"/")