Rule selection rules

This makes the following changes:
- riles are identified by an ID
- include / exclude list now work
- rules are selected based on these lists
- blacklist rules are broken out into methods
- rule constructors now take the config map
- config file can be used to select rules
- CLI options embelish config selection options
This commit is contained in:
Tim Kelsey 2016-08-10 12:51:03 +01:00
parent 235308f853
commit 713949fe69
31 changed files with 211 additions and 181 deletions

54
main.go
View file

@ -22,6 +22,7 @@ import (
"log" "log"
"os" "os"
"path/filepath" "path/filepath"
"sort"
"strings" "strings"
gas "github.com/HewlettPackard/gas/core" gas "github.com/HewlettPackard/gas/core"
@ -61,15 +62,20 @@ USAGE:
var logger *log.Logger var logger *log.Logger
func extendConfList(conf map[string]interface{}, name string, input []string) { func extendConfList(conf map[string]interface{}, name string, inputStr string) {
if val, ok := conf[name]; ok { if inputStr == "" {
if data, ok := val.(*[]string); ok {
conf[name] = append(*data, input...)
} else {
logger.Fatal("Config item must be a string list: ", name)
}
} else {
conf[name] = []string{} conf[name] = []string{}
} else {
input := strings.Split(inputStr, ",")
if val, ok := conf[name]; ok {
if data, ok := val.(*[]string); ok {
conf[name] = append(*data, input...)
} else {
logger.Fatal("Config item must be a string list: ", name)
}
} else {
conf[name] = input
}
} }
} }
@ -86,8 +92,8 @@ func buildConfig(incRules string, excRules string) map[string]interface{} {
} }
// add in CLI include and exclude data // add in CLI include and exclude data
extendConfList(config, "include", strings.Split(incRules, ",")) extendConfList(config, "include", incRules)
extendConfList(config, "exclude", strings.Split(excRules, ",")) extendConfList(config, "exclude", excRules)
// override ignoreNosec if given on CLI // override ignoreNosec if given on CLI
if flagIgnoreNoSec != nil { if flagIgnoreNoSec != nil {
@ -108,6 +114,20 @@ func usage() {
fmt.Fprintln(os.Stderr, usageText) fmt.Fprintln(os.Stderr, usageText)
fmt.Fprint(os.Stderr, "OPTIONS:\n\n") fmt.Fprint(os.Stderr, "OPTIONS:\n\n")
flag.PrintDefaults() flag.PrintDefaults()
fmt.Fprint(os.Stderr, "\n\nRULES:\n\n")
// sorted rule list for eas of reading
rl := GetFullRuleList()
keys := make([]string, 0, len(rl))
for key := range rl {
keys = append(keys, key)
}
sort.Strings(keys)
for _, k := range keys {
v := rl[k]
fmt.Fprintf(os.Stderr, "\t%s: %s\n", k, v.description)
}
fmt.Fprint(os.Stderr, "\n")
} }
func main() { func main() {
@ -119,15 +139,11 @@ func main() {
var excluded filelist = []string{"*_test.go"} var excluded filelist = []string{"*_test.go"}
flag.Var(&excluded, "skip", "File pattern to exclude from scan") flag.Var(&excluded, "skip", "File pattern to exclude from scan")
// Rule configuration
rules := newRulelist()
flag.Var(&rules, "rule", "GAS rules enabled when performing a scan")
incRules := "" incRules := ""
flag.StringVar(&incRules, "include", "", "comma sperated list of rules to include") flag.StringVar(&incRules, "include", "", "comma sperated list of rules IDs to include, see rule list")
excRules := "" excRules := ""
flag.StringVar(&excRules, "exclude", "", "comma sperated list of rules to exclude") flag.StringVar(&excRules, "exclude", "", "comma sperated list of rules IDs to exclude, see rule list")
// Custom commands / utilities to run instead of default analyzer // Custom commands / utilities to run instead of default analyzer
tools := newUtils() tools := newUtils()
@ -155,12 +171,8 @@ func main() {
// Setup analyzer // Setup analyzer
config := buildConfig(incRules, excRules) config := buildConfig(incRules, excRules)
analyzer := gas.NewAnalyzer(config, logger) analyzer := gas.NewAnalyzer(config, logger)
if !rules.overwritten { AddRules(&analyzer, config)
rules.useDefaults()
}
rules.apply(&analyzer)
// Traverse directory structure if './...' // Traverse directory structure if './...'
if flag.NArg() == 1 && flag.Arg(0) == "./..." { if flag.NArg() == 1 && flag.Arg(0) == "./..." {

View file

@ -17,85 +17,77 @@ package main
import ( import (
"fmt" "fmt"
"go/ast" "go/ast"
"strings"
gas "github.com/HewlettPackard/gas/core" gas "github.com/HewlettPackard/gas/core"
"github.com/HewlettPackard/gas/rules" "github.com/HewlettPackard/gas/rules"
) )
type ruleMaker func() (gas.Rule, ast.Node) type RuleInfo struct {
type ruleConfig struct { description string
enabled bool build func(map[string]interface{}) (gas.Rule, ast.Node)
constructors []ruleMaker
} }
type rulelist struct { // GetFullRuleList get the full list of all rules available to GAS
rules map[string]*ruleConfig func GetFullRuleList() map[string]RuleInfo {
overwritten bool return map[string]RuleInfo{
} // misc
"G101": RuleInfo{"hardcoded credentials", rules.NewHardcodedCredentials},
"G102": RuleInfo{"bind to all interfaces", rules.NewBindsToAllNetworkInterfaces},
"G103": RuleInfo{"use of unsafe block", rules.NewUsingUnsafe},
"G104": RuleInfo{"errors not checked", rules.NewTemplateCheck},
func newRulelist() rulelist { // injection
var rs rulelist "G201": RuleInfo{"sql string format", rules.NewSqlStrFormat},
rs.rules = make(map[string]*ruleConfig) "G202": RuleInfo{"sql string concat", rules.NewSqlStrConcat},
rs.overwritten = false "G203": RuleInfo{"unescaped templates", rules.NewTemplateCheck},
rs.register("sql", rules.NewSqlStrConcat, rules.NewSqlStrFormat) "G204": RuleInfo{"use of exec", rules.NewSubproc},
rs.register("crypto", rules.NewUsesWeakCryptography)
rs.register("hardcoded", rules.NewHardcodedCredentials)
rs.register("perms", rules.NewMkdirPerms, rules.NewChmodPerms)
rs.register("tempfile", rules.NewBadTempFile)
rs.register("tls_good", rules.NewModernTlsCheck)
rs.register("tls_ok", rules.NewIntermediateTlsCheck)
rs.register("tls_old", rules.NewCompatTlsCheck)
rs.register("bind", rules.NewBindsToAllNetworkInterfaces)
rs.register("unsafe", rules.NewUsingUnsafe)
rs.register("rsa", rules.NewWeakKeyStrength)
rs.register("templates", rules.NewTemplateCheck)
rs.register("exec", rules.NewSubproc)
rs.register("errors", rules.NewNoErrorCheck)
rs.register("rand", rules.NewWeakRandCheck)
rs.register("blacklist_imports", rules.NewBlacklistImports)
return rs
}
func (r *rulelist) register(name string, cons ...ruleMaker) { // filesystem
r.rules[name] = &ruleConfig{false, cons} "G301": RuleInfo{"poor mkdir permissions", rules.NewMkdirPerms},
} "G302": RuleInfo{"poor chmod permisions", rules.NewChmodPerms},
"G303": RuleInfo{"predicatable tempfile", rules.NewBadTempFile},
func (r *rulelist) useDefaults() { // crypto
for k := range r.rules { "G401": RuleInfo{"weak crypto", rules.NewUsesWeakCryptography},
r.rules[k].enabled = true "G402": RuleInfo{"bad TLS options", rules.NewIntermediateTlsCheck},
"G403": RuleInfo{"bad RSA key length", rules.NewWeakKeyStrength},
"G404": RuleInfo{"poor random source (rand)", rules.NewWeakRandCheck},
// blacklist
"G501": RuleInfo{"blacklist: crypto/md5", rules.NewBlacklist_crypto_md5},
"G502": RuleInfo{"blacklist: crypto/des", rules.NewBlacklist_crypto_des},
"G503": RuleInfo{"blacklist: crypto/rc4", rules.NewBlacklist_crypto_rc4},
"G504": RuleInfo{"blacklist: net/http/cgi", rules.NewBlacklist_net_http_cgi},
} }
} }
func (r *rulelist) list() []string { func AddRules(analyzer *gas.Analyzer, conf map[string]interface{}) {
i := 0 var all map[string]RuleInfo
keys := make([]string, len(r.rules))
for k := range r.rules {
keys[i] = k
i++
}
return keys
}
func (r *rulelist) apply(g *gas.Analyzer) { inc := conf["include"].([]string)
for _, v := range r.rules { exc := conf["exclude"].([]string)
if v.enabled {
for _, ctor := range v.constructors { fmt.Println(len(inc))
g.AddRule(ctor())
// add included rules
if len(inc) == 0 {
all = GetFullRuleList()
} else {
all = map[string]RuleInfo{}
tmp := GetFullRuleList()
for _, v := range inc {
if val, ok := tmp[v]; ok {
all[v] = val
} }
} }
} }
}
func (r *rulelist) String() string { // remove excluded rules
return strings.Join(r.list(), ", ") for _, v := range exc {
} delete(all, v)
}
func (r *rulelist) Set(opt string) error {
r.overwritten = true for _, v := range all {
if x, ok := r.rules[opt]; ok { analyzer.AddRule(v.build(conf))
x.enabled = true
return nil
} }
return fmt.Errorf("Valid rules are: %s", r)
} }

View file

@ -15,9 +15,10 @@
package rules package rules
import ( import (
gas "github.com/HewlettPackard/gas/core"
"go/ast" "go/ast"
"regexp" "regexp"
gas "github.com/HewlettPackard/gas/core"
) )
// Looks for net.Listen("0.0.0.0") or net.Listen(":8080") // Looks for net.Listen("0.0.0.0") or net.Listen(":8080")
@ -38,7 +39,7 @@ func (r *BindsToAllNetworkInterfaces) Match(n ast.Node, c *gas.Context) (gi *gas
return return
} }
func NewBindsToAllNetworkInterfaces() (r gas.Rule, n ast.Node) { func NewBindsToAllNetworkInterfaces(conf map[string]interface{}) (r gas.Rule, n ast.Node) {
r = &BindsToAllNetworkInterfaces{ r = &BindsToAllNetworkInterfaces{
call: regexp.MustCompile(`^net\.Listen$`), call: regexp.MustCompile(`^net\.Listen$`),
pattern: regexp.MustCompile(`^(0.0.0.0|:).*$`), pattern: regexp.MustCompile(`^(0.0.0.0|:).*$`),

View file

@ -23,7 +23,7 @@ import (
func TestBind0000(t *testing.T) { func TestBind0000(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewBindsToAllNetworkInterfaces()) analyzer.AddRule(NewBindsToAllNetworkInterfaces(config))
issues := gasTestRunner(` issues := gasTestRunner(`
package main package main
@ -45,7 +45,7 @@ func TestBind0000(t *testing.T) {
func TestBindEmptyHost(t *testing.T) { func TestBindEmptyHost(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewBindsToAllNetworkInterfaces()) analyzer.AddRule(NewBindsToAllNetworkInterfaces(config))
issues := gasTestRunner(` issues := gasTestRunner(`
package main package main

View file

@ -20,47 +20,68 @@ import (
gas "github.com/HewlettPackard/gas/core" gas "github.com/HewlettPackard/gas/core"
) )
type BlacklistImports struct { type BlacklistImport struct {
BlacklistSet map[string]gas.MetaData gas.MetaData
Path string
} }
func (r *BlacklistImports) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err error) { func (r *BlacklistImport) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err error) {
if node, ok := n.(*ast.ImportSpec); ok { if node, ok := n.(*ast.ImportSpec); ok {
if data, ok := r.BlacklistSet[node.Path.Value]; ok { if r.Path == node.Path.Value {
return gas.NewIssue(c, n, data.What, data.Severity, data.Confidence), nil return gas.NewIssue(c, n, r.What, r.Severity, r.Confidence), nil
} }
} }
return nil, nil return nil, nil
} }
func NewBlacklistImports() (r gas.Rule, n ast.Node) { func NewBlacklist_crypto_md5(conf map[string]interface{}) (r gas.Rule, n ast.Node) {
// TODO(tkelsey): make this configurable r = &BlacklistImport{
// TODO(tkelsey): make it so each item can be selected/excluded individually MetaData: gas.MetaData{
r = &BlacklistImports{ Severity: gas.High,
BlacklistSet: map[string]gas.MetaData{ Confidence: gas.High,
`"crypto/md5"`: gas.MetaData{ What: "Use of weak cryptographic primitive",
Severity: gas.High,
Confidence: gas.High,
What: "Use of weak cryptographic primitive",
},
`"crypto/des"`: gas.MetaData{
Severity: gas.High,
Confidence: gas.High,
What: "Use of weak cryptographic primitive",
},
`"crypto/rc4"`: gas.MetaData{
Severity: gas.High,
Confidence: gas.High,
What: "Use of weak cryptographic primitive",
},
`"net/http/cgi"`: gas.MetaData{
Severity: gas.High,
Confidence: gas.Low,
What: "Go code running under CGI is vulnerable to Httpoxy attack. (CVE-2016-5386)",
},
}, },
Path: `"crypto/md5"`,
}
n = (*ast.ImportSpec)(nil)
return
}
func NewBlacklist_crypto_des(conf map[string]interface{}) (r gas.Rule, n ast.Node) {
r = &BlacklistImport{
MetaData: gas.MetaData{
Severity: gas.High,
Confidence: gas.High,
What: "Use of weak cryptographic primitive",
},
Path: `"crypto/des"`,
}
n = (*ast.ImportSpec)(nil)
return
}
func NewBlacklist_crypto_rc4(conf map[string]interface{}) (r gas.Rule, n ast.Node) {
r = &BlacklistImport{
MetaData: gas.MetaData{
Severity: gas.High,
Confidence: gas.High,
What: "Use of weak cryptographic primitive",
},
Path: `"crypto/rc4"`,
}
n = (*ast.ImportSpec)(nil)
return
}
func NewBlacklist_net_http_cgi(conf map[string]interface{}) (r gas.Rule, n ast.Node) {
r = &BlacklistImport{
MetaData: gas.MetaData{
Severity: gas.High,
Confidence: gas.High,
What: "Go code running under CGI is vulnerable to Httpoxy attack. (CVE-2016-5386)",
},
Path: `"net/http/cgi"`,
} }
n = (*ast.ImportSpec)(nil) n = (*ast.ImportSpec)(nil)
return return
} }

View file

@ -50,7 +50,7 @@ func (r *NoErrorCheck) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err err
return nil, nil return nil, nil
} }
func NewNoErrorCheck() (r gas.Rule, n ast.Node) { func NewNoErrorCheck(conf map[string]interface{}) (r gas.Rule, n ast.Node) {
r = &NoErrorCheck{ r = &NoErrorCheck{
MetaData: gas.MetaData{ MetaData: gas.MetaData{
Severity: gas.Low, Severity: gas.Low,

View file

@ -23,7 +23,7 @@ import (
func TestErrorsMulti(t *testing.T) { func TestErrorsMulti(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewNoErrorCheck()) analyzer.AddRule(NewNoErrorCheck(config))
issues := gasTestRunner( issues := gasTestRunner(
`package main `package main
@ -46,7 +46,7 @@ func TestErrorsMulti(t *testing.T) {
func TestErrorsSingle(t *testing.T) { func TestErrorsSingle(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewNoErrorCheck()) analyzer.AddRule(NewNoErrorCheck(config))
issues := gasTestRunner( issues := gasTestRunner(
`package main `package main
@ -69,7 +69,7 @@ func TestErrorsSingle(t *testing.T) {
func TestErrorsGood(t *testing.T) { func TestErrorsGood(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewNoErrorCheck()) analyzer.AddRule(NewNoErrorCheck(config))
issues := gasTestRunner( issues := gasTestRunner(
`package main `package main

View file

@ -16,9 +16,10 @@ package rules
import ( import (
"fmt" "fmt"
gas "github.com/HewlettPackard/gas/core"
"go/ast" "go/ast"
"regexp" "regexp"
gas "github.com/HewlettPackard/gas/core"
) )
type FilePermissions struct { type FilePermissions struct {
@ -36,7 +37,7 @@ func (r *FilePermissions) Match(n ast.Node, c *gas.Context) (*gas.Issue, error)
return nil, nil return nil, nil
} }
func NewChmodPerms() (r gas.Rule, n ast.Node) { func NewChmodPerms(conf map[string]interface{}) (r gas.Rule, n ast.Node) {
mode := 0600 mode := 0600
r = &FilePermissions{ r = &FilePermissions{
pattern: regexp.MustCompile(`^os\.Chmod$`), pattern: regexp.MustCompile(`^os\.Chmod$`),
@ -51,7 +52,7 @@ func NewChmodPerms() (r gas.Rule, n ast.Node) {
return return
} }
func NewMkdirPerms() (r gas.Rule, n ast.Node) { func NewMkdirPerms(conf map[string]interface{}) (r gas.Rule, n ast.Node) {
mode := 0700 mode := 0700
r = &FilePermissions{ r = &FilePermissions{
pattern: regexp.MustCompile(`^(os\.Mkdir|os\.MkdirAll)$`), pattern: regexp.MustCompile(`^(os\.Mkdir|os\.MkdirAll)$`),

View file

@ -23,7 +23,7 @@ import (
func TestChmod(t *testing.T) { func TestChmod(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewChmodPerms()) analyzer.AddRule(NewChmodPerms(config))
issues := gasTestRunner(` issues := gasTestRunner(`
package main package main
@ -39,7 +39,7 @@ func TestChmod(t *testing.T) {
func TestMkdir(t *testing.T) { func TestMkdir(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewMkdirPerms()) analyzer.AddRule(NewMkdirPerms(config))
issues := gasTestRunner(` issues := gasTestRunner(`
package main package main

View file

@ -43,7 +43,7 @@ func (r *CredsAssign) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err erro
return return
} }
func NewHardcodedCredentials() (r gas.Rule, n ast.Node) { func NewHardcodedCredentials(conf map[string]interface{}) (r gas.Rule, n ast.Node) {
r = &CredsAssign{ r = &CredsAssign{
pattern: regexp.MustCompile(`(?i)passwd|pass|password|pwd|secret|token`), pattern: regexp.MustCompile(`(?i)passwd|pass|password|pwd|secret|token`),
MetaData: gas.MetaData{ MetaData: gas.MetaData{

View file

@ -23,7 +23,7 @@ import (
func TestHardcoded(t *testing.T) { func TestHardcoded(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewHardcodedCredentials()) analyzer.AddRule(NewHardcodedCredentials(config))
issues := gasTestRunner( issues := gasTestRunner(
` `

View file

@ -23,7 +23,7 @@ import (
func TestHttpoxy(t *testing.T) { func TestHttpoxy(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewBlacklistImports()) analyzer.AddRule(NewBlacklist_net_http_cgi(config))
issues := gasTestRunner(` issues := gasTestRunner(`
package main package main

View file

@ -23,7 +23,7 @@ import (
func TestNosec(t *testing.T) { func TestNosec(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSubproc()) analyzer.AddRule(NewSubproc(config))
issues := gasTestRunner( issues := gasTestRunner(
`package main `package main
@ -42,7 +42,7 @@ func TestNosec(t *testing.T) {
func TestNosecBlock(t *testing.T) { func TestNosecBlock(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSubproc()) analyzer.AddRule(NewSubproc(config))
issues := gasTestRunner( issues := gasTestRunner(
`package main `package main
@ -64,7 +64,7 @@ func TestNosecBlock(t *testing.T) {
func TestNosecIgnore(t *testing.T) { func TestNosecIgnore(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": true} config := map[string]interface{}{"ignoreNosec": true}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSubproc()) analyzer.AddRule(NewSubproc(config))
issues := gasTestRunner( issues := gasTestRunner(
`package main `package main

View file

@ -39,7 +39,7 @@ func (w *WeakRand) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
return nil, nil return nil, nil
} }
func NewWeakRandCheck() (r gas.Rule, n ast.Node) { func NewWeakRandCheck(conf map[string]interface{}) (r gas.Rule, n ast.Node) {
r = &WeakRand{ r = &WeakRand{
pattern: regexp.MustCompile(`^rand\.Read$`), pattern: regexp.MustCompile(`^rand\.Read$`),
packageName: "rand", packageName: "rand",

View file

@ -23,7 +23,7 @@ import (
func TestRandOk(t *testing.T) { func TestRandOk(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewWeakRandCheck()) analyzer.AddRule(NewWeakRandCheck(config))
issues := gasTestRunner( issues := gasTestRunner(
` `
@ -41,7 +41,7 @@ func TestRandOk(t *testing.T) {
func TestRandBad(t *testing.T) { func TestRandBad(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewWeakRandCheck()) analyzer.AddRule(NewWeakRandCheck(config))
issues := gasTestRunner( issues := gasTestRunner(
` `

View file

@ -37,7 +37,7 @@ func (w *WeakKeyStrength) Match(n ast.Node, c *gas.Context) (*gas.Issue, error)
return nil, nil return nil, nil
} }
func NewWeakKeyStrength() (r gas.Rule, n ast.Node) { func NewWeakKeyStrength(conf map[string]interface{}) (r gas.Rule, n ast.Node) {
bits := 2048 bits := 2048
r = &WeakKeyStrength{ r = &WeakKeyStrength{
pattern: regexp.MustCompile(`^rsa\.GenerateKey$`), pattern: regexp.MustCompile(`^rsa\.GenerateKey$`),

View file

@ -23,7 +23,7 @@ import (
func TestRSAKeys(t *testing.T) { func TestRSAKeys(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewWeakKeyStrength()) analyzer.AddRule(NewWeakKeyStrength(config))
issues := gasTestRunner( issues := gasTestRunner(
`package main `package main

View file

@ -56,7 +56,7 @@ func (s *SqlStrConcat) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
return nil, nil return nil, nil
} }
func NewSqlStrConcat() (r gas.Rule, n ast.Node) { func NewSqlStrConcat(conf map[string]interface{}) (r gas.Rule, n ast.Node) {
r = &SqlStrConcat{ r = &SqlStrConcat{
SqlStatement: SqlStatement{ SqlStatement: SqlStatement{
pattern: regexp.MustCompile(`(?)(SELECT|DELETE|INSERT|UPDATE|INTO|FROM|WHERE) `), pattern: regexp.MustCompile(`(?)(SELECT|DELETE|INSERT|UPDATE|INTO|FROM|WHERE) `),
@ -86,7 +86,7 @@ func (s *SqlStrFormat) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err err
return nil, nil return nil, nil
} }
func NewSqlStrFormat() (r gas.Rule, n ast.Node) { func NewSqlStrFormat(conf map[string]interface{}) (r gas.Rule, n ast.Node) {
r = &SqlStrFormat{ r = &SqlStrFormat{
call: regexp.MustCompile(`^fmt\.Sprintf$`), call: regexp.MustCompile(`^fmt\.Sprintf$`),
SqlStatement: SqlStatement{ SqlStatement: SqlStatement{

View file

@ -23,7 +23,7 @@ import (
func TestSQLInjectionViaConcatenation(t *testing.T) { func TestSQLInjectionViaConcatenation(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSqlStrConcat()) analyzer.AddRule(NewSqlStrConcat(config))
source := ` source := `
package main package main
@ -51,7 +51,7 @@ func TestSQLInjectionViaConcatenation(t *testing.T) {
func TestSQLInjectionViaIntepolation(t *testing.T) { func TestSQLInjectionViaIntepolation(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSqlStrFormat()) analyzer.AddRule(NewSqlStrFormat(config))
source := ` source := `
package main package main
@ -81,8 +81,8 @@ func TestSQLInjectionViaIntepolation(t *testing.T) {
func TestSQLInjectionFalsePositiveA(t *testing.T) { func TestSQLInjectionFalsePositiveA(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSqlStrConcat()) analyzer.AddRule(NewSqlStrConcat(config))
analyzer.AddRule(NewSqlStrFormat()) analyzer.AddRule(NewSqlStrFormat(config))
source := ` source := `
@ -117,8 +117,8 @@ func TestSQLInjectionFalsePositiveA(t *testing.T) {
func TestSQLInjectionFalsePositiveB(t *testing.T) { func TestSQLInjectionFalsePositiveB(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSqlStrConcat()) analyzer.AddRule(NewSqlStrConcat(config))
analyzer.AddRule(NewSqlStrFormat()) analyzer.AddRule(NewSqlStrFormat(config))
source := ` source := `
@ -153,8 +153,8 @@ func TestSQLInjectionFalsePositiveB(t *testing.T) {
func TestSQLInjectionFalsePositiveC(t *testing.T) { func TestSQLInjectionFalsePositiveC(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSqlStrConcat()) analyzer.AddRule(NewSqlStrConcat(config))
analyzer.AddRule(NewSqlStrFormat()) analyzer.AddRule(NewSqlStrFormat(config))
source := ` source := `
@ -189,8 +189,8 @@ func TestSQLInjectionFalsePositiveC(t *testing.T) {
func TestSQLInjectionFalsePositiveD(t *testing.T) { func TestSQLInjectionFalsePositiveD(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSqlStrConcat()) analyzer.AddRule(NewSqlStrConcat(config))
analyzer.AddRule(NewSqlStrFormat()) analyzer.AddRule(NewSqlStrFormat(config))
source := ` source := `

View file

@ -49,7 +49,7 @@ func (r *Subprocess) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
return nil, nil return nil, nil
} }
func NewSubproc() (r gas.Rule, n ast.Node) { func NewSubproc(conf map[string]interface{}) (r gas.Rule, n ast.Node) {
r = &Subprocess{ r = &Subprocess{
pattern: regexp.MustCompile(`^exec\.Command|syscall\.Exec$`), pattern: regexp.MustCompile(`^exec\.Command|syscall\.Exec$`),
} }

View file

@ -23,7 +23,7 @@ import (
func TestSubprocess(t *testing.T) { func TestSubprocess(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSubproc()) analyzer.AddRule(NewSubproc(config))
issues := gasTestRunner(` issues := gasTestRunner(`
package main package main
@ -51,7 +51,7 @@ func TestSubprocess(t *testing.T) {
func TestSubprocessVar(t *testing.T) { func TestSubprocessVar(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSubproc()) analyzer.AddRule(NewSubproc(config))
issues := gasTestRunner(` issues := gasTestRunner(`
package main package main
@ -79,7 +79,7 @@ func TestSubprocessVar(t *testing.T) {
func TestSubprocessPath(t *testing.T) { func TestSubprocessPath(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSubproc()) analyzer.AddRule(NewSubproc(config))
issues := gasTestRunner(` issues := gasTestRunner(`
package main package main
@ -106,7 +106,7 @@ func TestSubprocessPath(t *testing.T) {
func TestSubprocessSyscall(t *testing.T) { func TestSubprocessSyscall(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSubproc()) analyzer.AddRule(NewSubproc(config))
issues := gasTestRunner(` issues := gasTestRunner(`
package main package main

View file

@ -15,9 +15,10 @@
package rules package rules
import ( import (
gas "github.com/HewlettPackard/gas/core"
"go/ast" "go/ast"
"regexp" "regexp"
gas "github.com/HewlettPackard/gas/core"
) )
type BadTempFile struct { type BadTempFile struct {
@ -35,7 +36,7 @@ func (t *BadTempFile) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err erro
return nil, nil return nil, nil
} }
func NewBadTempFile() (r gas.Rule, n ast.Node) { func NewBadTempFile(conf map[string]interface{}) (r gas.Rule, n ast.Node) {
r = &BadTempFile{ r = &BadTempFile{
call: regexp.MustCompile(`ioutil\.WriteFile|os\.Create`), call: regexp.MustCompile(`ioutil\.WriteFile|os\.Create`),
args: regexp.MustCompile(`^/tmp/.*$|^/var/tmp/.*$`), args: regexp.MustCompile(`^/tmp/.*$|^/var/tmp/.*$`),

View file

@ -23,7 +23,7 @@ import (
func TestTempfiles(t *testing.T) { func TestTempfiles(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewBadTempFile()) analyzer.AddRule(NewBadTempFile(config))
source := ` source := `
package samples package samples

View file

@ -15,9 +15,10 @@
package rules package rules
import ( import (
gas "github.com/HewlettPackard/gas/core"
"go/ast" "go/ast"
"regexp" "regexp"
gas "github.com/HewlettPackard/gas/core"
) )
type TemplateCheck struct { type TemplateCheck struct {
@ -36,7 +37,7 @@ func (t *TemplateCheck) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err er
return nil, nil return nil, nil
} }
func NewTemplateCheck() (r gas.Rule, n ast.Node) { func NewTemplateCheck(conf map[string]interface{}) (r gas.Rule, n ast.Node) {
r = &TemplateCheck{ r = &TemplateCheck{
call: regexp.MustCompile(`^template\.(HTML|JS|URL)$`), call: regexp.MustCompile(`^template\.(HTML|JS|URL)$`),
MetaData: gas.MetaData{ MetaData: gas.MetaData{

View file

@ -23,7 +23,7 @@ import (
func TestTemplateCheckSafe(t *testing.T) { func TestTemplateCheckSafe(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewTemplateCheck()) analyzer.AddRule(NewTemplateCheck(config))
source := ` source := `
package samples package samples
@ -51,7 +51,7 @@ func TestTemplateCheckSafe(t *testing.T) {
func TestTemplateCheckBadHTML(t *testing.T) { func TestTemplateCheckBadHTML(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewTemplateCheck()) analyzer.AddRule(NewTemplateCheck(config))
source := ` source := `
package samples package samples
@ -80,7 +80,7 @@ func TestTemplateCheckBadHTML(t *testing.T) {
func TestTemplateCheckBadJS(t *testing.T) { func TestTemplateCheckBadJS(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewTemplateCheck()) analyzer.AddRule(NewTemplateCheck(config))
source := ` source := `
package samples package samples
@ -109,7 +109,7 @@ func TestTemplateCheckBadJS(t *testing.T) {
func TestTemplateCheckBadURL(t *testing.T) { func TestTemplateCheckBadURL(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewTemplateCheck()) analyzer.AddRule(NewTemplateCheck(config))
source := ` source := `
package samples package samples

View file

@ -109,7 +109,7 @@ func (t *InsecureConfigTLS) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, er
return return
} }
func NewModernTlsCheck() (r gas.Rule, n ast.Node) { func NewModernTlsCheck(conf map[string]interface{}) (r gas.Rule, n ast.Node) {
// https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility // https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility
r = &InsecureConfigTLS{ r = &InsecureConfigTLS{
pattern: regexp.MustCompile(`^tls\.Config$`), pattern: regexp.MustCompile(`^tls\.Config$`),
@ -126,7 +126,7 @@ func NewModernTlsCheck() (r gas.Rule, n ast.Node) {
return return
} }
func NewIntermediateTlsCheck() (r gas.Rule, n ast.Node) { func NewIntermediateTlsCheck(conf map[string]interface{}) (r gas.Rule, n ast.Node) {
// https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28default.29 // https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28default.29
r = &InsecureConfigTLS{ r = &InsecureConfigTLS{
pattern: regexp.MustCompile(`^tls\.Config$`), pattern: regexp.MustCompile(`^tls\.Config$`),
@ -154,7 +154,7 @@ func NewIntermediateTlsCheck() (r gas.Rule, n ast.Node) {
return return
} }
func NewCompatTlsCheck() (r gas.Rule, n ast.Node) { func NewCompatTlsCheck(conf map[string]interface{}) (r gas.Rule, n ast.Node) {
// https://wiki.mozilla.org/Security/Server_Side_TLS#Old_compatibility_.28default.29 // https://wiki.mozilla.org/Security/Server_Side_TLS#Old_compatibility_.28default.29
r = &InsecureConfigTLS{ r = &InsecureConfigTLS{
pattern: regexp.MustCompile(`^tls\.Config$`), pattern: regexp.MustCompile(`^tls\.Config$`),

View file

@ -23,7 +23,7 @@ import (
func TestInsecureSkipVerify(t *testing.T) { func TestInsecureSkipVerify(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewModernTlsCheck()) analyzer.AddRule(NewModernTlsCheck(config))
issues := gasTestRunner(` issues := gasTestRunner(`
package main package main
@ -52,7 +52,7 @@ func TestInsecureSkipVerify(t *testing.T) {
func TestInsecureMinVersion(t *testing.T) { func TestInsecureMinVersion(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewModernTlsCheck()) analyzer.AddRule(NewModernTlsCheck(config))
issues := gasTestRunner(` issues := gasTestRunner(`
package main package main
@ -81,7 +81,7 @@ func TestInsecureMinVersion(t *testing.T) {
func TestInsecureMaxVersion(t *testing.T) { func TestInsecureMaxVersion(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewModernTlsCheck()) analyzer.AddRule(NewModernTlsCheck(config))
issues := gasTestRunner(` issues := gasTestRunner(`
package main package main
@ -110,7 +110,7 @@ func TestInsecureMaxVersion(t *testing.T) {
func TestInsecureCipherSuite(t *testing.T) { func TestInsecureCipherSuite(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewModernTlsCheck()) analyzer.AddRule(NewModernTlsCheck(config))
issues := gasTestRunner(` issues := gasTestRunner(`
package main package main

View file

@ -15,9 +15,10 @@
package rules package rules
import ( import (
gas "github.com/HewlettPackard/gas/core"
"go/ast" "go/ast"
"regexp" "regexp"
gas "github.com/HewlettPackard/gas/core"
) )
type UsingUnsafe struct { type UsingUnsafe struct {
@ -32,7 +33,7 @@ func (r *UsingUnsafe) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err erro
return nil, nil return nil, nil
} }
func NewUsingUnsafe() (r gas.Rule, n ast.Node) { func NewUsingUnsafe(conf map[string]interface{}) (r gas.Rule, n ast.Node) {
r = &UsingUnsafe{ r = &UsingUnsafe{
pattern: regexp.MustCompile(`unsafe.*`), pattern: regexp.MustCompile(`unsafe.*`),
MetaData: gas.MetaData{ MetaData: gas.MetaData{

View file

@ -23,7 +23,7 @@ import (
func TestUnsafe(t *testing.T) { func TestUnsafe(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewUsingUnsafe()) analyzer.AddRule(NewUsingUnsafe(config))
issues := gasTestRunner(` issues := gasTestRunner(`
package main package main

View file

@ -34,7 +34,7 @@ func (r *UsesWeakCryptography) Match(n ast.Node, c *gas.Context) (*gas.Issue, er
} }
// Uses des.* md5.* or rc4.* // Uses des.* md5.* or rc4.*
func NewUsesWeakCryptography() (r gas.Rule, n ast.Node) { func NewUsesWeakCryptography(conf map[string]interface{}) (r gas.Rule, n ast.Node) {
r = &UsesWeakCryptography{ r = &UsesWeakCryptography{
pattern: regexp.MustCompile(`des\.NewCipher|des\.NewTripleDESCipher|md5\.New|md5\.Sum|rc4\.NewCipher`), pattern: regexp.MustCompile(`des\.NewCipher|des\.NewTripleDESCipher|md5\.New|md5\.Sum|rc4\.NewCipher`),
MetaData: gas.MetaData{ MetaData: gas.MetaData{

View file

@ -23,8 +23,8 @@ import (
func TestMD5(t *testing.T) { func TestMD5(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewBlacklistImports()) analyzer.AddRule(NewBlacklist_crypto_md5(config))
analyzer.AddRule(NewUsesWeakCryptography()) analyzer.AddRule(NewUsesWeakCryptography(config))
issues := gasTestRunner(` issues := gasTestRunner(`
package main package main
@ -45,8 +45,8 @@ func TestMD5(t *testing.T) {
func TestDES(t *testing.T) { func TestDES(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewBlacklistImports()) analyzer.AddRule(NewBlacklist_crypto_des(config))
analyzer.AddRule(NewUsesWeakCryptography()) analyzer.AddRule(NewUsesWeakCryptography(config))
issues := gasTestRunner(` issues := gasTestRunner(`
package main package main
@ -85,8 +85,8 @@ func TestDES(t *testing.T) {
func TestRC4(t *testing.T) { func TestRC4(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": false} config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil) analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewBlacklistImports()) analyzer.AddRule(NewBlacklist_crypto_rc4(config))
analyzer.AddRule(NewUsesWeakCryptography()) analyzer.AddRule(NewUsesWeakCryptography(config))
issues := gasTestRunner(` issues := gasTestRunner(`
package main package main