@@ -24,8 +24,9 @@ import (
24
24
type readfile struct {
25
25
gosec.MetaData
26
26
gosec.CallList
27
- pathJoin gosec.CallList
28
- clean gosec.CallList
27
+ pathJoin gosec.CallList
28
+ clean gosec.CallList
29
+ cleanedVar map [any ]ast.Node
29
30
}
30
31
31
32
// ID returns the identifier for this rule
@@ -57,24 +58,29 @@ func (r *readfile) isJoinFunc(n ast.Node, c *gosec.Context) bool {
57
58
return false
58
59
}
59
60
60
- // isFilepathClean checks if there is a filepath.Clean before assigning to a variable
61
- func (r * readfile ) isFilepathClean (n * ast.Ident , c * gosec. Context ) bool {
62
- if n .Obj .Kind != ast . Var {
63
- return false
61
+ // isFilepathClean checks if there is a filepath.Clean for given variable
62
+ func (r * readfile ) isFilepathClean (n * ast.Ident ) bool {
63
+ if _ , ok := r . cleanedVar [ n .Obj .Decl ]; ok {
64
+ return true
64
65
}
65
- if node , ok := n .Obj .Decl .(* ast.AssignStmt ); ok {
66
- if call , ok := node .Rhs [0 ].(* ast.CallExpr ); ok {
67
- if clean := r .clean .ContainsPkgCallExpr (call , c , false ); clean != nil {
68
- return true
69
- }
66
+ return false
67
+ }
68
+
69
+ // trackFilepathClean tracks back the declaration of variable from filepath.Clean argument
70
+ func (r * readfile ) trackFilepathClean (n ast.Node ) {
71
+ if clean , ok := n .(* ast.CallExpr ); ok && len (clean .Args ) > 0 {
72
+ if ident , ok := clean .Args [0 ].(* ast.Ident ); ok {
73
+ r .cleanedVar [ident .Obj .Decl ] = n
70
74
}
71
75
}
72
- return false
73
76
}
74
77
75
78
// Match inspects AST nodes to determine if the match the methods `os.Open` or `ioutil.ReadFile`
76
79
func (r * readfile ) Match (n ast.Node , c * gosec.Context ) (* gosec.Issue , error ) {
77
- if node := r .ContainsPkgCallExpr (n , c , false ); node != nil {
80
+ if node := r .clean .ContainsPkgCallExpr (n , c , false ); node != nil {
81
+ r .trackFilepathClean (n )
82
+ return nil , nil
83
+ } else if node := r .ContainsPkgCallExpr (n , c , false ); node != nil {
78
84
for _ , arg := range node .Args {
79
85
// handles path joining functions in Arg
80
86
// eg. os.Open(filepath.Join("/tmp/", file))
@@ -95,7 +101,7 @@ func (r *readfile) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
95
101
obj := c .Info .ObjectOf (ident )
96
102
if _ , ok := obj .(* types.Var ); ok &&
97
103
! gosec .TryResolve (ident , c ) &&
98
- ! r .isFilepathClean (ident , c ) {
104
+ ! r .isFilepathClean (ident ) {
99
105
return gosec .NewIssue (c , n , r .ID (), r .What , r .Severity , r .Confidence ), nil
100
106
}
101
107
}
@@ -116,6 +122,7 @@ func NewReadFile(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
116
122
Severity : gosec .Medium ,
117
123
Confidence : gosec .High ,
118
124
},
125
+ cleanedVar : map [any ]ast.Node {},
119
126
}
120
127
rule .pathJoin .Add ("path/filepath" , "Join" )
121
128
rule .pathJoin .Add ("path" , "Join" )
0 commit comments