Skip to content

Commit a305f10

Browse files
authored
Fileperms (#442)
1 parent 00363ed commit a305f10

File tree

7 files changed

+73
-2
lines changed

7 files changed

+73
-2
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ directory you can supply `./...` as the input argument.
8282
- G303: Creating tempfile using a predictable path
8383
- G304: File path provided as taint input
8484
- G305: File traversal when extracting zip archive
85+
- G306: Poor file permissions used when writing to a new file
8586
- G401: Detect the usage of DES, RC4, MD5 or SHA1
8687
- G402: Look for bad TLS connection settings
8788
- G403: Ensure minimum RSA key length of 2048 bits

cmd/tlsconfig/tlsconfig.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,5 +186,5 @@ func main() {
186186
outputPath := filepath.Join(dir, *outputFile)
187187
if err := ioutil.WriteFile(outputPath, src, 0644); err != nil {
188188
log.Fatalf("Writing output: %s", err)
189-
}
189+
} // #nosec G306
190190
}

rules/fileperms.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,22 @@ func (r *filePermissions) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, err
6060
return nil, nil
6161
}
6262

63+
// NewWritePerms creates a rule to detect file Writes with bad permissions.
64+
func NewWritePerms(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
65+
mode := getConfiguredMode(conf, "G306", 0600)
66+
return &filePermissions{
67+
mode: mode,
68+
pkg: "io/ioutil",
69+
calls: []string{"WriteFile"},
70+
MetaData: gosec.MetaData{
71+
ID: id,
72+
Severity: gosec.Medium,
73+
Confidence: gosec.High,
74+
What: fmt.Sprintf("Expect WriteFile permissions to be %#o or less", mode),
75+
},
76+
}, []ast.Node{(*ast.CallExpr)(nil)}
77+
}
78+
6379
// NewFilePerms creates a rule to detect file creation with a more permissive than configured
6480
// permission mask.
6581
func NewFilePerms(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {

rules/rulelist.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ func Generate(filters ...RuleFilter) RuleList {
8181
{"G303", "Creating tempfile using a predictable path", NewBadTempFile},
8282
{"G304", "File path provided as taint input", NewReadFile},
8383
{"G305", "File path traversal when extracting zip archive", NewArchive},
84+
{"G306", "Poor file permissions used when writing to a file", NewWritePerms},
8485

8586
// crypto
8687
{"G401", "Detect the usage of DES, RC4, MD5 or SHA1", NewUsesWeakCryptography},

rules/rules_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ var _ = Describe("gosec rules", func() {
127127
runner("G305", testutils.SampleCodeG305)
128128
})
129129

130+
It("should detect poor permissions when writing to a file", func() {
131+
runner("G306", testutils.SampleCodeG306)
132+
})
133+
130134
It("should detect weak crypto algorithms", func() {
131135
runner("G401", testutils.SampleCodeG401)
132136
})

testutils/pkg.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func (p *TestPackage) write() error {
5555
for filename, content := range p.Files {
5656
if e := ioutil.WriteFile(filename, []byte(content), 0644); e != nil {
5757
return e
58-
}
58+
} // #nosec G306
5959
}
6060
p.ondisk = true
6161
return nil

testutils/source.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,6 +1400,55 @@ func unzip(archive, target string) error {
14001400
}
14011401
14021402
return nil
1403+
}`}, 1, gosec.NewConfig()}}
1404+
1405+
// SampleCodeG306 - Poor permissions for WriteFile
1406+
SampleCodeG306 = []CodeSample{
1407+
{[]string{`package main
1408+
1409+
import (
1410+
"bufio"
1411+
"fmt"
1412+
"io/ioutil"
1413+
"os"
1414+
)
1415+
1416+
func check(e error) {
1417+
if e != nil {
1418+
panic(e)
1419+
}
1420+
}
1421+
1422+
func main() {
1423+
1424+
d1 := []byte("hello\ngo\n")
1425+
err := ioutil.WriteFile("/tmp/dat1", d1, 0744)
1426+
check(err)
1427+
1428+
allowed := ioutil.WriteFile("/tmp/dat1", d1, 0600)
1429+
check(allowed)
1430+
1431+
f, err := os.Create("/tmp/dat2")
1432+
check(err)
1433+
1434+
defer f.Close()
1435+
1436+
d2 := []byte{115, 111, 109, 101, 10}
1437+
n2, err := f.Write(d2)
1438+
check(err)
1439+
fmt.Printf("wrote %d bytes\n", n2)
1440+
1441+
n3, err := f.WriteString("writes\n")
1442+
fmt.Printf("wrote %d bytes\n", n3)
1443+
1444+
f.Sync()
1445+
1446+
w := bufio.NewWriter(f)
1447+
n4, err := w.WriteString("buffered\n")
1448+
fmt.Printf("wrote %d bytes\n", n4)
1449+
1450+
w.Flush()
1451+
14031452
}`}, 1, gosec.NewConfig()}}
14041453

14051454
// SampleCodeG401 - Use of weak crypto MD5

0 commit comments

Comments
 (0)