Skip to content

Commit

Permalink
Generate the SARIF types, handle taxonomies and separate responsibili…
Browse files Browse the repository at this point in the history
…ties
  • Loading branch information
mmorel-35 authored May 5, 2021
1 parent 0fa5d0b commit cc83d4c
Show file tree
Hide file tree
Showing 13 changed files with 2,011 additions and 279 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,22 @@ You can build the binary with:
make
```

### Note on Sarif Types Generation

Install the tool with :
```bash
go get -u github.com/a-h/generate/cmd/schema-generate
```

Then generate the types with :
```bash
schema-generate -i sarif-schema-2.1.0.json -o mypath/types.go
```

Most of the MarshallJSON/UnmarshalJSON are removed except the one for PropertyBag which is handy to inline the additionnal properties. The rest can be removed.
The URI,ID, UUID, GUID were renamed so it fits the Golang convention defined [here](https://github.com/golang/lint/blob/master/lint.go#L700)


### Tests

You can run all unit tests using:
Expand Down
109 changes: 109 additions & 0 deletions cwe/data.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package cwe

var data = map[string]Weakness{
"118": {
ID: "118",
Description: "The software does not restrict or incorrectly restricts operations within the boundaries of a resource that is accessed using an index or pointer, such as memory or files.",
Name: "Incorrect Access of Indexable Resource ('Range Error')",
},
"190": {
ID: "190",
Description: "The software performs a calculation that can produce an integer overflow or wraparound, when the logic assumes that the resulting value will always be larger than the original value. This can introduce other weaknesses when the calculation is used for resource management or execution control.",
Name: "Integer Overflow or Wraparound",
},
"200": {
ID: "200",
Description: "The product exposes sensitive information to an actor that is not explicitly authorized to have access to that information.",
Name: "Exposure of Sensitive Information to an Unauthorized Actor",
},
"22": {
ID: "22",
Description: "The software uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the software does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.",
Name: "Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')",
},
"242": {
ID: "242",
Description: "The program calls a function that can never be guaranteed to work safely.",
Name: "Use of Inherently Dangerous Function",
},
"276": {
ID: "276",
Description: "During installation, installed file permissions are set to allow anyone to modify those files.",
Name: "Incorrect Default Permissions",
},
"295": {
ID: "295",
Description: "The software does not validate, or incorrectly validates, a certificate.",
Name: "Improper Certificate Validation",
},
"310": {
ID: "310",
Description: "Weaknesses in this category are related to the design and implementation of data confidentiality and integrity. Frequently these deal with the use of encoding techniques, encryption libraries, and hashing algorithms. The weaknesses in this category could lead to a degradation of the quality data if they are not addressed.",
Name: "Cryptographic Issues",
},
"322": {
ID: "322",
Description: "The software performs a key exchange with an actor without verifying the identity of that actor.",
Name: "Key Exchange without Entity Authentication",
},
"326": {
ID: "326",
Description: "The software stores or transmits sensitive data using an encryption scheme that is theoretically sound, but is not strong enough for the level of protection required.",
Name: "Inadequate Encryption Strength",
},
"327": {
ID: "327",
Description: "The use of a broken or risky cryptographic algorithm is an unnecessary risk that may result in the exposure of sensitive information.",
Name: "Use of a Broken or Risky Cryptographic Algorithm",
},
"338": {
ID: "338",
Description: "The product uses a Pseudo-Random Number Generator (PRNG) in a security context, but the PRNG's algorithm is not cryptographically strong.",
Name: "Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG)",
},
"377": {
ID: "377",
Description: "Creating and using insecure temporary files can leave application and system data vulnerable to attack.",
Name: "Insecure Temporary File",
},
"409": {
ID: "409",
Description: "The software does not handle or incorrectly handles a compressed input with a very high compression ratio that produces a large output.",
Name: "Improper Handling of Highly Compressed Data (Data Amplification)",
},
"703": {
ID: "703",
Description: "The software does not properly anticipate or handle exceptional conditions that rarely occur during normal operation of the software.",
Name: "Improper Check or Handling of Exceptional Conditions",
},
"78": {
ID: "78",
Description: "The software constructs all or part of an OS command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended OS command when it is sent to a downstream component.",
Name: "Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')",
},
"79": {
ID: "79",
Description: "The software does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.",
Name: "Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')",
},
"798": {
ID: "798",
Description: "The software contains hard-coded credentials, such as a password or cryptographic key, which it uses for its own inbound authentication, outbound communication to external components, or encryption of internal data.",
Name: "Use of Hard-coded Credentials",
},
"88": {
ID: "88",
Description: "The software constructs a string for a command to executed by a separate component\nin another control sphere, but it does not properly delimit the\nintended arguments, options, or switches within that command string.",
Name: "Improper Neutralization of Argument Delimiters in a Command ('Argument Injection')",
},
"89": {
ID: "89",
Description: "The software constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component.",
Name: "Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')",
},
}

//Get Retrieves a CWE weakness by it's id
func Get(id string) Weakness {
return data[id]
}
17 changes: 17 additions & 0 deletions cwe/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package cwe

import (
"fmt"
)

// Weakness defines a CWE weakness based on http://cwe.mitre.org/data/xsd/cwe_schema_v6.4.xsd
type Weakness struct {
ID string
Name string
Description string
}

//URL Expose the CWE URL
func (w *Weakness) URL() string {
return fmt.Sprintf("https://cwe.mitre.org/data/definitions/%s.html", w.ID)
}
12 changes: 12 additions & 0 deletions formatter/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package formatter

import (
"github.com/securego/gosec/v2"
)

//ReportInfo this is report information
type ReportInfo struct {
Errors map[string][]gosec.Error `json:"Golang errors"`
Issues []*gosec.Issue
Stats *gosec.Metrics
}
3 changes: 1 addition & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
module github.com/securego/gosec/v2

require (
github.com/google/uuid v1.1.1
github.com/gookit/color v1.4.2
github.com/lib/pq v1.10.1 // indirect
github.com/mozilla/tls-observatory v0.0.0-20210209181001-cf43108d6880
github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354
github.com/onsi/ginkgo v1.16.1
github.com/onsi/gomega v1.11.0
golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e // indirect
golang.org/x/mod v0.4.1 // indirect
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect
golang.org/x/text v0.3.5 // indirect
Expand Down
7 changes: 3 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4
github.com/google/trillian v1.3.11/go.mod h1:0tPraVHrSDkA3BO6vKX67zgLXs6SsOAbHEivX+9mPgw=
github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
Expand Down Expand Up @@ -215,9 +216,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/letsencrypt/pkcs11key/v4 v4.0.0/go.mod h1:EFUvBDay26dErnNb70Nd0/VW3tJiIbETBPTl9ATXQag=
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8=
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.1 h1:6VXZrLU0jHBYyAqrSPa+MgPfnSvTPuMgK+k0o5kVFWo=
github.com/lib/pq v1.10.1/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
Expand Down Expand Up @@ -366,9 +366,8 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e h1:8foAy0aoO5GkqCvAEJ4VC4P3zksTg4X4aJCDpZzmgQI=
golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
Expand Down
90 changes: 13 additions & 77 deletions output/formatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import (

color "github.com/gookit/color"
"github.com/securego/gosec/v2"
"github.com/securego/gosec/v2/formatter"
"github.com/securego/gosec/v2/sarif"
"gopkg.in/yaml.v2"
)

Expand Down Expand Up @@ -76,16 +78,10 @@ Golang errors in file: [{{ $filePath }}]:
`

type reportInfo struct {
Errors map[string][]gosec.Error `json:"Golang errors"`
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, yaml, csv, junit-xml, html, sonarqube, golint and text.
func CreateReport(w io.Writer, format string, enableColor bool, rootPaths []string, issues []*gosec.Issue, metrics *gosec.Metrics, errors map[string][]gosec.Error) error {
data := &reportInfo{
data := &formatter.ReportInfo{
Errors: errors,
Issues: issues,
Stats: metrics,
Expand Down Expand Up @@ -116,7 +112,7 @@ func CreateReport(w io.Writer, format string, enableColor bool, rootPaths []stri
return err
}

func reportSonarqube(rootPaths []string, w io.Writer, data *reportInfo) error {
func reportSonarqube(rootPaths []string, w io.Writer, data *formatter.ReportInfo) error {
si, err := convertToSonarIssues(rootPaths, data)
if err != nil {
return err
Expand All @@ -129,67 +125,7 @@ func reportSonarqube(rootPaths []string, w io.Writer, data *reportInfo) error {
return err
}

func convertToSarifReport(rootPaths []string, data *reportInfo) (*sarifReport, error) {
sr := buildSarifReport()

type rule struct {
index int
rule *sarifRule
}

rules := make([]*sarifRule, 0)
rulesIndices := make(map[string]rule)
lastRuleIndex := -1

results := []*sarifResult{}

for _, issue := range data.Issues {
r, ok := rulesIndices[issue.RuleID]
if !ok {
lastRuleIndex++
r = rule{index: lastRuleIndex, rule: buildSarifRule(issue)}
rulesIndices[issue.RuleID] = r
rules = append(rules, r.rule)
}

location, err := buildSarifLocation(issue, rootPaths)
if err != nil {
return nil, err
}

result := &sarifResult{
RuleID: r.rule.ID,
RuleIndex: r.index,
Level: getSarifLevel(issue.Severity.String()),
Message: &sarifMessage{
Text: issue.What,
},
Locations: []*sarifLocation{location},
}

results = append(results, result)
}

tool := &sarifTool{
Driver: &sarifDriver{
Name: "gosec",
Version: "2.1.0",
InformationURI: "https://github.com/securego/gosec/",
Rules: rules,
},
}

run := &sarifRun{
Tool: tool,
Results: results,
}

sr.Runs = append(sr.Runs, run)

return sr, nil
}

func reportJSON(w io.Writer, data *reportInfo) error {
func reportJSON(w io.Writer, data *formatter.ReportInfo) error {
raw, err := json.MarshalIndent(data, "", "\t")
if err != nil {
return err
Expand All @@ -199,7 +135,7 @@ func reportJSON(w io.Writer, data *reportInfo) error {
return err
}

func reportYAML(w io.Writer, data *reportInfo) error {
func reportYAML(w io.Writer, data *formatter.ReportInfo) error {
raw, err := yaml.Marshal(data)
if err != nil {
return err
Expand All @@ -208,7 +144,7 @@ func reportYAML(w io.Writer, data *reportInfo) error {
return err
}

func reportCSV(w io.Writer, data *reportInfo) error {
func reportCSV(w io.Writer, data *formatter.ReportInfo) error {
out := csv.NewWriter(w)
defer out.Flush()
for _, issue := range data.Issues {
Expand All @@ -228,7 +164,7 @@ func reportCSV(w io.Writer, data *reportInfo) error {
return nil
}

func reportGolint(w io.Writer, data *reportInfo) error {
func reportGolint(w io.Writer, data *formatter.ReportInfo) error {
// Output Sample:
// /tmp/main.go:11:14: [CWE-310] RSA keys should be at least 2048 bits (Rule:G403, Severity:MEDIUM, Confidence:HIGH)

Expand Down Expand Up @@ -258,7 +194,7 @@ func reportGolint(w io.Writer, data *reportInfo) error {
return nil
}

func reportJUnitXML(w io.Writer, data *reportInfo) error {
func reportJUnitXML(w io.Writer, data *formatter.ReportInfo) error {
junitXMLStruct := createJUnitXMLStruct(data)
raw, err := xml.MarshalIndent(junitXMLStruct, "", "\t")
if err != nil {
Expand All @@ -275,8 +211,8 @@ func reportJUnitXML(w io.Writer, data *reportInfo) error {
return nil
}

func reportSARIFTemplate(rootPaths []string, w io.Writer, data *reportInfo) error {
sr, err := convertToSarifReport(rootPaths, data)
func reportSARIFTemplate(rootPaths []string, w io.Writer, data *formatter.ReportInfo) error {
sr, err := sarif.ConvertToSarifReport(rootPaths, data)
if err != nil {
return err
}
Expand All @@ -289,7 +225,7 @@ func reportSARIFTemplate(rootPaths []string, w io.Writer, data *reportInfo) erro
return err
}

func reportFromPlaintextTemplate(w io.Writer, reportTemplate string, enableColor bool, data *reportInfo) error {
func reportFromPlaintextTemplate(w io.Writer, reportTemplate string, enableColor bool, data *formatter.ReportInfo) error {
t, e := plainTemplate.
New("gosec").
Funcs(plainTextFuncMap(enableColor)).
Expand All @@ -301,7 +237,7 @@ func reportFromPlaintextTemplate(w io.Writer, reportTemplate string, enableColor
return t.Execute(w, data)
}

func reportFromHTMLTemplate(w io.Writer, reportTemplate string, data *reportInfo) error {
func reportFromHTMLTemplate(w io.Writer, reportTemplate string, data *formatter.ReportInfo) error {
t, e := htmlTemplate.New("gosec").Parse(reportTemplate)
if e != nil {
return e
Expand Down
Loading

0 comments on commit cc83d4c

Please sign in to comment.