go.lang.security.zip.path-traversal-inside-zip-extraction
Verifed by r2c
Community Favorite
semgrep
Author
156,963
Download Count*
License
File traversal when extracting zip archive
Run Locally
Run in CI
Defintion
rules:
- id: path-traversal-inside-zip-extraction
message: File traversal when extracting zip archive
metadata:
cwe:
- "CWE-22: Improper Limitation of a Pathname to a Restricted Directory
('Path Traversal')"
source_rule_url: https://github.com/securego/gosec/issues/205
category: security
technology:
- go
confidence: LOW
owasp:
- A05:2017 - Broken Access Control
- A01:2021 - Broken Access Control
references:
- https://owasp.org/Top10/A01_2021-Broken_Access_Control
cwe2022-top25: true
cwe2021-top25: true
subcategory:
- audit
likelihood: LOW
impact: LOW
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
vulnerability_class:
- Path Traversal
languages:
- go
severity: WARNING
pattern: |
reader, $ERR := zip.OpenReader($ARCHIVE)
...
for _, $FILE := range reader.File {
...
path := filepath.Join($TARGET, $FILE.Name)
...
}
Examples
zip.go
package unzip
import (
"archive/zip"
"fmt"
"io"
"log"
"os"
"path/filepath"
)
func unzip(archive, target string) error {
// ruleid: path-traversal-inside-zip-extraction
reader, err := zip.OpenReader(archive)
if err != nil {
return err
}
if err := os.MkdirAll(target, 0750); err != nil {
return err
}
for _, file := range reader.File {
path := filepath.Join(target, file.Name)
if file.FileInfo().IsDir() {
os.MkdirAll(path, file.Mode()) // #nosec
continue
}
fileReader, err := file.Open()
if err != nil {
return err
}
defer fileReader.Close()
targetFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode())
if err != nil {
return err
}
defer targetFile.Close()
if _, err := io.Copy(targetFile, fileReader); err != nil {
return err
}
}
return nil
}
func unzip_good() {
// Open a zip archive for reading.
r, err := zip.OpenReader("testdata/readme.zip")
if err != nil {
log.Fatal(err)
}
defer r.Close()
// Iterate through the files in the archive,
// printing some of their contents.
for _, f := range r.File {
fmt.Printf("Contents of %s:\n", f.Name)
rc, err := f.Open()
if err != nil {
log.Fatal(err)
}
_, err = io.CopyN(os.Stdout, rc, 68)
if err != nil {
log.Fatal(err)
}
rc.Close()
fmt.Println()
}
// Output:
// Contents of README:
// This is the source code repository for the Go programming language.
}
Short Link: https://sg.run/Av64