Skip to content
This repository has been archived by the owner on Oct 17, 2024. It is now read-only.

Commit

Permalink
Semgrep producer (#66)
Browse files Browse the repository at this point in the history
* Add initial support for a semgrep producer

* Fix formatting issues
  • Loading branch information
alexplaskett authored Oct 28, 2020
1 parent 59b4fb2 commit a78ba3e
Show file tree
Hide file tree
Showing 6 changed files with 233 additions and 0 deletions.
36 changes: 36 additions & 0 deletions producers/semgrep/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
subinclude("@third_party/subrepos/pleasings//docker")

go_binary(
name = "semgrep",
srcs = [
"main.go",
],
deps = [
"//api/proto:v1",
"//producers",
"//producers/semgrep/types:semgrep-issue"
],
)

go_test(
name = "semgrep_test",
srcs = [
"main.go",
"main_test.go",
],
deps = [
"//api/proto:v1",
"//producers",
"//third_party/go:stretchr_testify",
"//producers/semgrep/types:semgrep-issue",
],
)

docker_image(
name = "image",
srcs = [
":semgrep",
],
base_image = "//build/docker:dracon-base-go",
image = "dracon-producer-semgrep",
)
5 changes: 5 additions & 0 deletions producers/semgrep/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM //build/docker:dracon-base-go

COPY semgrep /semgrep

ENTRYPOINT ["/semgrep"]
58 changes: 58 additions & 0 deletions producers/semgrep/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package main

import (
"fmt"
"log"

v1 "github.com/thought-machine/dracon/api/proto/v1"
types "github.com/thought-machine/dracon/producers/semgrep/types/semgrep-issue"

"github.com/thought-machine/dracon/producers"
)

func main() {
if err := producers.ParseFlags(); err != nil {
log.Fatal(err)
}
var results types.SemgrepResults
if err := producers.ParseInFileJSON(&results); err != nil {
log.Fatal(err)
}

issues := parseIssues(results)
if err := producers.WriteDraconOut(
"semgrep",
issues,
); err != nil {
log.Fatal(err)
}
}

func parseIssues(out types.SemgrepResults) []*v1.Issue {
issues := []*v1.Issue{}

results := out.Results

for _, r := range results {

// Map the semgrep severity levels to dracon severity levels
severityMap := map[string]v1.Severity{
"INFO": v1.Severity_SEVERITY_INFO,
"WARNING": v1.Severity_SEVERITY_MEDIUM,
"ERROR": v1.Severity_SEVERITY_HIGH,
}

sev := severityMap[r.Extra.Severity]

issues = append(issues, &v1.Issue{
Target: fmt.Sprintf("%s:%v-%v", r.Path, r.Start.Line, r.End.Line),
Type: r.Extra.Message,
Title: r.CheckID,
Severity: sev,
Cvss: 0.0,
Confidence: v1.Confidence_CONFIDENCE_MEDIUM,
Description: r.Extra.Lines,
})
}
return issues
}
87 changes: 87 additions & 0 deletions producers/semgrep/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package main

import (
v1 "github.com/thought-machine/dracon/api/proto/v1"
types "github.com/thought-machine/dracon/producers/semgrep/types/semgrep-issue"

"encoding/json"
"testing"

"github.com/stretchr/testify/assert"
)

const exampleOutput = `
{
"results": [
{
"check_id": "rules.go.xss.Go using template.HTML",
"path": "/src/go/xss/template-html.go",
"start": {"line": 10, "col": 11},
"end": {"line": 10, "col": 32},
"extra": {
"message": "Use of this type presents a security risk: the encapsulated content should come from a trusted source, \nas it will be included verbatim in the template output.\nhttps://blogtitle.github.io/go-safe-html/\n",
"metavars": {},
"metadata": {},
"severity": "WARNING",
"lines": "\t\t\treturn template.HTML(revStr)"
}
},
{
"check_id": "rules.python.grpc.GRPC Insecure Port",
"path": "/src/python/grpc/grpc_insecure_port.py",
"start": {"line": 19, "col": 5},
"end": {"line": 19, "col": 68},
"extra": {
"message": "The gRPC server listening port is configured insecurely, this offers no encryption and authentication.\nPlease review and ensure that this is appropriate for the communication. \n",
"metavars": {
"$VAR": {
"start": {"line": 19, "col": 5, "offset": 389},
"end": {"line": 19, "col": 20, "offset": 404},
"abstract_content": "insecure_server",
"unique_id": {
"type": "id", "value": "insecure_server",
"kind": "Local", "sid": 8
}
}
},
"metadata": {},
"severity": "WARNING",
"lines": " insecure_server.add_insecure_port('[::]:{}'.format(flags.port))"
}
}
]
}
`

func TestParseIssues(t *testing.T) {
semgrepResults := types.SemgrepResults{}
err := json.Unmarshal([]byte(exampleOutput), &semgrepResults)

assert.Nil(t, err)
issues := parseIssues(semgrepResults)

expectedIssue := &v1.Issue{
Target: "/src/go/xss/template-html.go:10-10",
Type: "Use of this type presents a security risk: the encapsulated content should come from a trusted source, \nas it will be included verbatim in the template output.\nhttps://blogtitle.github.io/go-safe-html/\n",
Title: "rules.go.xss.Go using template.HTML",
Severity: v1.Severity_SEVERITY_MEDIUM,
Cvss: 0.0,
Confidence: v1.Confidence_CONFIDENCE_MEDIUM,
Description: "\t\t\treturn template.HTML(revStr)",
}

assert.Equal(t, expectedIssue, issues[0])

expectedIssue2 := &v1.Issue{
Target: "/src/python/grpc/grpc_insecure_port.py:19-19",
Type: "The gRPC server listening port is configured insecurely, this offers no encryption and authentication.\nPlease review and ensure that this is appropriate for the communication. \n",
Title: "rules.python.grpc.GRPC Insecure Port",
Severity: v1.Severity_SEVERITY_MEDIUM,
Cvss: 0.0,
Confidence: v1.Confidence_CONFIDENCE_MEDIUM,
Description: " insecure_server.add_insecure_port('[::]:{}'.format(flags.port))",
}

assert.Equal(t, expectedIssue2, issues[1])

}
9 changes: 9 additions & 0 deletions producers/semgrep/types/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

go_library(
name = "semgrep-issue",
srcs = [
"semgrep-issue.go",
],
visibility = ["//producers/semgrep/..."]

)
38 changes: 38 additions & 0 deletions producers/semgrep/types/semgrep-issue.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package types

// Position represents where in the file the finding is located
type Position struct {
Col int `json:"col"`
Line int `json:"line"`
}

// Extra contains extra info needed for semgrep issue
type Extra struct {
Message string `json:"message"`
Metavars Metavars `json:"metavars"`
Metadata Metadata `json:"metadata"`
Severity string `json:"severity"`
Lines string `json:"lines"`
}

// SemgrepIssue represents a semgrep issue
type SemgrepIssue struct {
CheckID string `json:"check_id"`
Path string `json:"path"`
Start Position `json:"start"`
End Position `json:"end"`
Extra Extra `json:"extra"`
}

// SemgrepResults represents a series of semgrep issues
type SemgrepResults struct {
Results []SemgrepIssue `'json:"results"`
}

// Metavars currently is empty but could represent more metavariables for semgrep
type Metavars struct {
}

// Metadata currently is empty, however, could represent semgrep issue metadata going forward.
type Metadata struct {
}

0 comments on commit a78ba3e

Please sign in to comment.