mirror of
https://github.com/securego/gosec.git
synced 2024-12-24 11:35:52 +00:00
feat: adds support for path.Join and for tar archives in G305
This commit is contained in:
parent
673a139e55
commit
b60ddc21ba
3 changed files with 86 additions and 11 deletions
|
@ -107,7 +107,7 @@ directory you can supply `./...` as the input argument.
|
||||||
- G302: Poor file permissions used with chmod
|
- G302: Poor file permissions used with chmod
|
||||||
- G303: Creating tempfile using a predictable path
|
- G303: Creating tempfile using a predictable path
|
||||||
- G304: File path provided as taint input
|
- G304: File path provided as taint input
|
||||||
- G305: File traversal when extracting zip archive
|
- G305: File traversal when extracting zip/tar archive
|
||||||
- G306: Poor file permissions used when writing to a new file
|
- G306: Poor file permissions used when writing to a new file
|
||||||
- G307: Deferring a method which returns an error
|
- G307: Deferring a method which returns an error
|
||||||
- G401: Detect the usage of DES, RC4, MD5 or SHA1
|
- G401: Detect the usage of DES, RC4, MD5 or SHA1
|
||||||
|
|
|
@ -9,15 +9,15 @@ import (
|
||||||
|
|
||||||
type archive struct {
|
type archive struct {
|
||||||
gosec.MetaData
|
gosec.MetaData
|
||||||
calls gosec.CallList
|
calls gosec.CallList
|
||||||
argType string
|
argTypes []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *archive) ID() string {
|
func (a *archive) ID() string {
|
||||||
return a.MetaData.ID
|
return a.MetaData.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match inspects AST nodes to determine if the filepath.Joins uses any argument derived from type zip.File
|
// Match inspects AST nodes to determine if the filepath.Joins uses any argument derived from type zip.File or tar.Header
|
||||||
func (a *archive) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
func (a *archive) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||||
if node := a.calls.ContainsPkgCallExpr(n, c, false); node != nil {
|
if node := a.calls.ContainsPkgCallExpr(n, c, false); node != nil {
|
||||||
for _, arg := range node.Args {
|
for _, arg := range node.Args {
|
||||||
|
@ -35,26 +35,31 @@ func (a *archive) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if argType != nil && argType.String() == a.argType {
|
if argType != nil {
|
||||||
return gosec.NewIssue(c, n, a.ID(), a.What, a.Severity, a.Confidence), nil
|
for _, t := range a.argTypes {
|
||||||
|
if argType.String() == t {
|
||||||
|
return gosec.NewIssue(c, n, a.ID(), a.What, a.Severity, a.Confidence), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewArchive creates a new rule which detects the file traversal when extracting zip archives
|
// NewArchive creates a new rule which detects the file traversal when extracting zip/tar archives
|
||||||
func NewArchive(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
func NewArchive(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||||
calls := gosec.NewCallList()
|
calls := gosec.NewCallList()
|
||||||
calls.Add("path/filepath", "Join")
|
calls.Add("path/filepath", "Join")
|
||||||
|
calls.Add("path", "Join")
|
||||||
return &archive{
|
return &archive{
|
||||||
calls: calls,
|
calls: calls,
|
||||||
argType: "*archive/zip.File",
|
argTypes: []string{"*archive/zip.File", "*archive/tar.Header"},
|
||||||
MetaData: gosec.MetaData{
|
MetaData: gosec.MetaData{
|
||||||
ID: id,
|
ID: id,
|
||||||
Severity: gosec.Medium,
|
Severity: gosec.Medium,
|
||||||
Confidence: gosec.High,
|
Confidence: gosec.High,
|
||||||
What: "File traversal when extracting zip archive",
|
What: "File traversal when extracting zip/tar archive",
|
||||||
},
|
},
|
||||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1588,7 +1588,7 @@ func main() {
|
||||||
log.Print(body)
|
log.Print(body)
|
||||||
}`}, 1, gosec.NewConfig()}}
|
}`}, 1, gosec.NewConfig()}}
|
||||||
|
|
||||||
// SampleCodeG305 - File path traversal when extracting zip archives
|
// SampleCodeG305 - File path traversal when extracting zip/tar archives
|
||||||
SampleCodeG305 = []CodeSample{{[]string{`
|
SampleCodeG305 = []CodeSample{{[]string{`
|
||||||
package unzip
|
package unzip
|
||||||
|
|
||||||
|
@ -1680,6 +1680,76 @@ func unzip(archive, target string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
}`}, 1, gosec.NewConfig()}, {[]string{`
|
||||||
|
package zip
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/zip"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
)
|
||||||
|
|
||||||
|
func extractFile(f *zip.File, destPath string) error {
|
||||||
|
filePath := path.Join(destPath, f.Name)
|
||||||
|
os.MkdirAll(path.Dir(filePath), os.ModePerm)
|
||||||
|
|
||||||
|
rc, err := f.Open()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer rc.Close()
|
||||||
|
|
||||||
|
fw, err := os.Create(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer fw.Close()
|
||||||
|
|
||||||
|
if _, err = io.Copy(fw, rc); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.FileInfo().Mode()&os.ModeSymlink != 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = os.Chtimes(filePath, f.ModTime(), f.ModTime()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return os.Chmod(filePath, f.FileInfo().Mode())
|
||||||
|
}`}, 1, gosec.NewConfig()}, {[]string{`
|
||||||
|
package tz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/tar"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
)
|
||||||
|
|
||||||
|
func extractFile(f *tar.Header, tr *tar.Reader, destPath string) error {
|
||||||
|
filePath := path.Join(destPath, f.Name)
|
||||||
|
os.MkdirAll(path.Dir(filePath), os.ModePerm)
|
||||||
|
|
||||||
|
fw, err := os.Create(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer fw.Close()
|
||||||
|
|
||||||
|
if _, err = io.Copy(fw, tr); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.FileInfo().Mode()&os.ModeSymlink != 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = os.Chtimes(filePath, f.FileInfo().ModTime(), f.FileInfo().ModTime()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return os.Chmod(filePath, f.FileInfo().Mode())
|
||||||
}`}, 1, gosec.NewConfig()}}
|
}`}, 1, gosec.NewConfig()}}
|
||||||
|
|
||||||
// SampleCodeG306 - Poor permissions for WriteFile
|
// SampleCodeG306 - Poor permissions for WriteFile
|
||||||
|
|
Loading…
Reference in a new issue