Home  >  Article  >  Backend Development  >  How can I implement robust and secure zip file extraction in Go, addressing potential issues like file descriptor leaks and ZipSlip vulnerabilities?

How can I implement robust and secure zip file extraction in Go, addressing potential issues like file descriptor leaks and ZipSlip vulnerabilities?

Patricia Arquette
Patricia ArquetteOriginal
2024-11-13 06:46:02451browse

How can I implement robust and secure zip file extraction in Go, addressing potential issues like file descriptor leaks and ZipSlip vulnerabilities?

Effortless Zip File Extraction with Go

Unzipping files in Go can be a breeze with the help of the zip package. By utilizing its capabilities, you can easily extract the contents of compressed archives.

Original Code:

func Unzip(src, dest string) error {
    r, err := zip.OpenReader(src)
    if err != nil {
        return err
    }
    defer r.Close()

    for _, f := range r.File {
        rc, err := f.Open()
        if err != nil {
            return err
        }
        defer rc.Close()

        path := filepath.Join(dest, f.Name)
        if f.FileInfo().IsDir() {
            os.MkdirAll(path, f.Mode())
        } else {
            f, err := os.OpenFile(
                path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
            if err != nil {
                return err
            }
            defer f.Close()

            _, err = io.Copy(f, rc)
            if err != nil {
                return err
            }
        }
    }

    return nil
}

Enhanced Code:

To further improve the code and avoid file descriptor issues, consider the following enhancements:

  1. Create the destination directory (dest) if it doesn't exist (os.MkdirAll).
  2. Encapsulate file extraction and writing in a closure to eliminate stacking of defer .Close() calls.
  3. Add error handling to Close() operations.
  4. Implement a check for ZipSlip (directory traversal) vulnerabilities.
func Unzip(src, dest string) error {
    r, err := zip.OpenReader(src)
    if err != nil {
        return err
    }
    defer func() {
        if err := r.Close(); err != nil {
            panic(err)
        }
    }()

    os.MkdirAll(dest, 0755)

    extractAndWriteFile := func(f *zip.File) error {
        rc, err := f.Open()
        if err != nil {
            return err
        }
        defer func() {
            if err := rc.Close(); err != nil {
                panic(err)
            }
        }()

        path := filepath.Join(dest, f.Name)

        if !strings.HasPrefix(path, filepath.Clean(dest) + string(os.PathSeparator)) {
            return fmt.Errorf("illegal file path: %s", path)
        }

        if f.FileInfo().IsDir() {
            os.MkdirAll(path, f.Mode())
        } else {
            os.MkdirAll(filepath.Dir(path), f.Mode())
            f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
            if err != nil {
                return err
            }
            defer func() {
                if err := f.Close(); err != nil {
                    panic(err)
                }
            }()

            _, err = io.Copy(f, rc)
            if err != nil {
                return err
            }
        }
        return nil
    }

    for _, f := range r.File {
        err := extractAndWriteFile(f)
        if err != nil {
            return err
        }
    }

    return nil
}

With these enhancements, you can now efficiently and securely unzip files in Go.

The above is the detailed content of How can I implement robust and secure zip file extraction in Go, addressing potential issues like file descriptor leaks and ZipSlip vulnerabilities?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn