mirror of
https://github.com/securego/gosec.git
synced 2024-11-05 11:35:51 +00:00
Replace gas with gosec everywhere in the project
This commit is contained in:
parent
da26f64208
commit
893b87b343
52 changed files with 387 additions and 390 deletions
2
.github/issue_template.md
vendored
2
.github/issue_template.md
vendored
|
@ -2,7 +2,7 @@
|
|||
|
||||
### Steps to reproduce the behavior
|
||||
|
||||
### Gas version
|
||||
### gosec version
|
||||
|
||||
### Go version (output of 'go version')
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ install:
|
|||
- go get -u github.com/onsi/ginkgo/ginkgo
|
||||
- go get -u github.com/onsi/gomega
|
||||
- go get -u golang.org/x/crypto/ssh
|
||||
- go get -u github.com/securego/gas/cmd/gas/...
|
||||
- go get -u github.com/securego/gosec/cmd/gosec/...
|
||||
- go get -v -t ./...
|
||||
- export PATH=$PATH:$HOME/gopath/bin
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
FROM golang:1.9.4-alpine3.7
|
||||
|
||||
ENV BIN=gas
|
||||
ENV BIN=gosec
|
||||
|
||||
COPY build/*-linux-amd64 /go/bin/$BIN
|
||||
COPY docker-entrypoint.sh /usr/local/bin
|
||||
|
|
8
Makefile
8
Makefile
|
@ -1,7 +1,7 @@
|
|||
GIT_TAG?= $(shell git describe --always --tags)
|
||||
BUILD_DATE = $(shell date +%Y-%m-%d)
|
||||
BIN = gas
|
||||
BUILD_CMD = go build -ldflags "-X main.Version=${VERSION} -X main.GitTag=${GIT_TAG} -X main.BuildDate=${BUILD_DATE}" -o build/$(BIN)-$(VERSION)-$${GOOS}-$${GOARCH} ./cmd/gas/ &
|
||||
BIN = gosec
|
||||
BUILD_CMD = go build -ldflags "-X main.Version=${VERSION} -X main.GitTag=${GIT_TAG} -X main.BuildDate=${BUILD_DATE}" -o build/$(BIN)-$(VERSION)-$${GOOS}-$${GOARCH} ./cmd/gosec/ &
|
||||
FMT_CMD = $(gofmt -s -l -w $(find . -type f -name '*.go' -not -path './vendor/*') | tee /dev/stderr)
|
||||
IMAGE_REPO = docker.io
|
||||
|
||||
|
@ -13,12 +13,12 @@ test: bootstrap
|
|||
test -z '$(FMT_CMD)'
|
||||
go vet $(go list ./... | grep -v /vendor/)
|
||||
golint -set_exit_status $(shell go list ./... | grep -v vendor)
|
||||
gas ./...
|
||||
gosec ./...
|
||||
ginkgo -r -v
|
||||
bootstrap:
|
||||
dep ensure
|
||||
build:
|
||||
go build -o $(BIN) ./cmd/gas/
|
||||
go build -o $(BIN) ./cmd/gosec/
|
||||
clean:
|
||||
rm -rf build vendor
|
||||
rm -f release image bootstrap $(BIN)
|
||||
|
|
98
analyzer.go
98
analyzer.go
|
@ -12,8 +12,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package gas holds the central scanning logic used by GAS
|
||||
package gas
|
||||
// Package gosec holds the central scanning logic used by gosec security scanner
|
||||
package gosec
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
|
@ -55,7 +55,7 @@ type Metrics struct {
|
|||
NumFound int `json:"found"`
|
||||
}
|
||||
|
||||
// Analyzer object is the main object of GAS. It has methods traverse an AST
|
||||
// Analyzer object is the main object of gosec. It has methods traverse an AST
|
||||
// and invoke the correct checking rules as on each node as required.
|
||||
type Analyzer struct {
|
||||
ignoreNosec bool
|
||||
|
@ -74,7 +74,7 @@ func NewAnalyzer(conf Config, logger *log.Logger) *Analyzer {
|
|||
ignoreNoSec = setting == "true" || setting == "enabled"
|
||||
}
|
||||
if logger == nil {
|
||||
logger = log.New(os.Stderr, "[gas]", log.LstdFlags)
|
||||
logger = log.New(os.Stderr, "[gosec]", log.LstdFlags)
|
||||
}
|
||||
return &Analyzer{
|
||||
ignoreNosec: ignoreNoSec,
|
||||
|
@ -89,15 +89,15 @@ func NewAnalyzer(conf Config, logger *log.Logger) *Analyzer {
|
|||
|
||||
// LoadRules instantiates all the rules to be used when analyzing source
|
||||
// packages
|
||||
func (gas *Analyzer) LoadRules(ruleDefinitions map[string]RuleBuilder) {
|
||||
func (gosec *Analyzer) LoadRules(ruleDefinitions map[string]RuleBuilder) {
|
||||
for id, def := range ruleDefinitions {
|
||||
r, nodes := def(id, gas.config)
|
||||
gas.ruleset.Register(r, nodes...)
|
||||
r, nodes := def(id, gosec.config)
|
||||
gosec.ruleset.Register(r, nodes...)
|
||||
}
|
||||
}
|
||||
|
||||
// Process kicks off the analysis process for a given package
|
||||
func (gas *Analyzer) Process(buildTags []string, packagePaths ...string) error {
|
||||
func (gosec *Analyzer) Process(buildTags []string, packagePaths ...string) error {
|
||||
ctx := build.Default
|
||||
ctx.BuildTags = append(ctx.BuildTags, buildTags...)
|
||||
packageConfig := loader.Config{
|
||||
|
@ -111,10 +111,10 @@ func (gas *Analyzer) Process(buildTags []string, packagePaths ...string) error {
|
|||
return err
|
||||
}
|
||||
if _, err := os.Stat(abspath); os.IsNotExist(err) {
|
||||
gas.logger.Printf("Skipping: %s. Path doesn't exist.", abspath)
|
||||
gosec.logger.Printf("Skipping: %s. Path doesn't exist.", abspath)
|
||||
continue
|
||||
}
|
||||
gas.logger.Println("Searching directory:", abspath)
|
||||
gosec.logger.Println("Searching directory:", abspath)
|
||||
|
||||
basePackage, err := build.Default.ImportDir(packagePath, build.ImportComment)
|
||||
if err != nil {
|
||||
|
@ -135,31 +135,31 @@ func (gas *Analyzer) Process(buildTags []string, packagePaths ...string) error {
|
|||
}
|
||||
|
||||
for _, pkg := range builtPackage.Created {
|
||||
gas.logger.Println("Checking package:", pkg.String())
|
||||
gosec.logger.Println("Checking package:", pkg.String())
|
||||
for _, file := range pkg.Files {
|
||||
gas.logger.Println("Checking file:", builtPackage.Fset.File(file.Pos()).Name())
|
||||
gas.context.FileSet = builtPackage.Fset
|
||||
gas.context.Config = gas.config
|
||||
gas.context.Comments = ast.NewCommentMap(gas.context.FileSet, file, file.Comments)
|
||||
gas.context.Root = file
|
||||
gas.context.Info = &pkg.Info
|
||||
gas.context.Pkg = pkg.Pkg
|
||||
gas.context.Imports = NewImportTracker()
|
||||
gas.context.Imports.TrackPackages(gas.context.Pkg.Imports()...)
|
||||
ast.Walk(gas, file)
|
||||
gas.stats.NumFiles++
|
||||
gas.stats.NumLines += builtPackage.Fset.File(file.Pos()).LineCount()
|
||||
gosec.logger.Println("Checking file:", builtPackage.Fset.File(file.Pos()).Name())
|
||||
gosec.context.FileSet = builtPackage.Fset
|
||||
gosec.context.Config = gosec.config
|
||||
gosec.context.Comments = ast.NewCommentMap(gosec.context.FileSet, file, file.Comments)
|
||||
gosec.context.Root = file
|
||||
gosec.context.Info = &pkg.Info
|
||||
gosec.context.Pkg = pkg.Pkg
|
||||
gosec.context.Imports = NewImportTracker()
|
||||
gosec.context.Imports.TrackPackages(gosec.context.Pkg.Imports()...)
|
||||
ast.Walk(gosec, file)
|
||||
gosec.stats.NumFiles++
|
||||
gosec.stats.NumLines += builtPackage.Fset.File(file.Pos()).LineCount()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ignore a node (and sub-tree) if it is tagged with a "#nosec" comment
|
||||
func (gas *Analyzer) ignore(n ast.Node) ([]string, bool) {
|
||||
if groups, ok := gas.context.Comments[n]; ok && !gas.ignoreNosec {
|
||||
func (gosec *Analyzer) ignore(n ast.Node) ([]string, bool) {
|
||||
if groups, ok := gosec.context.Comments[n]; ok && !gosec.ignoreNosec {
|
||||
for _, group := range groups {
|
||||
if strings.Contains(group.Text(), "#nosec") {
|
||||
gas.stats.NumNosec++
|
||||
gosec.stats.NumNosec++
|
||||
|
||||
// Pull out the specific rules that are listed to be ignored.
|
||||
re := regexp.MustCompile("(G\\d{3})")
|
||||
|
@ -182,27 +182,27 @@ func (gas *Analyzer) ignore(n ast.Node) ([]string, bool) {
|
|||
return nil, false
|
||||
}
|
||||
|
||||
// Visit runs the GAS visitor logic over an AST created by parsing go code.
|
||||
// Visit runs the gosec visitor logic over an AST created by parsing go code.
|
||||
// Rule methods added with AddRule will be invoked as necessary.
|
||||
func (gas *Analyzer) Visit(n ast.Node) ast.Visitor {
|
||||
func (gosec *Analyzer) Visit(n ast.Node) ast.Visitor {
|
||||
// If we've reached the end of this branch, pop off the ignores stack.
|
||||
if n == nil {
|
||||
if len(gas.context.Ignores) > 0 {
|
||||
gas.context.Ignores = gas.context.Ignores[1:]
|
||||
if len(gosec.context.Ignores) > 0 {
|
||||
gosec.context.Ignores = gosec.context.Ignores[1:]
|
||||
}
|
||||
return gas
|
||||
return gosec
|
||||
}
|
||||
|
||||
// Get any new rule exclusions.
|
||||
ignoredRules, ignoreAll := gas.ignore(n)
|
||||
ignoredRules, ignoreAll := gosec.ignore(n)
|
||||
if ignoreAll {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Now create the union of exclusions.
|
||||
ignores := make(map[string]bool, 0)
|
||||
if len(gas.context.Ignores) > 0 {
|
||||
for k, v := range gas.context.Ignores[0] {
|
||||
if len(gosec.context.Ignores) > 0 {
|
||||
for k, v := range gosec.context.Ignores[0] {
|
||||
ignores[k] = v
|
||||
}
|
||||
}
|
||||
|
@ -212,37 +212,37 @@ func (gas *Analyzer) Visit(n ast.Node) ast.Visitor {
|
|||
}
|
||||
|
||||
// Push the new set onto the stack.
|
||||
gas.context.Ignores = append([]map[string]bool{ignores}, gas.context.Ignores...)
|
||||
gosec.context.Ignores = append([]map[string]bool{ignores}, gosec.context.Ignores...)
|
||||
|
||||
// Track aliased and initialization imports
|
||||
gas.context.Imports.TrackImport(n)
|
||||
gosec.context.Imports.TrackImport(n)
|
||||
|
||||
for _, rule := range gas.ruleset.RegisteredFor(n) {
|
||||
for _, rule := range gosec.ruleset.RegisteredFor(n) {
|
||||
if _, ok := ignores[rule.ID()]; ok {
|
||||
continue
|
||||
}
|
||||
issue, err := rule.Match(n, gas.context)
|
||||
issue, err := rule.Match(n, gosec.context)
|
||||
if err != nil {
|
||||
file, line := GetLocation(n, gas.context)
|
||||
file, line := GetLocation(n, gosec.context)
|
||||
file = path.Base(file)
|
||||
gas.logger.Printf("Rule error: %v => %s (%s:%d)\n", reflect.TypeOf(rule), err, file, line)
|
||||
gosec.logger.Printf("Rule error: %v => %s (%s:%d)\n", reflect.TypeOf(rule), err, file, line)
|
||||
}
|
||||
if issue != nil {
|
||||
gas.issues = append(gas.issues, issue)
|
||||
gas.stats.NumFound++
|
||||
gosec.issues = append(gosec.issues, issue)
|
||||
gosec.stats.NumFound++
|
||||
}
|
||||
}
|
||||
return gas
|
||||
return gosec
|
||||
}
|
||||
|
||||
// Report returns the current issues discovered and the metrics about the scan
|
||||
func (gas *Analyzer) Report() ([]*Issue, *Metrics) {
|
||||
return gas.issues, gas.stats
|
||||
func (gosec *Analyzer) Report() ([]*Issue, *Metrics) {
|
||||
return gosec.issues, gosec.stats
|
||||
}
|
||||
|
||||
// Reset clears state such as context, issues and metrics from the configured analyzer
|
||||
func (gas *Analyzer) Reset() {
|
||||
gas.context = &Context{}
|
||||
gas.issues = make([]*Issue, 0, 16)
|
||||
gas.stats = &Metrics{}
|
||||
func (gosec *Analyzer) Reset() {
|
||||
gosec.context = &Context{}
|
||||
gosec.issues = make([]*Issue, 0, 16)
|
||||
gosec.stats = &Metrics{}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package gas_test
|
||||
package gosec_test
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
|
@ -6,24 +6,24 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gas/rules"
|
||||
"github.com/securego/gosec"
|
||||
"github.com/securego/gosec/rules"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/securego/gas/testutils"
|
||||
"github.com/securego/gosec/testutils"
|
||||
)
|
||||
|
||||
var _ = Describe("Analyzer", func() {
|
||||
|
||||
var (
|
||||
analyzer *gas.Analyzer
|
||||
analyzer *gosec.Analyzer
|
||||
logger *log.Logger
|
||||
buildTags []string
|
||||
)
|
||||
BeforeEach(func() {
|
||||
logger, _ = testutils.NewLogger()
|
||||
analyzer = gas.NewAnalyzer(nil, logger)
|
||||
analyzer = gosec.NewAnalyzer(nil, logger)
|
||||
})
|
||||
|
||||
Context("when processing a package", func() {
|
||||
|
@ -200,9 +200,9 @@ var _ = Describe("Analyzer", func() {
|
|||
source := sample.Code
|
||||
|
||||
// overwrite nosec option
|
||||
nosecIgnoreConfig := gas.NewConfig()
|
||||
nosecIgnoreConfig := gosec.NewConfig()
|
||||
nosecIgnoreConfig.SetGlobal("nosec", "true")
|
||||
customAnalyzer := gas.NewAnalyzer(nosecIgnoreConfig, logger)
|
||||
customAnalyzer := gosec.NewAnalyzer(nosecIgnoreConfig, logger)
|
||||
customAnalyzer.LoadRules(rules.Generate(rules.NewRuleFilter(false, "G401")).Builders())
|
||||
|
||||
nosecPackage := testutils.NewTestPackage()
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package gas
|
||||
package gosec
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
package gas_test
|
||||
package gosec_test
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gas/testutils"
|
||||
"github.com/securego/gosec"
|
||||
"github.com/securego/gosec/testutils"
|
||||
)
|
||||
|
||||
var _ = Describe("call list", func() {
|
||||
var (
|
||||
calls gas.CallList
|
||||
calls gosec.CallList
|
||||
)
|
||||
BeforeEach(func() {
|
||||
calls = gas.NewCallList()
|
||||
calls = gosec.NewCallList()
|
||||
})
|
||||
|
||||
It("should not return any matches when empty", func() {
|
||||
|
@ -72,7 +72,7 @@ var _ = Describe("call list", func() {
|
|||
matched := 0
|
||||
v := testutils.NewMockVisitor()
|
||||
v.Context = ctx
|
||||
v.Callback = func(n ast.Node, ctx *gas.Context) bool {
|
||||
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
||||
if _, ok := n.(*ast.CallExpr); ok && calls.ContainsCallExpr(n, ctx) != nil {
|
||||
matched++
|
||||
}
|
||||
|
|
|
@ -28,16 +28,16 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/kisielk/gotool"
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gas/output"
|
||||
"github.com/securego/gas/rules"
|
||||
"github.com/securego/gosec"
|
||||
"github.com/securego/gosec/output"
|
||||
"github.com/securego/gosec/rules"
|
||||
)
|
||||
|
||||
const (
|
||||
usageText = `
|
||||
GAS - Go AST Scanner
|
||||
gosec - Golang security checker
|
||||
|
||||
Gas analyzes Go source code to look for common programming mistakes that
|
||||
gosec analyzes Go source code to look for common programming mistakes that
|
||||
can lead to security problems.
|
||||
|
||||
VERSION: %s
|
||||
|
@ -47,17 +47,17 @@ BUILD DATE: %s
|
|||
USAGE:
|
||||
|
||||
# Check a single package
|
||||
$ gas $GOPATH/src/github.com/example/project
|
||||
$ gosec $GOPATH/src/github.com/example/project
|
||||
|
||||
# Check all packages under the current directory and save results in
|
||||
# json format.
|
||||
$ gas -fmt=json -out=results.json ./...
|
||||
$ gosec -fmt=json -out=results.json ./...
|
||||
|
||||
# Run a specific set of rules (by default all rules will be run):
|
||||
$ gas -include=G101,G203,G401 ./...
|
||||
$ gosec -include=G101,G203,G401 ./...
|
||||
|
||||
# Run all rules except the provided
|
||||
$ gas -exclude=G101 $GOPATH/src/github.com/example/project/...
|
||||
$ gosec -exclude=G101 $GOPATH/src/github.com/example/project/...
|
||||
|
||||
`
|
||||
)
|
||||
|
@ -119,8 +119,8 @@ func usage() {
|
|||
fmt.Fprint(os.Stderr, "\n")
|
||||
}
|
||||
|
||||
func loadConfig(configFile string) (gas.Config, error) {
|
||||
config := gas.NewConfig()
|
||||
func loadConfig(configFile string) (gosec.Config, error) {
|
||||
config := gosec.NewConfig()
|
||||
if configFile != "" {
|
||||
// #nosec
|
||||
file, err := os.Open(configFile)
|
||||
|
@ -158,7 +158,7 @@ func loadRules(include, exclude string) rules.RuleList {
|
|||
return rules.Generate(filters...)
|
||||
}
|
||||
|
||||
func saveOutput(filename, format string, issues []*gas.Issue, metrics *gas.Metrics) error {
|
||||
func saveOutput(filename, format string, issues []*gosec.Issue, metrics *gosec.Metrics) error {
|
||||
if filename != "" {
|
||||
outfile, err := os.Create(filename)
|
||||
if err != nil {
|
||||
|
@ -283,7 +283,7 @@ func main() {
|
|||
if *flagQuiet {
|
||||
logger = log.New(ioutil.Discard, "", 0)
|
||||
} else {
|
||||
logger = log.New(logWriter, "[gas] ", log.LstdFlags)
|
||||
logger = log.New(logWriter, "[gosec] ", log.LstdFlags)
|
||||
}
|
||||
|
||||
// Load config
|
||||
|
@ -299,7 +299,7 @@ func main() {
|
|||
}
|
||||
|
||||
// Create the analyzer
|
||||
analyzer := gas.NewAnalyzer(config, logger)
|
||||
analyzer := gosec.NewAnalyzer(config, logger)
|
||||
analyzer.LoadRules(ruleDefinitions.Builders())
|
||||
|
||||
vendor := regexp.MustCompile(`[\\/]vendor([\\/]|$)`)
|
|
@ -3,10 +3,10 @@ package main
|
|||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
type sortBySeverity []*gas.Issue
|
||||
type sortBySeverity []*gosec.Issue
|
||||
|
||||
func (s sortBySeverity) Len() int { return len(s) }
|
||||
|
||||
|
@ -15,6 +15,6 @@ func (s sortBySeverity) Less(i, j int) bool { return s[i].Severity > s[i].Severi
|
|||
func (s sortBySeverity) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
// sortIssues sorts the issues by severity in descending order
|
||||
func sortIssues(issues []*gas.Issue) {
|
||||
func sortIssues(issues []*gosec.Issue) {
|
||||
sort.Sort(sortBySeverity(issues))
|
||||
}
|
|
@ -8,6 +8,6 @@ package {{.}}
|
|||
import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
`))
|
||||
|
|
|
@ -5,9 +5,9 @@ import "text/template"
|
|||
var generatedRuleTmpl = template.Must(template.New("generated").Parse(`
|
||||
// New{{.Name}}TLSCheck creates a check for {{.Name}} TLS ciphers
|
||||
// DO NOT EDIT - generated by tlsconfig tool
|
||||
func New{{.Name}}TLSCheck(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
func New{{.Name}}TLSCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return &insecureConfigTLS{
|
||||
MetaData: gas.MetaData{ID: id},
|
||||
MetaData: gosec.MetaData{ID: id},
|
||||
requiredType: "crypto/tls.Config",
|
||||
MinVersion: {{ .MinVersion }},
|
||||
MaxVersion: {{ .MaxVersion }},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package gas
|
||||
package gosec
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -10,7 +10,7 @@ import (
|
|||
|
||||
const (
|
||||
// Globals are applicable to all rules and used for general
|
||||
// configuration settings for gas.
|
||||
// configuration settings for gosec.
|
||||
Globals = "global"
|
||||
)
|
||||
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
package gas_test
|
||||
package gosec_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
var _ = Describe("Configuration", func() {
|
||||
var configuration gas.Config
|
||||
var configuration gosec.Config
|
||||
BeforeEach(func() {
|
||||
configuration = gas.NewConfig()
|
||||
configuration = gosec.NewConfig()
|
||||
})
|
||||
|
||||
Context("when loading from disk", func() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package gas_test
|
||||
package gosec_test
|
||||
|
||||
import (
|
||||
. "github.com/onsi/ginkgo"
|
||||
|
@ -7,7 +7,7 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
func TestGas(t *testing.T) {
|
||||
func TestGosec(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
RunSpecs(t, "Gas Suite")
|
||||
RunSpecs(t, "gosec Suite")
|
||||
}
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package gas
|
||||
package gosec
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package gas_test
|
||||
package gosec_test
|
||||
|
||||
import (
|
||||
. "github.com/onsi/ginkgo"
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package gas
|
||||
package gosec
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
|
|
6
issue.go
6
issue.go
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package gas
|
||||
package gosec
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
@ -34,7 +34,7 @@ const (
|
|||
High
|
||||
)
|
||||
|
||||
// Issue is returnd by a GAS rule if it discovers an issue with the scanned code.
|
||||
// Issue is returnd by a gosec rule if it discovers an issue with the scanned code.
|
||||
type Issue struct {
|
||||
Severity Score `json:"severity"` // issue severity (how problematic it is)
|
||||
Confidence Score `json:"confidence"` // issue confidence (how sure we are we found it)
|
||||
|
@ -45,7 +45,7 @@ type Issue struct {
|
|||
Line string `json:"line"` // Line number in file
|
||||
}
|
||||
|
||||
// MetaData is embedded in all GAS rules. The Severity, Confidence and What message
|
||||
// MetaData is embedded in all gosec rules. The Severity, Confidence and What message
|
||||
// will be passed tbhrough to reported issues.
|
||||
type MetaData struct {
|
||||
ID string
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package gas_test
|
||||
package gosec_test
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gas/rules"
|
||||
"github.com/securego/gas/testutils"
|
||||
"github.com/securego/gosec"
|
||||
"github.com/securego/gosec/rules"
|
||||
"github.com/securego/gosec/testutils"
|
||||
)
|
||||
|
||||
var _ = Describe("Issue", func() {
|
||||
|
@ -26,7 +26,7 @@ var _ = Describe("Issue", func() {
|
|||
pkg.AddFile("foo.go", source)
|
||||
ctx := pkg.CreateContext("foo.go")
|
||||
v := testutils.NewMockVisitor()
|
||||
v.Callback = func(n ast.Node, ctx *gas.Context) bool {
|
||||
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
||||
if node, ok := n.(*ast.BasicLit); ok {
|
||||
target = node
|
||||
return false
|
||||
|
@ -37,7 +37,7 @@ var _ = Describe("Issue", func() {
|
|||
ast.Walk(v, ctx.Root)
|
||||
Expect(target).ShouldNot(BeNil())
|
||||
|
||||
issue := gas.NewIssue(ctx, target, "TEST", "", gas.High, gas.High)
|
||||
issue := gosec.NewIssue(ctx, target, "TEST", "", gosec.High, gosec.High)
|
||||
Expect(issue).ShouldNot(BeNil())
|
||||
Expect(issue.Code).Should(MatchRegexp(`"bar"`))
|
||||
Expect(issue.Line).Should(Equal("2"))
|
||||
|
@ -58,7 +58,7 @@ var _ = Describe("Issue", func() {
|
|||
source := `package main
|
||||
import "os"
|
||||
func main(){`
|
||||
source += "q := `SELECT * FROM table WHERE` + \n os.Args[1] + `= ?` // nolint: gas\n"
|
||||
source += "q := `SELECT * FROM table WHERE` + \n os.Args[1] + `= ?` // nolint: gosec\n"
|
||||
source += `println(q)}`
|
||||
|
||||
pkg := testutils.NewTestPackage()
|
||||
|
@ -66,7 +66,7 @@ var _ = Describe("Issue", func() {
|
|||
pkg.AddFile("foo.go", source)
|
||||
ctx := pkg.CreateContext("foo.go")
|
||||
v := testutils.NewMockVisitor()
|
||||
v.Callback = func(n ast.Node, ctx *gas.Context) bool {
|
||||
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
||||
if node, ok := n.(*ast.BinaryExpr); ok {
|
||||
target = node
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ var _ = Describe("Issue", func() {
|
|||
Expect(target).ShouldNot(BeNil())
|
||||
|
||||
// Use SQL rule to check binary expr
|
||||
cfg := gas.NewConfig()
|
||||
cfg := gosec.NewConfig()
|
||||
rule, _ := rules.NewSQLStrConcat("TEST", cfg)
|
||||
issue, err := rule.Match(target, ctx)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
|
|
@ -22,7 +22,7 @@ import (
|
|||
"io"
|
||||
plainTemplate "text/template"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
|
@ -58,13 +58,13 @@ Summary:
|
|||
`
|
||||
|
||||
type reportInfo struct {
|
||||
Issues []*gas.Issue
|
||||
Stats *gas.Metrics
|
||||
Issues []*gosec.Issue
|
||||
Stats *gosec.Metrics
|
||||
}
|
||||
|
||||
// CreateReport generates a report based for the supplied issues and metrics given
|
||||
// the specified format. The formats currently accepted are: json, csv, html and text.
|
||||
func CreateReport(w io.Writer, format string, issues []*gas.Issue, metrics *gas.Metrics) error {
|
||||
func CreateReport(w io.Writer, format string, issues []*gosec.Issue, metrics *gosec.Metrics) error {
|
||||
data := &reportInfo{
|
||||
Issues: issues,
|
||||
Stats: metrics,
|
||||
|
@ -150,7 +150,7 @@ func reportJUnitXML(w io.Writer, data *reportInfo) error {
|
|||
}
|
||||
|
||||
func reportFromPlaintextTemplate(w io.Writer, reportTemplate string, data *reportInfo) error {
|
||||
t, e := plainTemplate.New("gas").Parse(reportTemplate)
|
||||
t, e := plainTemplate.New("gosec").Parse(reportTemplate)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ func reportFromPlaintextTemplate(w io.Writer, reportTemplate string, data *repor
|
|||
}
|
||||
|
||||
func reportFromHTMLTemplate(w io.Writer, reportTemplate string, data *reportInfo) error {
|
||||
t, e := htmlTemplate.New("gas").Parse(reportTemplate)
|
||||
t, e := htmlTemplate.New("gosec").Parse(reportTemplate)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
htmlLib "html"
|
||||
"strconv"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
type junitXMLReport struct {
|
||||
|
@ -32,26 +32,26 @@ type failure struct {
|
|||
Text string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
func generatePlaintext(issue *gas.Issue) string {
|
||||
func generatePlaintext(issue *gosec.Issue) string {
|
||||
return "Results:\n" +
|
||||
"[" + issue.File + ":" + issue.Line + "] - " +
|
||||
issue.What + " (Confidence: " + strconv.Itoa(int(issue.Confidence)) +
|
||||
", Severity: " + strconv.Itoa(int(issue.Severity)) + ")\n" + "> " + htmlLib.EscapeString(issue.Code)
|
||||
}
|
||||
|
||||
func groupDataByRules(data *reportInfo) map[string][]*gas.Issue {
|
||||
groupedData := make(map[string][]*gas.Issue)
|
||||
func groupDataByRules(data *reportInfo) map[string][]*gosec.Issue {
|
||||
groupedData := make(map[string][]*gosec.Issue)
|
||||
for _, issue := range data.Issues {
|
||||
if _, ok := groupedData[issue.What]; ok {
|
||||
groupedData[issue.What] = append(groupedData[issue.What], issue)
|
||||
} else {
|
||||
groupedData[issue.What] = []*gas.Issue{issue}
|
||||
groupedData[issue.What] = []*gosec.Issue{issue}
|
||||
}
|
||||
}
|
||||
return groupedData
|
||||
}
|
||||
|
||||
func createJUnitXMLStruct(groupedData map[string][]*gas.Issue) junitXMLReport {
|
||||
func createJUnitXMLStruct(groupedData map[string][]*gosec.Issue) junitXMLReport {
|
||||
var xmlReport junitXMLReport
|
||||
for what, issues := range groupedData {
|
||||
testsuite := testsuite{
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package gas
|
||||
package gosec
|
||||
|
||||
import "go/ast"
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package gas_test
|
||||
package gosec_test
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gas/testutils"
|
||||
"github.com/securego/gosec"
|
||||
"github.com/securego/gosec/testutils"
|
||||
)
|
||||
|
||||
var _ = Describe("Resolve ast node to concrete value", func() {
|
||||
|
@ -19,7 +19,7 @@ var _ = Describe("Resolve ast node to concrete value", func() {
|
|||
pkg.AddFile("foo.go", `package main; const foo = "bar"; func main(){}`)
|
||||
ctx := pkg.CreateContext("foo.go")
|
||||
v := testutils.NewMockVisitor()
|
||||
v.Callback = func(n ast.Node, ctx *gas.Context) bool {
|
||||
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
||||
if node, ok := n.(*ast.BasicLit); ok {
|
||||
basicLiteral = node
|
||||
return false
|
||||
|
@ -29,7 +29,7 @@ var _ = Describe("Resolve ast node to concrete value", func() {
|
|||
v.Context = ctx
|
||||
ast.Walk(v, ctx.Root)
|
||||
Expect(basicLiteral).ShouldNot(BeNil())
|
||||
Expect(gas.TryResolve(basicLiteral, ctx)).Should(BeTrue())
|
||||
Expect(gosec.TryResolve(basicLiteral, ctx)).Should(BeTrue())
|
||||
})
|
||||
|
||||
It("should successfully resolve identifier", func() {
|
||||
|
@ -39,7 +39,7 @@ var _ = Describe("Resolve ast node to concrete value", func() {
|
|||
pkg.AddFile("foo.go", `package main; var foo string = "bar"; func main(){}`)
|
||||
ctx := pkg.CreateContext("foo.go")
|
||||
v := testutils.NewMockVisitor()
|
||||
v.Callback = func(n ast.Node, ctx *gas.Context) bool {
|
||||
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
||||
if node, ok := n.(*ast.Ident); ok {
|
||||
ident = node
|
||||
return false
|
||||
|
@ -49,7 +49,7 @@ var _ = Describe("Resolve ast node to concrete value", func() {
|
|||
v.Context = ctx
|
||||
ast.Walk(v, ctx.Root)
|
||||
Expect(ident).ShouldNot(BeNil())
|
||||
Expect(gas.TryResolve(ident, ctx)).Should(BeTrue())
|
||||
Expect(gosec.TryResolve(ident, ctx)).Should(BeTrue())
|
||||
})
|
||||
|
||||
It("should successfully resolve assign statement", func() {
|
||||
|
@ -59,7 +59,7 @@ var _ = Describe("Resolve ast node to concrete value", func() {
|
|||
pkg.AddFile("foo.go", `package main; const x = "bar"; func main(){ y := x; println(y) }`)
|
||||
ctx := pkg.CreateContext("foo.go")
|
||||
v := testutils.NewMockVisitor()
|
||||
v.Callback = func(n ast.Node, ctx *gas.Context) bool {
|
||||
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
||||
if node, ok := n.(*ast.AssignStmt); ok {
|
||||
if id, ok := node.Lhs[0].(*ast.Ident); ok && id.Name == "y" {
|
||||
assign = node
|
||||
|
@ -70,7 +70,7 @@ var _ = Describe("Resolve ast node to concrete value", func() {
|
|||
v.Context = ctx
|
||||
ast.Walk(v, ctx.Root)
|
||||
Expect(assign).ShouldNot(BeNil())
|
||||
Expect(gas.TryResolve(assign, ctx)).Should(BeTrue())
|
||||
Expect(gosec.TryResolve(assign, ctx)).Should(BeTrue())
|
||||
})
|
||||
|
||||
It("should successfully resolve a binary statement", func() {
|
||||
|
@ -80,7 +80,7 @@ var _ = Describe("Resolve ast node to concrete value", func() {
|
|||
pkg.AddFile("foo.go", `package main; const (x = "bar"; y = "baz"); func main(){ z := x + y; println(z) }`)
|
||||
ctx := pkg.CreateContext("foo.go")
|
||||
v := testutils.NewMockVisitor()
|
||||
v.Callback = func(n ast.Node, ctx *gas.Context) bool {
|
||||
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
||||
if node, ok := n.(*ast.BinaryExpr); ok {
|
||||
target = node
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ var _ = Describe("Resolve ast node to concrete value", func() {
|
|||
v.Context = ctx
|
||||
ast.Walk(v, ctx.Root)
|
||||
Expect(target).ShouldNot(BeNil())
|
||||
Expect(gas.TryResolve(target, ctx)).Should(BeTrue())
|
||||
Expect(gosec.TryResolve(target, ctx)).Should(BeTrue())
|
||||
})
|
||||
|
||||
// TODO: It should resolve call expressions
|
||||
|
|
4
rule.go
4
rule.go
|
@ -10,14 +10,14 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package gas
|
||||
package gosec
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// The Rule interface used by all rules supported by GAS.
|
||||
// The Rule interface used by all rules supported by gosec.
|
||||
type Rule interface {
|
||||
ID() string
|
||||
Match(ast.Node, *Context) (*Issue, error)
|
||||
|
|
28
rule_test.go
28
rule_test.go
|
@ -1,4 +1,4 @@
|
|||
package gas_test
|
||||
package gosec_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -6,20 +6,20 @@ import (
|
|||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
type mockrule struct {
|
||||
issue *gas.Issue
|
||||
issue *gosec.Issue
|
||||
err error
|
||||
callback func(n ast.Node, ctx *gas.Context) bool
|
||||
callback func(n ast.Node, ctx *gosec.Context) bool
|
||||
}
|
||||
|
||||
func (m *mockrule) ID() string {
|
||||
return "MOCK"
|
||||
}
|
||||
|
||||
func (m *mockrule) Match(n ast.Node, ctx *gas.Context) (*gas.Issue, error) {
|
||||
func (m *mockrule) Match(n ast.Node, ctx *gosec.Context) (*gosec.Issue, error) {
|
||||
if m.callback(n, ctx) {
|
||||
return m.issue, nil
|
||||
}
|
||||
|
@ -31,29 +31,29 @@ var _ = Describe("Rule", func() {
|
|||
Context("when using a ruleset", func() {
|
||||
|
||||
var (
|
||||
ruleset gas.RuleSet
|
||||
dummyErrorRule gas.Rule
|
||||
dummyIssueRule gas.Rule
|
||||
ruleset gosec.RuleSet
|
||||
dummyErrorRule gosec.Rule
|
||||
dummyIssueRule gosec.Rule
|
||||
)
|
||||
|
||||
JustBeforeEach(func() {
|
||||
ruleset = gas.NewRuleSet()
|
||||
ruleset = gosec.NewRuleSet()
|
||||
dummyErrorRule = &mockrule{
|
||||
issue: nil,
|
||||
err: fmt.Errorf("An unexpected error occurred"),
|
||||
callback: func(n ast.Node, ctx *gas.Context) bool { return false },
|
||||
callback: func(n ast.Node, ctx *gosec.Context) bool { return false },
|
||||
}
|
||||
dummyIssueRule = &mockrule{
|
||||
issue: &gas.Issue{
|
||||
Severity: gas.High,
|
||||
Confidence: gas.High,
|
||||
issue: &gosec.Issue{
|
||||
Severity: gosec.High,
|
||||
Confidence: gosec.High,
|
||||
What: `Some explanation of the thing`,
|
||||
File: "main.go",
|
||||
Code: `#include <stdio.h> int main(){ puts("hello world"); }`,
|
||||
Line: "42",
|
||||
},
|
||||
err: nil,
|
||||
callback: func(n ast.Node, ctx *gas.Context) bool { return true },
|
||||
callback: func(n ast.Node, ctx *gosec.Context) bool { return true },
|
||||
}
|
||||
})
|
||||
It("should be possible to register a rule for multiple ast.Node", func() {
|
||||
|
|
|
@ -4,12 +4,12 @@ import (
|
|||
"go/ast"
|
||||
"go/types"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
type archive struct {
|
||||
gas.MetaData
|
||||
calls gas.CallList
|
||||
gosec.MetaData
|
||||
calls gosec.CallList
|
||||
argType string
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ func (a *archive) ID() string {
|
|||
}
|
||||
|
||||
// Match inspects AST nodes to determine if the filepath.Joins uses any argument derived from type zip.File
|
||||
func (a *archive) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
func (a *archive) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
if node := a.calls.ContainsCallExpr(n, c); node != nil {
|
||||
for _, arg := range node.Args {
|
||||
var argType types.Type
|
||||
|
@ -36,7 +36,7 @@ func (a *archive) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
|||
}
|
||||
|
||||
if argType != nil && argType.String() == a.argType {
|
||||
return gas.NewIssue(c, n, a.ID(), a.What, a.Severity, a.Confidence), nil
|
||||
return gosec.NewIssue(c, n, a.ID(), a.What, a.Severity, a.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,16 +44,16 @@ func (a *archive) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
|||
}
|
||||
|
||||
// NewArchive creates a new rule which detects the file traversal when extracting zip archives
|
||||
func NewArchive(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
calls := gas.NewCallList()
|
||||
func NewArchive(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
calls := gosec.NewCallList()
|
||||
calls.Add("path/filepath", "Join")
|
||||
return &archive{
|
||||
calls: calls,
|
||||
argType: "*archive/zip.File",
|
||||
MetaData: gas.MetaData{
|
||||
MetaData: gosec.MetaData{
|
||||
ID: id,
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.High,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
What: "File traversal when extracting zip archive",
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
|
|
18
rules/big.go
18
rules/big.go
|
@ -17,11 +17,11 @@ package rules
|
|||
import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
type usingBigExp struct {
|
||||
gas.MetaData
|
||||
gosec.MetaData
|
||||
pkg string
|
||||
calls []string
|
||||
}
|
||||
|
@ -30,23 +30,23 @@ func (r *usingBigExp) ID() string {
|
|||
return r.MetaData.ID
|
||||
}
|
||||
|
||||
func (r *usingBigExp) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err error) {
|
||||
if _, matched := gas.MatchCallByType(n, c, r.pkg, r.calls...); matched {
|
||||
return gas.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
func (r *usingBigExp) Match(n ast.Node, c *gosec.Context) (gi *gosec.Issue, err error) {
|
||||
if _, matched := gosec.MatchCallByType(n, c, r.pkg, r.calls...); matched {
|
||||
return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewUsingBigExp detects issues with modulus == 0 for Bignum
|
||||
func NewUsingBigExp(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
func NewUsingBigExp(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return &usingBigExp{
|
||||
pkg: "*math/big.Int",
|
||||
calls: []string{"Exp"},
|
||||
MetaData: gas.MetaData{
|
||||
MetaData: gosec.MetaData{
|
||||
ID: id,
|
||||
What: "Use of math/big.Int.Exp function should be audited for modulus == 0",
|
||||
Severity: gas.Low,
|
||||
Confidence: gas.High,
|
||||
Severity: gosec.Low,
|
||||
Confidence: gosec.High,
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
}
|
||||
|
|
|
@ -18,13 +18,13 @@ import (
|
|||
"go/ast"
|
||||
"regexp"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
// Looks for net.Listen("0.0.0.0") or net.Listen(":8080")
|
||||
type bindsToAllNetworkInterfaces struct {
|
||||
gas.MetaData
|
||||
calls gas.CallList
|
||||
gosec.MetaData
|
||||
calls gosec.CallList
|
||||
pattern *regexp.Regexp
|
||||
}
|
||||
|
||||
|
@ -32,14 +32,14 @@ func (r *bindsToAllNetworkInterfaces) ID() string {
|
|||
return r.MetaData.ID
|
||||
}
|
||||
|
||||
func (r *bindsToAllNetworkInterfaces) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
func (r *bindsToAllNetworkInterfaces) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
callExpr := r.calls.ContainsCallExpr(n, c)
|
||||
if callExpr == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if arg, err := gas.GetString(callExpr.Args[1]); err == nil {
|
||||
if arg, err := gosec.GetString(callExpr.Args[1]); err == nil {
|
||||
if r.pattern.MatchString(arg) {
|
||||
return gas.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
|
@ -47,17 +47,17 @@ func (r *bindsToAllNetworkInterfaces) Match(n ast.Node, c *gas.Context) (*gas.Is
|
|||
|
||||
// NewBindsToAllNetworkInterfaces detects socket connections that are setup to
|
||||
// listen on all network interfaces.
|
||||
func NewBindsToAllNetworkInterfaces(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
calls := gas.NewCallList()
|
||||
func NewBindsToAllNetworkInterfaces(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
calls := gosec.NewCallList()
|
||||
calls.Add("net", "Listen")
|
||||
calls.Add("crypto/tls", "Listen")
|
||||
return &bindsToAllNetworkInterfaces{
|
||||
calls: calls,
|
||||
pattern: regexp.MustCompile(`^(0.0.0.0|:).*$`),
|
||||
MetaData: gas.MetaData{
|
||||
MetaData: gosec.MetaData{
|
||||
ID: id,
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.High,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
What: "Binds to all network interfaces",
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
|
|
|
@ -18,11 +18,11 @@ import (
|
|||
"go/ast"
|
||||
"strings"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
type blacklistedImport struct {
|
||||
gas.MetaData
|
||||
gosec.MetaData
|
||||
Blacklisted map[string]string
|
||||
}
|
||||
|
||||
|
@ -36,10 +36,10 @@ func (r *blacklistedImport) ID() string {
|
|||
return r.MetaData.ID
|
||||
}
|
||||
|
||||
func (r *blacklistedImport) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
func (r *blacklistedImport) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
if node, ok := n.(*ast.ImportSpec); ok {
|
||||
if description, ok := r.Blacklisted[unquote(node.Path.Value)]; ok {
|
||||
return gas.NewIssue(c, node, r.ID(), description, r.Severity, r.Confidence), nil
|
||||
return gosec.NewIssue(c, node, r.ID(), description, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
|
@ -47,40 +47,40 @@ func (r *blacklistedImport) Match(n ast.Node, c *gas.Context) (*gas.Issue, error
|
|||
|
||||
// NewBlacklistedImports reports when a blacklisted import is being used.
|
||||
// Typically when a deprecated technology is being used.
|
||||
func NewBlacklistedImports(id string, conf gas.Config, blacklist map[string]string) (gas.Rule, []ast.Node) {
|
||||
func NewBlacklistedImports(id string, conf gosec.Config, blacklist map[string]string) (gosec.Rule, []ast.Node) {
|
||||
return &blacklistedImport{
|
||||
MetaData: gas.MetaData{
|
||||
MetaData: gosec.MetaData{
|
||||
ID: id,
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.High,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
},
|
||||
Blacklisted: blacklist,
|
||||
}, []ast.Node{(*ast.ImportSpec)(nil)}
|
||||
}
|
||||
|
||||
// NewBlacklistedImportMD5 fails if MD5 is imported
|
||||
func NewBlacklistedImportMD5(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
func NewBlacklistedImportMD5(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return NewBlacklistedImports(id, conf, map[string]string{
|
||||
"crypto/md5": "Blacklisted import crypto/md5: weak cryptographic primitive",
|
||||
})
|
||||
}
|
||||
|
||||
// NewBlacklistedImportDES fails if DES is imported
|
||||
func NewBlacklistedImportDES(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
func NewBlacklistedImportDES(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return NewBlacklistedImports(id, conf, map[string]string{
|
||||
"crypto/des": "Blacklisted import crypto/des: weak cryptographic primitive",
|
||||
})
|
||||
}
|
||||
|
||||
// NewBlacklistedImportRC4 fails if DES is imported
|
||||
func NewBlacklistedImportRC4(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
func NewBlacklistedImportRC4(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return NewBlacklistedImports(id, conf, map[string]string{
|
||||
"crypto/rc4": "Blacklisted import crypto/rc4: weak cryptographic primitive",
|
||||
})
|
||||
}
|
||||
|
||||
// NewBlacklistedImportCGI fails if CGI is imported
|
||||
func NewBlacklistedImportCGI(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
func NewBlacklistedImportCGI(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return NewBlacklistedImports(id, conf, map[string]string{
|
||||
"net/http/cgi": "Blacklisted import net/http/cgi: Go versions < 1.6.3 are vulnerable to Httpoxy attack: (CVE-2016-5386)",
|
||||
})
|
||||
|
|
|
@ -18,19 +18,19 @@ import (
|
|||
"go/ast"
|
||||
"go/types"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
type noErrorCheck struct {
|
||||
gas.MetaData
|
||||
whitelist gas.CallList
|
||||
gosec.MetaData
|
||||
whitelist gosec.CallList
|
||||
}
|
||||
|
||||
func (r *noErrorCheck) ID() string {
|
||||
return r.MetaData.ID
|
||||
}
|
||||
|
||||
func returnsError(callExpr *ast.CallExpr, ctx *gas.Context) int {
|
||||
func returnsError(callExpr *ast.CallExpr, ctx *gosec.Context) int {
|
||||
if tv := ctx.Info.TypeOf(callExpr); tv != nil {
|
||||
switch t := tv.(type) {
|
||||
case *types.Tuple:
|
||||
|
@ -49,7 +49,7 @@ func returnsError(callExpr *ast.CallExpr, ctx *gas.Context) int {
|
|||
return -1
|
||||
}
|
||||
|
||||
func (r *noErrorCheck) Match(n ast.Node, ctx *gas.Context) (*gas.Issue, error) {
|
||||
func (r *noErrorCheck) Match(n ast.Node, ctx *gosec.Context) (*gosec.Issue, error) {
|
||||
switch stmt := n.(type) {
|
||||
case *ast.AssignStmt:
|
||||
for _, expr := range stmt.Rhs {
|
||||
|
@ -59,7 +59,7 @@ func (r *noErrorCheck) Match(n ast.Node, ctx *gas.Context) (*gas.Issue, error) {
|
|||
return nil, nil
|
||||
}
|
||||
if id, ok := stmt.Lhs[pos].(*ast.Ident); ok && id.Name == "_" {
|
||||
return gas.NewIssue(ctx, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
return gosec.NewIssue(ctx, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ func (r *noErrorCheck) Match(n ast.Node, ctx *gas.Context) (*gas.Issue, error) {
|
|||
if callExpr, ok := stmt.X.(*ast.CallExpr); ok && r.whitelist.ContainsCallExpr(stmt.X, ctx) == nil {
|
||||
pos := returnsError(callExpr, ctx)
|
||||
if pos >= 0 {
|
||||
return gas.NewIssue(ctx, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
return gosec.NewIssue(ctx, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -75,10 +75,10 @@ func (r *noErrorCheck) Match(n ast.Node, ctx *gas.Context) (*gas.Issue, error) {
|
|||
}
|
||||
|
||||
// NewNoErrorCheck detects if the returned error is unchecked
|
||||
func NewNoErrorCheck(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
func NewNoErrorCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
// TODO(gm) Come up with sensible defaults here. Or flip it to use a
|
||||
// black list instead.
|
||||
whitelist := gas.NewCallList()
|
||||
whitelist := gosec.NewCallList()
|
||||
whitelist.AddAll("bytes.Buffer", "Write", "WriteByte", "WriteRune", "WriteString")
|
||||
whitelist.AddAll("fmt", "Print", "Printf", "Println", "Fprint", "Fprintf", "Fprintln")
|
||||
whitelist.Add("io.PipeWriter", "CloseWithError")
|
||||
|
@ -91,10 +91,10 @@ func NewNoErrorCheck(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
|||
}
|
||||
}
|
||||
return &noErrorCheck{
|
||||
MetaData: gas.MetaData{
|
||||
MetaData: gosec.MetaData{
|
||||
ID: id,
|
||||
Severity: gas.Low,
|
||||
Confidence: gas.High,
|
||||
Severity: gosec.Low,
|
||||
Confidence: gosec.High,
|
||||
What: "Errors unhandled.",
|
||||
},
|
||||
whitelist: whitelist,
|
||||
|
|
|
@ -19,11 +19,11 @@ import (
|
|||
"go/ast"
|
||||
"strconv"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
type filePermissions struct {
|
||||
gas.MetaData
|
||||
gosec.MetaData
|
||||
mode int64
|
||||
pkg string
|
||||
calls []string
|
||||
|
@ -50,11 +50,11 @@ func getConfiguredMode(conf map[string]interface{}, configKey string, defaultMod
|
|||
return mode
|
||||
}
|
||||
|
||||
func (r *filePermissions) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
if callexpr, matched := gas.MatchCallByPackage(n, c, r.pkg, r.calls...); matched {
|
||||
func (r *filePermissions) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
if callexpr, matched := gosec.MatchCallByPackage(n, c, r.pkg, r.calls...); matched {
|
||||
modeArg := callexpr.Args[len(callexpr.Args)-1]
|
||||
if mode, err := gas.GetInt(modeArg); err == nil && mode > r.mode {
|
||||
return gas.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
if mode, err := gosec.GetInt(modeArg); err == nil && mode > r.mode {
|
||||
return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
|
@ -62,16 +62,16 @@ func (r *filePermissions) Match(n ast.Node, c *gas.Context) (*gas.Issue, error)
|
|||
|
||||
// NewFilePerms creates a rule to detect file creation with a more permissive than configured
|
||||
// permission mask.
|
||||
func NewFilePerms(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
func NewFilePerms(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
mode := getConfiguredMode(conf, "G302", 0600)
|
||||
return &filePermissions{
|
||||
mode: mode,
|
||||
pkg: "os",
|
||||
calls: []string{"OpenFile", "Chmod"},
|
||||
MetaData: gas.MetaData{
|
||||
MetaData: gosec.MetaData{
|
||||
ID: id,
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.High,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
What: fmt.Sprintf("Expect file permissions to be %#o or less", mode),
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
|
@ -79,16 +79,16 @@ func NewFilePerms(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
|||
|
||||
// NewMkdirPerms creates a rule to detect directory creation with more permissive than
|
||||
// configured permission mask.
|
||||
func NewMkdirPerms(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
func NewMkdirPerms(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
mode := getConfiguredMode(conf, "G301", 0750)
|
||||
return &filePermissions{
|
||||
mode: mode,
|
||||
pkg: "os",
|
||||
calls: []string{"Mkdir", "MkdirAll"},
|
||||
MetaData: gas.MetaData{
|
||||
MetaData: gosec.MetaData{
|
||||
ID: id,
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.High,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
What: fmt.Sprintf("Expect directory permissions to be %#o or less", mode),
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
|
|
|
@ -19,12 +19,12 @@ import (
|
|||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/nbutton23/zxcvbn-go"
|
||||
"github.com/securego/gas"
|
||||
zxcvbn "github.com/nbutton23/zxcvbn-go"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
type credentials struct {
|
||||
gas.MetaData
|
||||
gosec.MetaData
|
||||
pattern *regexp.Regexp
|
||||
entropyThreshold float64
|
||||
perCharThreshold float64
|
||||
|
@ -52,7 +52,7 @@ func (r *credentials) isHighEntropyString(str string) bool {
|
|||
entropyPerChar >= r.perCharThreshold))
|
||||
}
|
||||
|
||||
func (r *credentials) Match(n ast.Node, ctx *gas.Context) (*gas.Issue, error) {
|
||||
func (r *credentials) Match(n ast.Node, ctx *gosec.Context) (*gosec.Issue, error) {
|
||||
switch node := n.(type) {
|
||||
case *ast.AssignStmt:
|
||||
return r.matchAssign(node, ctx)
|
||||
|
@ -62,14 +62,14 @@ func (r *credentials) Match(n ast.Node, ctx *gas.Context) (*gas.Issue, error) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *credentials) matchAssign(assign *ast.AssignStmt, ctx *gas.Context) (*gas.Issue, error) {
|
||||
func (r *credentials) matchAssign(assign *ast.AssignStmt, ctx *gosec.Context) (*gosec.Issue, error) {
|
||||
for _, i := range assign.Lhs {
|
||||
if ident, ok := i.(*ast.Ident); ok {
|
||||
if r.pattern.MatchString(ident.Name) {
|
||||
for _, e := range assign.Rhs {
|
||||
if val, err := gas.GetString(e); err == nil {
|
||||
if val, err := gosec.GetString(e); err == nil {
|
||||
if r.ignoreEntropy || (!r.ignoreEntropy && r.isHighEntropyString(val)) {
|
||||
return gas.NewIssue(ctx, assign, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
return gosec.NewIssue(ctx, assign, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,16 +79,16 @@ func (r *credentials) matchAssign(assign *ast.AssignStmt, ctx *gas.Context) (*ga
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *credentials) matchValueSpec(valueSpec *ast.ValueSpec, ctx *gas.Context) (*gas.Issue, error) {
|
||||
func (r *credentials) matchValueSpec(valueSpec *ast.ValueSpec, ctx *gosec.Context) (*gosec.Issue, error) {
|
||||
for index, ident := range valueSpec.Names {
|
||||
if r.pattern.MatchString(ident.Name) && valueSpec.Values != nil {
|
||||
// const foo, bar = "same value"
|
||||
if len(valueSpec.Values) <= index {
|
||||
index = len(valueSpec.Values) - 1
|
||||
}
|
||||
if val, err := gas.GetString(valueSpec.Values[index]); err == nil {
|
||||
if val, err := gosec.GetString(valueSpec.Values[index]); err == nil {
|
||||
if r.ignoreEntropy || (!r.ignoreEntropy && r.isHighEntropyString(val)) {
|
||||
return gas.NewIssue(ctx, valueSpec, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
return gosec.NewIssue(ctx, valueSpec, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ func (r *credentials) matchValueSpec(valueSpec *ast.ValueSpec, ctx *gas.Context)
|
|||
|
||||
// NewHardcodedCredentials attempts to find high entropy string constants being
|
||||
// assigned to variables that appear to be related to credentials.
|
||||
func NewHardcodedCredentials(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
func NewHardcodedCredentials(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
pattern := `(?i)passwd|pass|password|pwd|secret|token`
|
||||
entropyThreshold := 80.0
|
||||
perCharThreshold := 3.0
|
||||
|
@ -137,11 +137,11 @@ func NewHardcodedCredentials(id string, conf gas.Config) (gas.Rule, []ast.Node)
|
|||
perCharThreshold: perCharThreshold,
|
||||
ignoreEntropy: ignoreEntropy,
|
||||
truncate: truncateString,
|
||||
MetaData: gas.MetaData{
|
||||
MetaData: gosec.MetaData{
|
||||
ID: id,
|
||||
What: "Potential hardcoded credentials",
|
||||
Confidence: gas.Low,
|
||||
Severity: gas.High,
|
||||
Confidence: gosec.Low,
|
||||
Severity: gosec.High,
|
||||
},
|
||||
}, []ast.Node{(*ast.AssignStmt)(nil), (*ast.ValueSpec)(nil)}
|
||||
}
|
||||
|
|
|
@ -17,11 +17,11 @@ package rules
|
|||
import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
type weakRand struct {
|
||||
gas.MetaData
|
||||
gosec.MetaData
|
||||
funcNames []string
|
||||
packagePath string
|
||||
}
|
||||
|
@ -30,10 +30,10 @@ func (w *weakRand) ID() string {
|
|||
return w.MetaData.ID
|
||||
}
|
||||
|
||||
func (w *weakRand) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
func (w *weakRand) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
for _, funcName := range w.funcNames {
|
||||
if _, matched := gas.MatchCallByPackage(n, c, w.packagePath, funcName); matched {
|
||||
return gas.NewIssue(c, n, w.ID(), w.What, w.Severity, w.Confidence), nil
|
||||
if _, matched := gosec.MatchCallByPackage(n, c, w.packagePath, funcName); matched {
|
||||
return gosec.NewIssue(c, n, w.ID(), w.What, w.Severity, w.Confidence), nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,14 +41,14 @@ func (w *weakRand) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
|||
}
|
||||
|
||||
// NewWeakRandCheck detects the use of random number generator that isn't cryptographically secure
|
||||
func NewWeakRandCheck(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
func NewWeakRandCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return &weakRand{
|
||||
funcNames: []string{"Read", "Int"},
|
||||
packagePath: "math/rand",
|
||||
MetaData: gas.MetaData{
|
||||
MetaData: gosec.MetaData{
|
||||
ID: id,
|
||||
Severity: gas.High,
|
||||
Confidence: gas.Medium,
|
||||
Severity: gosec.High,
|
||||
Confidence: gosec.Medium,
|
||||
What: "Use of weak random number generator (math/rand instead of crypto/rand)",
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
|
|
|
@ -18,12 +18,12 @@ import (
|
|||
"go/ast"
|
||||
"go/types"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
type readfile struct {
|
||||
gas.MetaData
|
||||
gas.CallList
|
||||
gosec.MetaData
|
||||
gosec.CallList
|
||||
}
|
||||
|
||||
// ID returns the identifier for this rule
|
||||
|
@ -32,13 +32,13 @@ func (r *readfile) ID() string {
|
|||
}
|
||||
|
||||
// Match inspects AST nodes to determine if the match the methods `os.Open` or `ioutil.ReadFile`
|
||||
func (r *readfile) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
func (r *readfile) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
if node := r.ContainsCallExpr(n, c); node != nil {
|
||||
for _, arg := range node.Args {
|
||||
if ident, ok := arg.(*ast.Ident); ok {
|
||||
obj := c.Info.ObjectOf(ident)
|
||||
if _, ok := obj.(*types.Var); ok && !gas.TryResolve(ident, c) {
|
||||
return gas.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
if _, ok := obj.(*types.Var); ok && !gosec.TryResolve(ident, c) {
|
||||
return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,14 +47,14 @@ func (r *readfile) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
|||
}
|
||||
|
||||
// NewReadFile detects cases where we read files
|
||||
func NewReadFile(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
func NewReadFile(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
rule := &readfile{
|
||||
CallList: gas.NewCallList(),
|
||||
MetaData: gas.MetaData{
|
||||
CallList: gosec.NewCallList(),
|
||||
MetaData: gosec.MetaData{
|
||||
ID: id,
|
||||
What: "Potential file inclusion via variable",
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.High,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
},
|
||||
}
|
||||
rule.Add("io/ioutil", "ReadFile")
|
||||
|
|
22
rules/rsa.go
22
rules/rsa.go
|
@ -18,12 +18,12 @@ import (
|
|||
"fmt"
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
type weakKeyStrength struct {
|
||||
gas.MetaData
|
||||
calls gas.CallList
|
||||
gosec.MetaData
|
||||
calls gosec.CallList
|
||||
bits int
|
||||
}
|
||||
|
||||
|
@ -31,27 +31,27 @@ func (w *weakKeyStrength) ID() string {
|
|||
return w.MetaData.ID
|
||||
}
|
||||
|
||||
func (w *weakKeyStrength) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
func (w *weakKeyStrength) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
if callExpr := w.calls.ContainsCallExpr(n, c); callExpr != nil {
|
||||
if bits, err := gas.GetInt(callExpr.Args[1]); err == nil && bits < (int64)(w.bits) {
|
||||
return gas.NewIssue(c, n, w.ID(), w.What, w.Severity, w.Confidence), nil
|
||||
if bits, err := gosec.GetInt(callExpr.Args[1]); err == nil && bits < (int64)(w.bits) {
|
||||
return gosec.NewIssue(c, n, w.ID(), w.What, w.Severity, w.Confidence), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewWeakKeyStrength builds a rule that detects RSA keys < 2048 bits
|
||||
func NewWeakKeyStrength(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
calls := gas.NewCallList()
|
||||
func NewWeakKeyStrength(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
calls := gosec.NewCallList()
|
||||
calls.Add("crypto/rsa", "GenerateKey")
|
||||
bits := 2048
|
||||
return &weakKeyStrength{
|
||||
calls: calls,
|
||||
bits: bits,
|
||||
MetaData: gas.MetaData{
|
||||
MetaData: gosec.MetaData{
|
||||
ID: id,
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.High,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
What: fmt.Sprintf("RSA keys should be at least %d bits", bits),
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
|
|
|
@ -14,24 +14,22 @@
|
|||
|
||||
package rules
|
||||
|
||||
import (
|
||||
"github.com/securego/gas"
|
||||
)
|
||||
import "github.com/securego/gosec"
|
||||
|
||||
// RuleDefinition contains the description of a rule and a mechanism to
|
||||
// create it.
|
||||
type RuleDefinition struct {
|
||||
ID string
|
||||
Description string
|
||||
Create gas.RuleBuilder
|
||||
Create gosec.RuleBuilder
|
||||
}
|
||||
|
||||
// RuleList is a mapping of rule ID's to rule definitions
|
||||
type RuleList map[string]RuleDefinition
|
||||
|
||||
// Builders returns all the create methods for a given rule list
|
||||
func (rl RuleList) Builders() map[string]gas.RuleBuilder {
|
||||
builders := make(map[string]gas.RuleBuilder)
|
||||
func (rl RuleList) Builders() map[string]gosec.RuleBuilder {
|
||||
builders := make(map[string]gosec.RuleBuilder)
|
||||
for _, def := range rl {
|
||||
builders[def.ID] = def.Create
|
||||
}
|
||||
|
|
|
@ -4,28 +4,27 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/securego/gas"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/securego/gas/rules"
|
||||
"github.com/securego/gas/testutils"
|
||||
"github.com/securego/gosec"
|
||||
"github.com/securego/gosec/rules"
|
||||
"github.com/securego/gosec/testutils"
|
||||
)
|
||||
|
||||
var _ = Describe("gas rules", func() {
|
||||
var _ = Describe("gosec rules", func() {
|
||||
|
||||
var (
|
||||
logger *log.Logger
|
||||
config gas.Config
|
||||
analyzer *gas.Analyzer
|
||||
config gosec.Config
|
||||
analyzer *gosec.Analyzer
|
||||
runner func(string, []testutils.CodeSample)
|
||||
buildTags []string
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
logger, _ = testutils.NewLogger()
|
||||
config = gas.NewConfig()
|
||||
analyzer = gas.NewAnalyzer(config, logger)
|
||||
config = gosec.NewConfig()
|
||||
analyzer = gosec.NewAnalyzer(config, logger)
|
||||
runner = func(rule string, samples []testutils.CodeSample) {
|
||||
analyzer.LoadRules(rules.Generate(rules.NewRuleFilter(false, rule)).Builders())
|
||||
for n, sample := range samples {
|
||||
|
|
36
rules/sql.go
36
rules/sql.go
|
@ -18,11 +18,11 @@ import (
|
|||
"go/ast"
|
||||
"regexp"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
type sqlStatement struct {
|
||||
gas.MetaData
|
||||
gosec.MetaData
|
||||
|
||||
// Contains a list of patterns which must all match for the rule to match.
|
||||
patterns []*regexp.Regexp
|
||||
|
@ -59,10 +59,10 @@ func (s *sqlStrConcat) checkObject(n *ast.Ident) bool {
|
|||
}
|
||||
|
||||
// Look for "SELECT * FROM table WHERE " + " ' OR 1=1"
|
||||
func (s *sqlStrConcat) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
func (s *sqlStrConcat) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
if node, ok := n.(*ast.BinaryExpr); ok {
|
||||
if start, ok := node.X.(*ast.BasicLit); ok {
|
||||
if str, e := gas.GetString(start); e == nil {
|
||||
if str, e := gosec.GetString(start); e == nil {
|
||||
if !s.MatchPatterns(str) {
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ func (s *sqlStrConcat) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
|||
if second, ok := node.Y.(*ast.Ident); ok && s.checkObject(second) {
|
||||
return nil, nil
|
||||
}
|
||||
return gas.NewIssue(c, n, s.ID(), s.What, s.Severity, s.Confidence), nil
|
||||
return gosec.NewIssue(c, n, s.ID(), s.What, s.Severity, s.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -80,16 +80,16 @@ func (s *sqlStrConcat) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
|||
}
|
||||
|
||||
// NewSQLStrConcat looks for cases where we are building SQL strings via concatenation
|
||||
func NewSQLStrConcat(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
func NewSQLStrConcat(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return &sqlStrConcat{
|
||||
sqlStatement: sqlStatement{
|
||||
patterns: []*regexp.Regexp{
|
||||
regexp.MustCompile(`(?)(SELECT|DELETE|INSERT|UPDATE|INTO|FROM|WHERE) `),
|
||||
},
|
||||
MetaData: gas.MetaData{
|
||||
MetaData: gosec.MetaData{
|
||||
ID: id,
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.High,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
What: "SQL string concatenation",
|
||||
},
|
||||
},
|
||||
|
@ -98,34 +98,34 @@ func NewSQLStrConcat(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
|||
|
||||
type sqlStrFormat struct {
|
||||
sqlStatement
|
||||
calls gas.CallList
|
||||
calls gosec.CallList
|
||||
}
|
||||
|
||||
// Looks for "fmt.Sprintf("SELECT * FROM foo where '%s', userInput)"
|
||||
func (s *sqlStrFormat) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
func (s *sqlStrFormat) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
|
||||
// TODO(gm) improve confidence if database/sql is being used
|
||||
if node := s.calls.ContainsCallExpr(n, c); node != nil {
|
||||
if arg, e := gas.GetString(node.Args[0]); s.MatchPatterns(arg) && e == nil {
|
||||
return gas.NewIssue(c, n, s.ID(), s.What, s.Severity, s.Confidence), nil
|
||||
if arg, e := gosec.GetString(node.Args[0]); s.MatchPatterns(arg) && e == nil {
|
||||
return gosec.NewIssue(c, n, s.ID(), s.What, s.Severity, s.Confidence), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewSQLStrFormat looks for cases where we're building SQL query strings using format strings
|
||||
func NewSQLStrFormat(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
func NewSQLStrFormat(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
rule := &sqlStrFormat{
|
||||
calls: gas.NewCallList(),
|
||||
calls: gosec.NewCallList(),
|
||||
sqlStatement: sqlStatement{
|
||||
patterns: []*regexp.Regexp{
|
||||
regexp.MustCompile("(?)(SELECT|DELETE|INSERT|UPDATE|INTO|FROM|WHERE) "),
|
||||
regexp.MustCompile("%[^bdoxXfFp]"),
|
||||
},
|
||||
MetaData: gas.MetaData{
|
||||
MetaData: gosec.MetaData{
|
||||
ID: id,
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.High,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
What: "SQL string formatting",
|
||||
},
|
||||
},
|
||||
|
|
18
rules/ssh.go
18
rules/ssh.go
|
@ -3,11 +3,11 @@ package rules
|
|||
import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
type sshHostKey struct {
|
||||
gas.MetaData
|
||||
gosec.MetaData
|
||||
pkg string
|
||||
calls []string
|
||||
}
|
||||
|
@ -16,23 +16,23 @@ func (r *sshHostKey) ID() string {
|
|||
return r.MetaData.ID
|
||||
}
|
||||
|
||||
func (r *sshHostKey) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err error) {
|
||||
if _, matches := gas.MatchCallByPackage(n, c, r.pkg, r.calls...); matches {
|
||||
return gas.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
func (r *sshHostKey) Match(n ast.Node, c *gosec.Context) (gi *gosec.Issue, err error) {
|
||||
if _, matches := gosec.MatchCallByPackage(n, c, r.pkg, r.calls...); matches {
|
||||
return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewSSHHostKey rule detects the use of insecure ssh HostKeyCallback.
|
||||
func NewSSHHostKey(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
func NewSSHHostKey(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return &sshHostKey{
|
||||
pkg: "golang.org/x/crypto/ssh",
|
||||
calls: []string{"InsecureIgnoreHostKey"},
|
||||
MetaData: gas.MetaData{
|
||||
MetaData: gosec.MetaData{
|
||||
ID: id,
|
||||
What: "Use of ssh InsecureIgnoreHostKey should be audited",
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.High,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
}
|
||||
|
|
|
@ -18,12 +18,12 @@ import (
|
|||
"go/ast"
|
||||
"go/types"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
type subprocess struct {
|
||||
gas.MetaData
|
||||
gas.CallList
|
||||
gosec.MetaData
|
||||
gosec.CallList
|
||||
}
|
||||
|
||||
func (r *subprocess) ID() string {
|
||||
|
@ -39,24 +39,24 @@ func (r *subprocess) ID() string {
|
|||
// is unsafe. For example:
|
||||
//
|
||||
// syscall.Exec("echo", "foobar" + tainted)
|
||||
func (r *subprocess) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
func (r *subprocess) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
if node := r.ContainsCallExpr(n, c); node != nil {
|
||||
for _, arg := range node.Args {
|
||||
if ident, ok := arg.(*ast.Ident); ok {
|
||||
obj := c.Info.ObjectOf(ident)
|
||||
if _, ok := obj.(*types.Var); ok && !gas.TryResolve(ident, c) {
|
||||
return gas.NewIssue(c, n, r.ID(), "Subprocess launched with variable", gas.Medium, gas.High), nil
|
||||
if _, ok := obj.(*types.Var); ok && !gosec.TryResolve(ident, c) {
|
||||
return gosec.NewIssue(c, n, r.ID(), "Subprocess launched with variable", gosec.Medium, gosec.High), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return gas.NewIssue(c, n, r.ID(), "Subprocess launching should be audited", gas.Low, gas.High), nil
|
||||
return gosec.NewIssue(c, n, r.ID(), "Subprocess launching should be audited", gosec.Low, gosec.High), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewSubproc detects cases where we are forking out to an external process
|
||||
func NewSubproc(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
rule := &subprocess{gas.MetaData{ID: id}, gas.NewCallList()}
|
||||
func NewSubproc(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
rule := &subprocess{gosec.MetaData{ID: id}, gosec.NewCallList()}
|
||||
rule.Add("os/exec", "Command")
|
||||
rule.Add("syscall", "Exec")
|
||||
return rule, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
|
|
|
@ -18,12 +18,12 @@ import (
|
|||
"go/ast"
|
||||
"regexp"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
type badTempFile struct {
|
||||
gas.MetaData
|
||||
calls gas.CallList
|
||||
gosec.MetaData
|
||||
calls gosec.CallList
|
||||
args *regexp.Regexp
|
||||
}
|
||||
|
||||
|
@ -31,27 +31,27 @@ func (t *badTempFile) ID() string {
|
|||
return t.MetaData.ID
|
||||
}
|
||||
|
||||
func (t *badTempFile) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err error) {
|
||||
func (t *badTempFile) Match(n ast.Node, c *gosec.Context) (gi *gosec.Issue, err error) {
|
||||
if node := t.calls.ContainsCallExpr(n, c); node != nil {
|
||||
if arg, e := gas.GetString(node.Args[0]); t.args.MatchString(arg) && e == nil {
|
||||
return gas.NewIssue(c, n, t.ID(), t.What, t.Severity, t.Confidence), nil
|
||||
if arg, e := gosec.GetString(node.Args[0]); t.args.MatchString(arg) && e == nil {
|
||||
return gosec.NewIssue(c, n, t.ID(), t.What, t.Severity, t.Confidence), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewBadTempFile detects direct writes to predictable path in temporary directory
|
||||
func NewBadTempFile(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
calls := gas.NewCallList()
|
||||
func NewBadTempFile(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
calls := gosec.NewCallList()
|
||||
calls.Add("io/ioutil", "WriteFile")
|
||||
calls.Add("os", "Create")
|
||||
return &badTempFile{
|
||||
calls: calls,
|
||||
args: regexp.MustCompile(`^/tmp/.*$|^/var/tmp/.*$`),
|
||||
MetaData: gas.MetaData{
|
||||
MetaData: gosec.MetaData{
|
||||
ID: id,
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.High,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
What: "File creation in shared tmp directory without using ioutil.Tempfile",
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
|
|
|
@ -17,23 +17,23 @@ package rules
|
|||
import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
type templateCheck struct {
|
||||
gas.MetaData
|
||||
calls gas.CallList
|
||||
gosec.MetaData
|
||||
calls gosec.CallList
|
||||
}
|
||||
|
||||
func (t *templateCheck) ID() string {
|
||||
return t.MetaData.ID
|
||||
}
|
||||
|
||||
func (t *templateCheck) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
func (t *templateCheck) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
if node := t.calls.ContainsCallExpr(n, c); node != nil {
|
||||
for _, arg := range node.Args {
|
||||
if _, ok := arg.(*ast.BasicLit); !ok { // basic lits are safe
|
||||
return gas.NewIssue(c, n, t.ID(), t.What, t.Severity, t.Confidence), nil
|
||||
return gosec.NewIssue(c, n, t.ID(), t.What, t.Severity, t.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,19 +42,19 @@ func (t *templateCheck) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
|||
|
||||
// NewTemplateCheck constructs the template check rule. This rule is used to
|
||||
// find use of tempaltes where HTML/JS escaping is not being used
|
||||
func NewTemplateCheck(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
func NewTemplateCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
|
||||
calls := gas.NewCallList()
|
||||
calls := gosec.NewCallList()
|
||||
calls.Add("html/template", "HTML")
|
||||
calls.Add("html/template", "HTMLAttr")
|
||||
calls.Add("html/template", "JS")
|
||||
calls.Add("html/template", "URL")
|
||||
return &templateCheck{
|
||||
calls: calls,
|
||||
MetaData: gas.MetaData{
|
||||
MetaData: gosec.MetaData{
|
||||
ID: id,
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.Low,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.Low,
|
||||
What: "this method will not auto-escape HTML. Verify data is well formed.",
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
|
|
32
rules/tls.go
32
rules/tls.go
|
@ -20,11 +20,11 @@ import (
|
|||
"fmt"
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
type insecureConfigTLS struct {
|
||||
gas.MetaData
|
||||
gosec.MetaData
|
||||
MinVersion int16
|
||||
MaxVersion int16
|
||||
requiredType string
|
||||
|
@ -44,14 +44,14 @@ func stringInSlice(a string, list []string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (t *insecureConfigTLS) processTLSCipherSuites(n ast.Node, c *gas.Context) *gas.Issue {
|
||||
func (t *insecureConfigTLS) processTLSCipherSuites(n ast.Node, c *gosec.Context) *gosec.Issue {
|
||||
|
||||
if ciphers, ok := n.(*ast.CompositeLit); ok {
|
||||
for _, cipher := range ciphers.Elts {
|
||||
if ident, ok := cipher.(*ast.SelectorExpr); ok {
|
||||
if !stringInSlice(ident.Sel.Name, t.goodCiphers) {
|
||||
err := fmt.Sprintf("TLS Bad Cipher Suite: %s", ident.Sel.Name)
|
||||
return gas.NewIssue(c, ident, t.ID(), err, gas.High, gas.High)
|
||||
return gosec.NewIssue(c, ident, t.ID(), err, gosec.High, gosec.High)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,46 +59,46 @@ func (t *insecureConfigTLS) processTLSCipherSuites(n ast.Node, c *gas.Context) *
|
|||
return nil
|
||||
}
|
||||
|
||||
func (t *insecureConfigTLS) processTLSConfVal(n *ast.KeyValueExpr, c *gas.Context) *gas.Issue {
|
||||
func (t *insecureConfigTLS) processTLSConfVal(n *ast.KeyValueExpr, c *gosec.Context) *gosec.Issue {
|
||||
if ident, ok := n.Key.(*ast.Ident); ok {
|
||||
switch ident.Name {
|
||||
|
||||
case "InsecureSkipVerify":
|
||||
if node, ok := n.Value.(*ast.Ident); ok {
|
||||
if node.Name != "false" {
|
||||
return gas.NewIssue(c, n, t.ID(), "TLS InsecureSkipVerify set true.", gas.High, gas.High)
|
||||
return gosec.NewIssue(c, n, t.ID(), "TLS InsecureSkipVerify set true.", gosec.High, gosec.High)
|
||||
}
|
||||
} else {
|
||||
// TODO(tk): symbol tab look up to get the actual value
|
||||
return gas.NewIssue(c, n, t.ID(), "TLS InsecureSkipVerify may be true.", gas.High, gas.Low)
|
||||
return gosec.NewIssue(c, n, t.ID(), "TLS InsecureSkipVerify may be true.", gosec.High, gosec.Low)
|
||||
}
|
||||
|
||||
case "PreferServerCipherSuites":
|
||||
if node, ok := n.Value.(*ast.Ident); ok {
|
||||
if node.Name == "false" {
|
||||
return gas.NewIssue(c, n, t.ID(), "TLS PreferServerCipherSuites set false.", gas.Medium, gas.High)
|
||||
return gosec.NewIssue(c, n, t.ID(), "TLS PreferServerCipherSuites set false.", gosec.Medium, gosec.High)
|
||||
}
|
||||
} else {
|
||||
// TODO(tk): symbol tab look up to get the actual value
|
||||
return gas.NewIssue(c, n, t.ID(), "TLS PreferServerCipherSuites may be false.", gas.Medium, gas.Low)
|
||||
return gosec.NewIssue(c, n, t.ID(), "TLS PreferServerCipherSuites may be false.", gosec.Medium, gosec.Low)
|
||||
}
|
||||
|
||||
case "MinVersion":
|
||||
if ival, ierr := gas.GetInt(n.Value); ierr == nil {
|
||||
if ival, ierr := gosec.GetInt(n.Value); ierr == nil {
|
||||
if (int16)(ival) < t.MinVersion {
|
||||
return gas.NewIssue(c, n, t.ID(), "TLS MinVersion too low.", gas.High, gas.High)
|
||||
return gosec.NewIssue(c, n, t.ID(), "TLS MinVersion too low.", gosec.High, gosec.High)
|
||||
}
|
||||
// TODO(tk): symbol tab look up to get the actual value
|
||||
return gas.NewIssue(c, n, t.ID(), "TLS MinVersion may be too low.", gas.High, gas.Low)
|
||||
return gosec.NewIssue(c, n, t.ID(), "TLS MinVersion may be too low.", gosec.High, gosec.Low)
|
||||
}
|
||||
|
||||
case "MaxVersion":
|
||||
if ival, ierr := gas.GetInt(n.Value); ierr == nil {
|
||||
if ival, ierr := gosec.GetInt(n.Value); ierr == nil {
|
||||
if (int16)(ival) < t.MaxVersion {
|
||||
return gas.NewIssue(c, n, t.ID(), "TLS MaxVersion too low.", gas.High, gas.High)
|
||||
return gosec.NewIssue(c, n, t.ID(), "TLS MaxVersion too low.", gosec.High, gosec.High)
|
||||
}
|
||||
// TODO(tk): symbol tab look up to get the actual value
|
||||
return gas.NewIssue(c, n, t.ID(), "TLS MaxVersion may be too low.", gas.High, gas.Low)
|
||||
return gosec.NewIssue(c, n, t.ID(), "TLS MaxVersion may be too low.", gosec.High, gosec.Low)
|
||||
}
|
||||
|
||||
case "CipherSuites":
|
||||
|
@ -112,7 +112,7 @@ func (t *insecureConfigTLS) processTLSConfVal(n *ast.KeyValueExpr, c *gas.Contex
|
|||
return nil
|
||||
}
|
||||
|
||||
func (t *insecureConfigTLS) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
func (t *insecureConfigTLS) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
if complit, ok := n.(*ast.CompositeLit); ok && complit.Type != nil {
|
||||
actualType := c.Info.TypeOf(complit.Type)
|
||||
if actualType != nil && actualType.String() == t.requiredType {
|
||||
|
|
|
@ -3,14 +3,14 @@ package rules
|
|||
import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
// NewModernTLSCheck creates a check for Modern TLS ciphers
|
||||
// DO NOT EDIT - generated by tlsconfig tool
|
||||
func NewModernTLSCheck(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
func NewModernTLSCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return &insecureConfigTLS{
|
||||
MetaData: gas.MetaData{ID: id},
|
||||
MetaData: gosec.MetaData{ID: id},
|
||||
requiredType: "crypto/tls.Config",
|
||||
MinVersion: 0x0303,
|
||||
MaxVersion: 0x0303,
|
||||
|
@ -31,9 +31,9 @@ func NewModernTLSCheck(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
|||
|
||||
// NewIntermediateTLSCheck creates a check for Intermediate TLS ciphers
|
||||
// DO NOT EDIT - generated by tlsconfig tool
|
||||
func NewIntermediateTLSCheck(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
func NewIntermediateTLSCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return &insecureConfigTLS{
|
||||
MetaData: gas.MetaData{ID: id},
|
||||
MetaData: gosec.MetaData{ID: id},
|
||||
requiredType: "crypto/tls.Config",
|
||||
MinVersion: 0x0301,
|
||||
MaxVersion: 0x0303,
|
||||
|
@ -74,9 +74,9 @@ func NewIntermediateTLSCheck(id string, conf gas.Config) (gas.Rule, []ast.Node)
|
|||
|
||||
// NewOldTLSCheck creates a check for Old TLS ciphers
|
||||
// DO NOT EDIT - generated by tlsconfig tool
|
||||
func NewOldTLSCheck(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
func NewOldTLSCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return &insecureConfigTLS{
|
||||
MetaData: gas.MetaData{ID: id},
|
||||
MetaData: gosec.MetaData{ID: id},
|
||||
requiredType: "crypto/tls.Config",
|
||||
MinVersion: 0x0300,
|
||||
MaxVersion: 0x0303,
|
||||
|
|
|
@ -17,11 +17,11 @@ package rules
|
|||
import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
type usingUnsafe struct {
|
||||
gas.MetaData
|
||||
gosec.MetaData
|
||||
pkg string
|
||||
calls []string
|
||||
}
|
||||
|
@ -30,24 +30,24 @@ func (r *usingUnsafe) ID() string {
|
|||
return r.MetaData.ID
|
||||
}
|
||||
|
||||
func (r *usingUnsafe) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err error) {
|
||||
if _, matches := gas.MatchCallByPackage(n, c, r.pkg, r.calls...); matches {
|
||||
return gas.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
func (r *usingUnsafe) Match(n ast.Node, c *gosec.Context) (gi *gosec.Issue, err error) {
|
||||
if _, matches := gosec.MatchCallByPackage(n, c, r.pkg, r.calls...); matches {
|
||||
return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewUsingUnsafe rule detects the use of the unsafe package. This is only
|
||||
// really useful for auditing purposes.
|
||||
func NewUsingUnsafe(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
func NewUsingUnsafe(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return &usingUnsafe{
|
||||
pkg: "unsafe",
|
||||
calls: []string{"Alignof", "Offsetof", "Sizeof", "Pointer"},
|
||||
MetaData: gas.MetaData{
|
||||
MetaData: gosec.MetaData{
|
||||
ID: id,
|
||||
What: "Use of unsafe calls should be audited",
|
||||
Severity: gas.Low,
|
||||
Confidence: gas.High,
|
||||
Severity: gosec.Low,
|
||||
Confidence: gosec.High,
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
}
|
||||
|
|
|
@ -17,11 +17,11 @@ package rules
|
|||
import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
type usesWeakCryptography struct {
|
||||
gas.MetaData
|
||||
gosec.MetaData
|
||||
blacklist map[string][]string
|
||||
}
|
||||
|
||||
|
@ -29,27 +29,27 @@ func (r *usesWeakCryptography) ID() string {
|
|||
return r.MetaData.ID
|
||||
}
|
||||
|
||||
func (r *usesWeakCryptography) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
func (r *usesWeakCryptography) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
for pkg, funcs := range r.blacklist {
|
||||
if _, matched := gas.MatchCallByPackage(n, c, pkg, funcs...); matched {
|
||||
return gas.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
if _, matched := gosec.MatchCallByPackage(n, c, pkg, funcs...); matched {
|
||||
return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewUsesWeakCryptography detects uses of des.* md5.* or rc4.*
|
||||
func NewUsesWeakCryptography(id string, conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
func NewUsesWeakCryptography(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
calls := make(map[string][]string)
|
||||
calls["crypto/des"] = []string{"NewCipher", "NewTripleDESCipher"}
|
||||
calls["crypto/md5"] = []string{"New", "Sum"}
|
||||
calls["crypto/rc4"] = []string{"NewCipher"}
|
||||
rule := &usesWeakCryptography{
|
||||
blacklist: calls,
|
||||
MetaData: gas.MetaData{
|
||||
MetaData: gosec.MetaData{
|
||||
ID: id,
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.High,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
What: "Use of weak cryptographic primitive",
|
||||
},
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
"golang.org/x/tools/go/loader"
|
||||
)
|
||||
|
||||
|
@ -33,7 +33,7 @@ type TestPackage struct {
|
|||
func NewTestPackage() *TestPackage {
|
||||
// Files must exist in $GOPATH
|
||||
sourceDir := path.Join(os.Getenv("GOPATH"), "src")
|
||||
workingDir, err := ioutil.TempDir(sourceDir, "gas_test")
|
||||
workingDir, err := ioutil.TempDir(sourceDir, "gosecs_test")
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ func (p *TestPackage) Build() error {
|
|||
}
|
||||
|
||||
// CreateContext builds a context out of supplied package context
|
||||
func (p *TestPackage) CreateContext(filename string) *gas.Context {
|
||||
func (p *TestPackage) CreateContext(filename string) *gosec.Context {
|
||||
if err := p.Build(); err != nil {
|
||||
log.Fatal(err)
|
||||
return nil
|
||||
|
@ -109,13 +109,13 @@ func (p *TestPackage) CreateContext(filename string) *gas.Context {
|
|||
strip := fmt.Sprintf("%s%c", p.Path, os.PathSeparator)
|
||||
pkgFile = strings.TrimPrefix(pkgFile, strip)
|
||||
if pkgFile == filename {
|
||||
ctx := &gas.Context{
|
||||
ctx := &gosec.Context{
|
||||
FileSet: p.build.program.Fset,
|
||||
Root: file,
|
||||
Config: gas.NewConfig(),
|
||||
Config: gosec.NewConfig(),
|
||||
Info: &pkg.Info,
|
||||
Pkg: pkg.Pkg,
|
||||
Imports: gas.NewImportTracker(),
|
||||
Imports: gosec.NewImportTracker(),
|
||||
}
|
||||
ctx.Imports.TrackPackages(ctx.Pkg.Imports()...)
|
||||
return ctx
|
||||
|
|
|
@ -3,14 +3,14 @@ package testutils
|
|||
import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gas"
|
||||
"github.com/securego/gosec"
|
||||
)
|
||||
|
||||
// MockVisitor is useful for stubbing out ast.Visitor with callback
|
||||
// and looking for specific conditions to exist.
|
||||
type MockVisitor struct {
|
||||
Context *gas.Context
|
||||
Callback func(n ast.Node, ctx *gas.Context) bool
|
||||
Context *gosec.Context
|
||||
Callback func(n ast.Node, ctx *gosec.Context) bool
|
||||
}
|
||||
|
||||
// NewMockVisitor creates a new empty struct, the Context and
|
||||
|
|
Loading…
Reference in a new issue