mirror of
https://github.com/securego/gosec.git
synced 2024-12-26 04:25:52 +00:00
65 lines
1.6 KiB
Go
65 lines
1.6 KiB
Go
|
package rules
|
||
|
|
||
|
import (
|
||
|
"go/ast"
|
||
|
"regexp"
|
||
|
|
||
|
"github.com/securego/gosec/v2"
|
||
|
)
|
||
|
|
||
|
type traversal struct {
|
||
|
pattern *regexp.Regexp
|
||
|
gosec.MetaData
|
||
|
}
|
||
|
|
||
|
func (r *traversal) ID() string {
|
||
|
return r.MetaData.ID
|
||
|
}
|
||
|
|
||
|
func (r *traversal) Match(n ast.Node, ctx *gosec.Context) (*gosec.Issue, error) {
|
||
|
switch node := n.(type) {
|
||
|
case *ast.CallExpr:
|
||
|
return r.matchCallExpr(node, ctx)
|
||
|
}
|
||
|
return nil, nil
|
||
|
}
|
||
|
|
||
|
func (r *traversal) matchCallExpr(assign *ast.CallExpr, ctx *gosec.Context) (*gosec.Issue, error) {
|
||
|
for _, i := range assign.Args {
|
||
|
if basiclit, ok1 := i.(*ast.BasicLit); ok1 {
|
||
|
if fun, ok2 := assign.Fun.(*ast.SelectorExpr); ok2 {
|
||
|
if x, ok3 := fun.X.(*ast.Ident); ok3 {
|
||
|
string := x.Name + "." + fun.Sel.Name + "(" + basiclit.Value + ")"
|
||
|
if r.pattern.MatchString(string) {
|
||
|
return gosec.NewIssue(ctx, assign, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return nil, nil
|
||
|
}
|
||
|
|
||
|
// NewDirectoryTraversal attempts to find the use of http.Dir("/")
|
||
|
func NewDirectoryTraversal(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||
|
pattern := `http\.Dir\("\/"\)|http\.Dir\('\/'\)`
|
||
|
if val, ok := conf["G101"]; ok {
|
||
|
conf := val.(map[string]interface{})
|
||
|
if configPattern, ok := conf["pattern"]; ok {
|
||
|
if cfgPattern, ok := configPattern.(string); ok {
|
||
|
pattern = cfgPattern
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return &traversal{
|
||
|
pattern: regexp.MustCompile(pattern),
|
||
|
MetaData: gosec.MetaData{
|
||
|
ID: id,
|
||
|
What: "Potential directory traversal",
|
||
|
Confidence: gosec.Medium,
|
||
|
Severity: gosec.Medium,
|
||
|
},
|
||
|
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||
|
}
|