|
| 1 | +# Contributing |
| 2 | + |
| 3 | +## Adding a new rule |
| 4 | + |
| 5 | +New rules can be implemented in two ways: |
| 6 | + |
| 7 | +- as a `gosec.Rule` -- these define an arbitrary function which will be called on every AST node in the analyzed file, and are appropriate for rules that mostly need to reason about a single statement. |
| 8 | +- as an Analyzer -- these can operate on the entire program, and receive an [SSA](https://pkg.go.dev/golang.org/x/tools/go/ssa) representation of the package. This type of rule is useful when you need to perform a more complex analysis that requires a great deal of context. |
| 9 | + |
| 10 | +### Adding a gosec.Rule |
| 11 | + |
| 12 | +1. Copy an existing rule file as a starting point-- `./rules/unsafe.go` is a good option, as it implements a very simple rule with no additional supporting logic. Put the copied file in the `./rules/` directory. |
| 13 | +2. Change the name of the rule constructor function and of the types in the rule file you've copied so they will be unique. |
| 14 | +3. Edit the `Generate` function in `./rules/rulelist.go` to include your rule. |
| 15 | +4. Add a RuleID to CWE ID mapping for your rule to the `ruleToCWE` map in `./issue/issue.go`. If you need a CWE that isn't already defined in `./cwe/data.go`, add it to the `idWeaknessess` map in that file. |
| 16 | +5. Use `make` to compile `gosec`. The binary will now contain your rule. |
| 17 | + |
| 18 | +To make your rule actually useful, you will likely want to use the support functions defined in `./resolve.go`, `./helpers.go` and `./call_list.go`. There are inline comments explaining the purpose of most of these functions, and you can find usage examples in the existing rule files. |
| 19 | + |
| 20 | +### Adding an Analyzer |
| 21 | + |
| 22 | +1. Create a new go file under `./analyzers/` with the following scaffolding in it: |
| 23 | + |
| 24 | +```go |
| 25 | +package analyzers |
| 26 | + |
| 27 | +import ( |
| 28 | + "fmt" |
| 29 | + |
| 30 | + "golang.org/x/tools/go/analysis" |
| 31 | + "golang.org/x/tools/go/analysis/passes/buildssa" |
| 32 | + "github.com/securego/gosec/v2/issue" |
| 33 | +) |
| 34 | + |
| 35 | +const defaultIssueDescriptionMyAnalyzer = "My new analyzer!" |
| 36 | + |
| 37 | +func newMyAnalyzer(id string, description string) *analysis.Analyzer { |
| 38 | + return &analysis.Analyzer{ |
| 39 | + Name: id, |
| 40 | + Doc: description, |
| 41 | + Run: runMyAnalyzer, |
| 42 | + Requires: []*analysis.Analyzer{buildssa.Analyzer}, |
| 43 | + } |
| 44 | +} |
| 45 | + |
| 46 | +func runMyAnalyzer(pass *analysis.Pass) (interface{}, error) { |
| 47 | + ssaResult, err := getSSAResult(pass) |
| 48 | + if err != nil { |
| 49 | + return nil, fmt.Errorf("building ssa representation: %w", err) |
| 50 | + } |
| 51 | + var issues []*issue.Issue |
| 52 | + fmt.Printf("My Analyzer ran! %+v\n", ssaResult) |
| 53 | + |
| 54 | + return issues, nil |
| 55 | +} |
| 56 | +``` |
| 57 | + |
| 58 | +2. Add the analyzer to `./analyzers/analyzerslist.go` in the `defaultAnalyzers` variable under an entry like `{"G999", "My test analyzer", newMyAnalyzer}` |
| 59 | +3. Add a RuleID to CWE ID mapping for your rule to the `ruleToCWE` map in `./issue/issue.go`. If you need a CWE that isn't already defined in `./cwe/data.go`, add it to the `idWeaknessess` map in that file. |
| 60 | +4. `make`; then run the `gosec` binary produced. You should see the output from our print statement. |
| 61 | +5. You now have a working example analyzer to play with-- look at the other implemented analyzers for ideas on how to make useful rules. |
| 62 | + |
| 63 | +## Developing your rule |
| 64 | + |
| 65 | +There are some utility tools which are useful for analyzing the SSA and AST representation `gosec` works with before writing rules or analyzers. |
| 66 | + |
| 67 | +For instance to dump the SSA, the [ssadump](https://pkg.go.dev/golang.org/x/tools/cmd/ssadump) tool can be used as following: |
| 68 | + |
| 69 | +```bash |
| 70 | +ssadump -build F main.go |
| 71 | +``` |
| 72 | + |
| 73 | +Consult the documentation for ssadump for an overview of available output flags and options. |
| 74 | + |
| 75 | +For outputting the AST and supporting information, there is a utility tool in <https://github.com/securego/gosec/blob/master/cmd/gosecutil/tools.go> which can be compiled and used as standalone. |
| 76 | + |
| 77 | +```bash |
| 78 | +gosecutil -tool ast main.go |
| 79 | +``` |
| 80 | + |
| 81 | +Valid tool arguments for this command are `ast`, `callobj`, `uses`, `types`, `defs`, `comments`, and `imports`. |
0 commit comments