diff --git a/.gitignore b/.gitignore index b0326bd..c9c457c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ *.a *.so *.swp -gas # Folders _obj diff --git a/analyzer.go b/analyzer.go index b360945..e6329bd 100644 --- a/analyzer.go +++ b/analyzer.go @@ -82,27 +82,33 @@ type Analyzer struct { ignoreNosec bool ruleset RuleSet context *Context + config Config logger *log.Logger Issues []*Issue `json:"issues"` Stats *Metrics `json:"metrics"` } // NewAnalyzer builds a new anaylzer. -func NewAnalyzer(conf map[string]interface{}, logger *log.Logger) Analyzer { +func NewAnalyzer(conf Config, logger *log.Logger) Analyzer { if logger == nil { logger = log.New(os.Stdout, "[gas]", 0) } + ignoreNoSec := false + if val, err := conf.Get("ignoreNoSec"); err == nil { + if override, ok := val.(bool); ok { + ignoreNoSec = override + } + } a := Analyzer{ - ignoreNosec: conf["ignoreNosec"].(bool), + ignoreNosec: ignoreNoSec, ruleset: make(RuleSet), context: &Context{}, + config: conf, logger: logger, Issues: make([]*Issue, 0, 16), Stats: &Metrics{0, 0, 0, 0}, } - // TODO(tkelsey): use the inc/exc lists - return a } @@ -111,6 +117,7 @@ func (gas *Analyzer) process(filename string, source interface{}) error { gas.context.FileSet = token.NewFileSet() root, err := parser.ParseFile(gas.context.FileSet, filename, source, mode) if err == nil { + gas.context.Config = gas.config gas.context.Comments = ast.NewCommentMap(gas.context.FileSet, root, root.Comments) gas.context.Root = root @@ -171,6 +178,7 @@ func (gas *Analyzer) Process(filename string) error { func (gas *Analyzer) ProcessPackage(prog *loader.Program, pkg *loader.PackageInfo, file *ast.File) error { gas.context.FileSet = prog.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 diff --git a/cmd/filelist.go b/cmd/gas/filelist.go similarity index 100% rename from cmd/filelist.go rename to cmd/gas/filelist.go diff --git a/cmd/filelist_test.go b/cmd/gas/filelist_test.go similarity index 100% rename from cmd/filelist_test.go rename to cmd/gas/filelist_test.go diff --git a/cmd/gas/gas b/cmd/gas/gas new file mode 100755 index 0000000..cee60db Binary files /dev/null and b/cmd/gas/gas differ diff --git a/cmd/main.go b/cmd/gas/main.go similarity index 88% rename from cmd/main.go rename to cmd/gas/main.go index 7ecda5a..9844291 100644 --- a/cmd/main.go +++ b/cmd/gas/main.go @@ -29,6 +29,7 @@ import ( "github.com/GoASTScanner/gas" "github.com/GoASTScanner/gas/output" + "github.com/GoASTScanner/gas/rules" "golang.org/x/tools/go/loader" ) @@ -138,7 +139,7 @@ func usage() { fmt.Fprint(os.Stderr, "\n\nRULES:\n\n") // sorted rule list for eas of reading - rl := GetFullRuleList() + rl := rules.Generate() keys := make([]string, 0, len(rl)) for key := range rl { keys = append(keys, key) @@ -146,13 +147,13 @@ func usage() { sort.Strings(keys) for _, k := range keys { v := rl[k] - fmt.Fprintf(os.Stderr, "\t%s: %s\n", k, v.description) + fmt.Fprintf(os.Stderr, "\t%s: %s\n", k, v.Description) } fmt.Fprint(os.Stderr, "\n") } // TODO(gm) This needs to be refactored (potentially included in Analyzer) -func analyzePackage(packageDirectory string, metrics *gas.Metrics, config map[string]interface{}, logger *log.Logger) ([]*gas.Issue, error) { +func analyzePackage(packageDirectory string, metrics *gas.Metrics, config gas.Config, logger *log.Logger, ruleDefs rules.RuleList) ([]*gas.Issue, error) { basePackage, err := build.Default.ImportDir(packageDirectory, build.ImportComment) if err != nil { @@ -174,7 +175,9 @@ func analyzePackage(packageDirectory string, metrics *gas.Metrics, config map[st for _, pkg := range builtPackage.Created { analyzer := gas.NewAnalyzer(config, logger) - AddRules(&analyzer, config) + for _, rule := range ruleDefs { + analyzer.AddRule(rule.Create(config)) + } for _, file := range pkg.Files { analyzer.ProcessPackage(builtPackage, pkg, file) } @@ -227,10 +230,30 @@ func main() { os.Exit(0) } - config := buildConfig(incRules, excRules) + // Load config + config := gas.NewConfig() + if flagConfig != nil && *flagConfig != "" { + file, err := os.Open(*flagConfig) + if err != nil { + logger.Fatal(err) + } + defer file.Close() + if _, err := config.ReadFrom(file); err != nil { + logger.Fatal(err) + } + } + filters := make([]rules.RuleFilter, 0) + if incRules != "" { + including := strings.Split(incRules, ",") + filters = append(filters, rules.NewRuleFilter(false, including...)) + } + if excRules != "" { + excluding := strings.Split(excRules, ",") + filters = append(filters, rules.NewRuleFilter(true, excluding...)) + } + ruleDefinitions := rules.Generate(filters...) issues := make([]*gas.Issue, 0) metrics := &gas.Metrics{} - for _, arg := range flag.Args() { if arg == "./..." { baseDirectory, err := os.Getwd() @@ -246,7 +269,7 @@ func main() { log.Printf("Skipping %s\n", path) return filepath.SkipDir } - newIssues, err := analyzePackage(path, metrics, config, logger) + newIssues, err := analyzePackage(path, metrics, config, logger, ruleDefinitions) if err != nil { log.Println(err) } else { @@ -256,7 +279,7 @@ func main() { return nil }) } else { - newIssues, err := analyzePackage(arg, metrics, config, logger) + newIssues, err := analyzePackage(arg, metrics, config, logger, ruleDefinitions) if err != nil { log.Fatal(err) } diff --git a/cmd/main_test.go b/cmd/gas/main_test.go similarity index 100% rename from cmd/main_test.go rename to cmd/gas/main_test.go diff --git a/cmd/tools.go b/cmd/gas/tools.go similarity index 100% rename from cmd/tools.go rename to cmd/gas/tools.go diff --git a/cmd/rulelist.go b/cmd/rulelist.go deleted file mode 100644 index 807a1df..0000000 --- a/cmd/rulelist.go +++ /dev/null @@ -1,91 +0,0 @@ -// (c) Copyright 2016 Hewlett Packard Enterprise Development LP -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "go/ast" - - "github.com/GoASTScanner/gas" - "github.com/GoASTScanner/gas/rules" -) - -type RuleInfo struct { - description string - build func(map[string]interface{}) (gas.Rule, []ast.Node) -} - -// GetFullRuleList get the full list of all rules available to GAS -func GetFullRuleList() map[string]RuleInfo { - return map[string]RuleInfo{ - // misc - "G101": RuleInfo{"Look for hardcoded credentials", rules.NewHardcodedCredentials}, - "G102": RuleInfo{"Bind to all interfaces", rules.NewBindsToAllNetworkInterfaces}, - "G103": RuleInfo{"Audit the use of unsafe block", rules.NewUsingUnsafe}, - "G104": RuleInfo{"Audit errors not checked", rules.NewNoErrorCheck}, - "G105": RuleInfo{"Audit the use of big.Exp function", rules.NewUsingBigExp}, - - // injection - "G201": RuleInfo{"SQL query construction using format string", rules.NewSqlStrFormat}, - "G202": RuleInfo{"SQL query construction using string concatenation", rules.NewSqlStrConcat}, - "G203": RuleInfo{"Use of unescaped data in HTML templates", rules.NewTemplateCheck}, - "G204": RuleInfo{"Audit use of command execution", rules.NewSubproc}, - - // filesystem - "G301": RuleInfo{"Poor file permissions used when creating a directory", rules.NewMkdirPerms}, - "G302": RuleInfo{"Poor file permisions used when creation file or using chmod", rules.NewFilePerms}, - "G303": RuleInfo{"Creating tempfile using a predictable path", rules.NewBadTempFile}, - - // crypto - "G401": RuleInfo{"Detect the usage of DES, RC4, or MD5", rules.NewUsesWeakCryptography}, - "G402": RuleInfo{"Look for bad TLS connection settings", rules.NewIntermediateTlsCheck}, - "G403": RuleInfo{"Ensure minimum RSA key length of 2048 bits", rules.NewWeakKeyStrength}, - "G404": RuleInfo{"Insecure random number source (rand)", rules.NewWeakRandCheck}, - - // blacklist - "G501": RuleInfo{"Import blacklist: crypto/md5", rules.NewBlacklist_crypto_md5}, - "G502": RuleInfo{"Import blacklist: crypto/des", rules.NewBlacklist_crypto_des}, - "G503": RuleInfo{"Import blacklist: crypto/rc4", rules.NewBlacklist_crypto_rc4}, - "G504": RuleInfo{"Import blacklist: net/http/cgi", rules.NewBlacklist_net_http_cgi}, - } -} - -func AddRules(analyzer *gas.Analyzer, conf map[string]interface{}) { - var all map[string]RuleInfo - - inc := conf["include"].([]string) - exc := conf["exclude"].([]string) - - // 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 - } - } - } - - // remove excluded rules - for _, v := range exc { - delete(all, v) - } - - for _, v := range all { - analyzer.AddRule(v.build(conf)) - } -} diff --git a/config.go b/config.go new file mode 100644 index 0000000..2759950 --- /dev/null +++ b/config.go @@ -0,0 +1,80 @@ +package gas + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "io/ioutil" +) + +// Config is used to provide configuration and customization to each of the rules. +type Config map[string]interface{} + +// NewConfig initializes a new configuration instance. The configuration data then +// needs to be loaded via c.ReadFrom(strings.NewReader("config data")) +// or from a *os.File. +func NewConfig() Config { + return make(Config) +} + +// ReadFrom implements the io.ReaderFrom interface. This +// should be used with io.Reader to load configuration from +//file or from string etc. +func (c Config) ReadFrom(r io.Reader) (int64, error) { + data, err := ioutil.ReadAll(r) + if err != nil { + return int64(len(data)), err + } + if err = json.Unmarshal(data, c); err != nil { + return int64(len(data)), err + } + return int64(len(data)), nil +} + +// WriteTo implements the io.WriteTo interface. This should +// be used to save or print out the configuration information. +func (c Config) WriteTo(w io.Writer) (int64, error) { + data, err := json.Marshal(c) + if err != nil { + return int64(len(data)), err + } + return io.Copy(w, bytes.NewReader(data)) +} + +// EnableRule will change the rule to the specified enabled state +func (c Config) EnableRule(ruleID string, enabled bool) { + if data, found := c["rules"]; found { + if rules, ok := data.(map[string]bool); ok { + rules[ruleID] = enabled + } + } +} + +// Enabled returns a list of rules that are enabled +func (c Config) Enabled() []string { + if data, found := c["rules"]; found { + if rules, ok := data.(map[string]bool); ok { + enabled := make([]string, len(rules)) + for ruleID := range rules { + enabled = append(enabled, ruleID) + } + return enabled + } + } + return nil +} + +// Get returns the configuration section for a given rule +func (c Config) Get(ruleID string) (interface{}, error) { + section, found := c[ruleID] + if !found { + return nil, fmt.Errorf("Rule %s not in configuration", ruleID) + } + return section, nil +} + +// Set section for a given rule +func (c Config) Set(ruleID string, val interface{}) { + c[ruleID] = val +} diff --git a/rules/big.go b/rules/big.go index 9268b0f..dd37b5e 100644 --- a/rules/big.go +++ b/rules/big.go @@ -15,8 +15,9 @@ package rules import ( - "github.com/GoASTScanner/gas" "go/ast" + + "github.com/GoASTScanner/gas" ) type UsingBigExp struct { @@ -31,7 +32,7 @@ func (r *UsingBigExp) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err erro } return nil, nil } -func NewUsingBigExp(conf map[string]interface{}) (gas.Rule, []ast.Node) { +func NewUsingBigExp(conf gas.Config) (gas.Rule, []ast.Node) { return &UsingBigExp{ pkg: "*math/big.Int", calls: []string{"Exp"}, diff --git a/rules/bind.go b/rules/bind.go index b1f126e..0016016 100644 --- a/rules/bind.go +++ b/rules/bind.go @@ -39,7 +39,7 @@ func (r *BindsToAllNetworkInterfaces) Match(n ast.Node, c *gas.Context) (gi *gas return } -func NewBindsToAllNetworkInterfaces(conf map[string]interface{}) (gas.Rule, []ast.Node) { +func NewBindsToAllNetworkInterfaces(conf gas.Config) (gas.Rule, []ast.Node) { return &BindsToAllNetworkInterfaces{ call: regexp.MustCompile(`^(net|tls)\.Listen$`), pattern: regexp.MustCompile(`^(0.0.0.0|:).*$`), diff --git a/rules/blacklist.go b/rules/blacklist.go index cff1af1..895044e 100644 --- a/rules/blacklist.go +++ b/rules/blacklist.go @@ -34,7 +34,7 @@ func (r *BlacklistImport) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err return nil, nil } -func NewBlacklist_crypto_md5(conf map[string]interface{}) (gas.Rule, []ast.Node) { +func NewBlacklist_crypto_md5(conf gas.Config) (gas.Rule, []ast.Node) { return &BlacklistImport{ MetaData: gas.MetaData{ Severity: gas.High, @@ -45,7 +45,7 @@ func NewBlacklist_crypto_md5(conf map[string]interface{}) (gas.Rule, []ast.Node) }, []ast.Node{(*ast.ImportSpec)(nil)} } -func NewBlacklist_crypto_des(conf map[string]interface{}) (gas.Rule, []ast.Node) { +func NewBlacklist_crypto_des(conf gas.Config) (gas.Rule, []ast.Node) { return &BlacklistImport{ MetaData: gas.MetaData{ Severity: gas.High, @@ -56,7 +56,7 @@ func NewBlacklist_crypto_des(conf map[string]interface{}) (gas.Rule, []ast.Node) }, []ast.Node{(*ast.ImportSpec)(nil)} } -func NewBlacklist_crypto_rc4(conf map[string]interface{}) (gas.Rule, []ast.Node) { +func NewBlacklist_crypto_rc4(conf gas.Config) (gas.Rule, []ast.Node) { return &BlacklistImport{ MetaData: gas.MetaData{ Severity: gas.High, @@ -67,7 +67,7 @@ func NewBlacklist_crypto_rc4(conf map[string]interface{}) (gas.Rule, []ast.Node) }, []ast.Node{(*ast.ImportSpec)(nil)} } -func NewBlacklist_net_http_cgi(conf map[string]interface{}) (gas.Rule, []ast.Node) { +func NewBlacklist_net_http_cgi(conf gas.Config) (gas.Rule, []ast.Node) { return &BlacklistImport{ MetaData: gas.MetaData{ Severity: gas.High, diff --git a/rules/errors.go b/rules/errors.go index 46bd3d4..6ed0c82 100644 --- a/rules/errors.go +++ b/rules/errors.go @@ -70,7 +70,7 @@ func (r *NoErrorCheck) Match(n ast.Node, ctx *gas.Context) (*gas.Issue, error) { return nil, nil } -func NewNoErrorCheck(conf map[string]interface{}) (gas.Rule, []ast.Node) { +func NewNoErrorCheck(conf gas.Config) (gas.Rule, []ast.Node) { // TODO(gm) Come up with sensible defaults here. Or flip it to use a // black list instead. diff --git a/rules/fileperms.go b/rules/fileperms.go index 2ee5ec8..ec8295d 100644 --- a/rules/fileperms.go +++ b/rules/fileperms.go @@ -56,7 +56,7 @@ func (r *FilePermissions) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) return nil, nil } -func NewFilePerms(conf map[string]interface{}) (gas.Rule, []ast.Node) { +func NewFilePerms(conf gas.Config) (gas.Rule, []ast.Node) { mode := getConfiguredMode(conf, "G302", 0600) return &FilePermissions{ mode: mode, @@ -70,7 +70,7 @@ func NewFilePerms(conf map[string]interface{}) (gas.Rule, []ast.Node) { }, []ast.Node{(*ast.CallExpr)(nil)} } -func NewMkdirPerms(conf map[string]interface{}) (gas.Rule, []ast.Node) { +func NewMkdirPerms(conf gas.Config) (gas.Rule, []ast.Node) { mode := getConfiguredMode(conf, "G301", 0700) return &FilePermissions{ mode: mode, diff --git a/rules/hardcoded_credentials.go b/rules/hardcoded_credentials.go index 9c1d278..f4b4806 100644 --- a/rules/hardcoded_credentials.go +++ b/rules/hardcoded_credentials.go @@ -100,7 +100,7 @@ func (r *Credentials) matchGenDecl(decl *ast.GenDecl, ctx *gas.Context) (*gas.Is return nil, nil } -func NewHardcodedCredentials(conf map[string]interface{}) (gas.Rule, []ast.Node) { +func NewHardcodedCredentials(conf gas.Config) (gas.Rule, []ast.Node) { pattern := `(?i)passwd|pass|password|pwd|secret|token` entropyThreshold := 80.0 perCharThreshold := 3.0 diff --git a/rules/rand.go b/rules/rand.go index dae12f1..22ab48d 100644 --- a/rules/rand.go +++ b/rules/rand.go @@ -36,7 +36,7 @@ func (w *WeakRand) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) { return nil, nil } -func NewWeakRandCheck(conf map[string]interface{}) (gas.Rule, []ast.Node) { +func NewWeakRandCheck(conf gas.Config) (gas.Rule, []ast.Node) { return &WeakRand{ funcNames: []string{"Read", "Int"}, packagePath: "math/rand", diff --git a/rules/rsa.go b/rules/rsa.go index a24c986..ee9fec2 100644 --- a/rules/rsa.go +++ b/rules/rsa.go @@ -37,7 +37,7 @@ func (w *WeakKeyStrength) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) return nil, nil } -func NewWeakKeyStrength(conf map[string]interface{}) (gas.Rule, []ast.Node) { +func NewWeakKeyStrength(conf gas.Config) (gas.Rule, []ast.Node) { bits := 2048 return &WeakKeyStrength{ pattern: regexp.MustCompile(`^rsa\.GenerateKey$`), diff --git a/rules/rulelist.go b/rules/rulelist.go new file mode 100644 index 0000000..fff5cb2 --- /dev/null +++ b/rules/rulelist.go @@ -0,0 +1,87 @@ +// (c) Copyright 2016 Hewlett Packard Enterprise Development LP +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rules + +import ( + "go/ast" + + "github.com/GoASTScanner/gas" +) + +type RuleDefinition struct { + Description string + Create func(c gas.Config) (gas.Rule, []ast.Node) +} + +type RuleList map[string]RuleDefinition + +type RuleFilter func(string) bool + +func NewRuleFilter(action bool, ruleIDs ...string) RuleFilter { + rulelist := make(map[string]bool) + for _, rule := range ruleIDs { + rulelist[rule] = true + } + return func(rule string) bool { + if _, found := rulelist[rule]; found { + return action + } + return !action + } +} + +// Generate the list of rules to use +func Generate(filters ...RuleFilter) RuleList { + rules := map[string]RuleDefinition{ + // misc + "G101": RuleDefinition{"Look for hardcoded credentials", NewHardcodedCredentials}, + "G102": RuleDefinition{"Bind to all interfaces", NewBindsToAllNetworkInterfaces}, + "G103": RuleDefinition{"Audit the use of unsafe block", NewUsingUnsafe}, + "G104": RuleDefinition{"Audit errors not checked", NewNoErrorCheck}, + "G105": RuleDefinition{"Audit the use of big.Exp function", NewUsingBigExp}, + + // injection + "G201": RuleDefinition{"SQL query construction using format string", NewSqlStrFormat}, + "G202": RuleDefinition{"SQL query construction using string concatenation", NewSqlStrConcat}, + "G203": RuleDefinition{"Use of unescaped data in HTML templates", NewTemplateCheck}, + "G204": RuleDefinition{"Audit use of command execution", NewSubproc}, + + // filesystem + "G301": RuleDefinition{"Poor file permissions used when creating a directory", NewMkdirPerms}, + "G302": RuleDefinition{"Poor file permisions used when creation file or using chmod", NewFilePerms}, + "G303": RuleDefinition{"Creating tempfile using a predictable path", NewBadTempFile}, + + // crypto + "G401": RuleDefinition{"Detect the usage of DES, RC4, or MD5", NewUsesWeakCryptography}, + "G402": RuleDefinition{"Look for bad TLS connection settings", NewIntermediateTlsCheck}, + "G403": RuleDefinition{"Ensure minimum RSA key length of 2048 bits", NewWeakKeyStrength}, + "G404": RuleDefinition{"Insecure random number source (rand)", NewWeakRandCheck}, + + // blacklist + "G501": RuleDefinition{"Import blacklist: crypto/md5", NewBlacklist_crypto_md5}, + "G502": RuleDefinition{"Import blacklist: crypto/des", NewBlacklist_crypto_des}, + "G503": RuleDefinition{"Import blacklist: crypto/rc4", NewBlacklist_crypto_rc4}, + "G504": RuleDefinition{"Import blacklist: net/http/cgi", NewBlacklist_net_http_cgi}, + } + + for rule := range rules { + for _, filter := range filters { + if filter(rule) { + delete(rules, rule) + } + } + } + return rules +} diff --git a/rules/sql.go b/rules/sql.go index fd04b34..0bf7a00 100644 --- a/rules/sql.go +++ b/rules/sql.go @@ -56,7 +56,7 @@ func (s *SqlStrConcat) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) { return nil, nil } -func NewSqlStrConcat(conf map[string]interface{}) (gas.Rule, []ast.Node) { +func NewSqlStrConcat(conf gas.Config) (gas.Rule, []ast.Node) { return &SqlStrConcat{ SqlStatement: SqlStatement{ pattern: regexp.MustCompile(`(?)(SELECT|DELETE|INSERT|UPDATE|INTO|FROM|WHERE) `), @@ -84,7 +84,7 @@ func (s *SqlStrFormat) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err err return nil, nil } -func NewSqlStrFormat(conf map[string]interface{}) (gas.Rule, []ast.Node) { +func NewSqlStrFormat(conf gas.Config) (gas.Rule, []ast.Node) { return &SqlStrFormat{ call: regexp.MustCompile(`^fmt\.Sprintf$`), SqlStatement: SqlStatement{ diff --git a/rules/subproc.go b/rules/subproc.go index b16b3af..3c86620 100644 --- a/rules/subproc.go +++ b/rules/subproc.go @@ -49,7 +49,7 @@ func (r *Subprocess) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) { return nil, nil } -func NewSubproc(conf map[string]interface{}) (gas.Rule, []ast.Node) { +func NewSubproc(conf gas.Config) (gas.Rule, []ast.Node) { return &Subprocess{ pattern: regexp.MustCompile(`^exec\.Command|syscall\.Exec$`), }, []ast.Node{(*ast.CallExpr)(nil)} diff --git a/rules/tempfiles.go b/rules/tempfiles.go index 964db27..43c81bf 100644 --- a/rules/tempfiles.go +++ b/rules/tempfiles.go @@ -36,7 +36,7 @@ func (t *BadTempFile) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err erro return nil, nil } -func NewBadTempFile(conf map[string]interface{}) (gas.Rule, []ast.Node) { +func NewBadTempFile(conf gas.Config) (gas.Rule, []ast.Node) { return &BadTempFile{ call: regexp.MustCompile(`ioutil\.WriteFile|os\.Create`), args: regexp.MustCompile(`^/tmp/.*$|^/var/tmp/.*$`), diff --git a/rules/templates.go b/rules/templates.go index e83f24e..d185768 100644 --- a/rules/templates.go +++ b/rules/templates.go @@ -37,7 +37,7 @@ func (t *TemplateCheck) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err er return nil, nil } -func NewTemplateCheck(conf map[string]interface{}) (gas.Rule, []ast.Node) { +func NewTemplateCheck(conf gas.Config) (gas.Rule, []ast.Node) { return &TemplateCheck{ call: regexp.MustCompile(`^template\.(HTML|JS|URL)$`), MetaData: gas.MetaData{ diff --git a/rules/tls.go b/rules/tls.go index a2410b5..7448ef5 100644 --- a/rules/tls.go +++ b/rules/tls.go @@ -121,7 +121,7 @@ func (t *InsecureConfigTLS) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, er return } -func NewModernTlsCheck(conf map[string]interface{}) (gas.Rule, []ast.Node) { +func NewModernTlsCheck(conf gas.Config) (gas.Rule, []ast.Node) { // https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility return &InsecureConfigTLS{ pattern: regexp.MustCompile(`^tls\.Config$`), @@ -136,7 +136,7 @@ func NewModernTlsCheck(conf map[string]interface{}) (gas.Rule, []ast.Node) { }, []ast.Node{(*ast.CompositeLit)(nil)} } -func NewIntermediateTlsCheck(conf map[string]interface{}) (gas.Rule, []ast.Node) { +func NewIntermediateTlsCheck(conf gas.Config) (gas.Rule, []ast.Node) { // https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28default.29 return &InsecureConfigTLS{ pattern: regexp.MustCompile(`^tls\.Config$`), @@ -162,7 +162,7 @@ func NewIntermediateTlsCheck(conf map[string]interface{}) (gas.Rule, []ast.Node) }, []ast.Node{(*ast.CompositeLit)(nil)} } -func NewCompatTlsCheck(conf map[string]interface{}) (gas.Rule, []ast.Node) { +func NewCompatTlsCheck(conf gas.Config) (gas.Rule, []ast.Node) { // https://wiki.mozilla.org/Security/Server_Side_TLS#Old_compatibility_.28default.29 return &InsecureConfigTLS{ pattern: regexp.MustCompile(`^tls\.Config$`), diff --git a/rules/unsafe.go b/rules/unsafe.go index 611ef0c..6c7dc4c 100644 --- a/rules/unsafe.go +++ b/rules/unsafe.go @@ -33,7 +33,7 @@ func (r *UsingUnsafe) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err erro return nil, nil } -func NewUsingUnsafe(conf map[string]interface{}) (gas.Rule, []ast.Node) { +func NewUsingUnsafe(conf gas.Config) (gas.Rule, []ast.Node) { return &UsingUnsafe{ pkg: "unsafe", calls: []string{"Alignof", "Offsetof", "Sizeof", "Pointer"}, diff --git a/rules/weakcrypto.go b/rules/weakcrypto.go index ac2b55f..d157407 100644 --- a/rules/weakcrypto.go +++ b/rules/weakcrypto.go @@ -36,7 +36,7 @@ func (r *UsesWeakCryptography) Match(n ast.Node, c *gas.Context) (*gas.Issue, er } // Uses des.* md5.* or rc4.* -func NewUsesWeakCryptography(conf map[string]interface{}) (gas.Rule, []ast.Node) { +func NewUsesWeakCryptography(conf gas.Config) (gas.Rule, []ast.Node) { calls := make(map[string][]string) calls["crypto/des"] = []string{"NewCipher", "NewTripleDESCipher"} calls["crypto/md5"] = []string{"New", "Sum"}