Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit

Permalink
Merge pull request #4 from leeturner/LT-simple-conversion-case
Browse files Browse the repository at this point in the history
Basic json to markdown conversion
  • Loading branch information
leeturner authored Aug 22, 2022
2 parents 2fece05 + 9144996 commit d96aa8d
Show file tree
Hide file tree
Showing 9 changed files with 255 additions and 24 deletions.
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ clean:
rm -rf bin/

test-input: fmt vet build
${BIN_DARWIN} -i test-data/dummy-report.json
${BIN_DARWIN} -i test-data/test-report-1-vuln.json

test-input-debug: fmt vet build
${BIN_DARWIN} -d -i test-data/dummy-report.json
${BIN_DARWIN} -d -i test-data/test-report-1-vuln.json

test-input-pipe: fmt vet build
cat test-data/dummy-report.json | ${BIN_DARWIN}
cat test-data/test-report-1-vuln.json | ${BIN_DARWIN}

test-output-file: fmt vet build
cat test-data/dummy-report.json | ${BIN_DARWIN} -o ./test-output.md
cat test-data/test-report-1-vuln.json | ${BIN_DARWIN} -o ./test-output.md
2 changes: 1 addition & 1 deletion pkg/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ var (
os.Exit(1)
}

resultMarkdown, err := service.Convert(contents, logger)
resultMarkdown, err := service.Convert(contents, false, false, logger)
if err != nil {
logger.Error(err.Error())
os.Exit(1)
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/utilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func exportResults(outputProvided bool, fileName string, contents string, logger
}

func writeToFile(fileName string, contents string, logger zap.SugaredLogger) error {
logger.Debug("Writing to file...")
logger.Infof("Vulnerability snapshot saved at %s", fileName)
err := os.WriteFile(fileName, []byte(contents), 0644)
if err != nil {
return fmt.Errorf("Couldn't write to file: %s", err)
Expand Down
28 changes: 14 additions & 14 deletions pkg/cmd/utilities_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,29 @@ func TestGetFileContent(t *testing.T) {
log := zaptest.NewLogger(t)
logger := *log.Sugar()
tests := []struct {
testName string
jsonInput string
expectedMD string
expectedErr error
testName string
jsonInputFile string
expectedJson string
expectedErr error
}{
{
testName: "input file does not exist",
jsonInput: "./doesnt-exist.txt",
expectedMD: "",
expectedErr: errors.New("could not open the file"),
testName: "input file does not exist",
jsonInputFile: "./doesnt-exist.txt",
expectedJson: "",
expectedErr: errors.New("could not open the file"),
},
{
testName: "input file does exist",
jsonInput: "../../test-data/dummy-report.json",
expectedMD: `{"ok": false}`,
expectedErr: nil,
testName: "input file does exist",
jsonInputFile: "../../test-data/dummy-report.json",
expectedJson: `{"ok": false}`,
expectedErr: nil,
},
}

for _, data := range tests {
t.Run(data.testName, func(t *testing.T) {
resultMD, resultErr := getFileContent(data.jsonInput, logger)
assert.Equal(t, data.expectedMD, resultMD)
resultMD, resultErr := getFileContent(data.jsonInputFile, logger)
assert.Equal(t, data.expectedJson, resultMD)
assert.Equal(t, data.expectedErr, resultErr)
})
}
Expand Down
59 changes: 55 additions & 4 deletions pkg/service/convert.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,62 @@
package service

import (
"bytes"
"embed"
"encoding/json"
"errors"
"go.uber.org/zap"
"text/template"
)

func Convert(jsonInput string, logger zap.SugaredLogger) (string, error) {
logger.Debugf("Converting jsonInput... \n raw jsonInput: %s", jsonInput)
// TODO conversion
return jsonInput, nil
const (
defaultTemplate = "markdown.tmpl"
)

var (
//go:embed template/markdown.tmpl
content embed.FS
snykJson SnykJson
)

type Vulnerability struct {
Title string
ModuleName string
PackageName string
Language string
Description string
}

type SnykJson struct {
DisplayOnlySummary bool
DisplayRemediation bool
OK bool
Vulnerabilities []Vulnerability
DependencyCount int
}

func Convert(jsonInput string, displayOnlySummary bool, displayRemediation bool, logger zap.SugaredLogger) (string, error) {
logger.Debug("Converting json...")

err := json.Unmarshal([]byte(jsonInput), &snykJson)
if err != nil || snykJson.Vulnerabilities == nil {
logger.Error(err)
return "", errors.New("unable to parse snyk json")
}
snykJson.DisplayRemediation = displayRemediation
snykJson.DisplayOnlySummary = displayOnlySummary

var markdown bytes.Buffer
tmpl, err := template.New(defaultTemplate).ParseFS(content, "template/"+defaultTemplate)
if err != nil {
logger.Error(err)
return "", errors.New("unable to parse snyk template file")
}

err = tmpl.Execute(&markdown, snykJson)
if err != nil {
logger.Error(err)
return "", errors.New("unable to parse snyk template file")
}
return markdown.String(), nil
}
55 changes: 55 additions & 0 deletions pkg/service/convert_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package service

import (
"errors"
"github.com/stretchr/testify/assert"
"go.uber.org/zap/zaptest"
"os"
"testing"
)

func TestConvert(t *testing.T) {
log := zaptest.NewLogger(t)
logger := *log.Sugar()
tests := []struct {
testName string
jsonInput string
displayOnlySummary bool
displayRemediation bool
expectedMD string
expectedErr error
}{
{
testName: "invalid snyk json",
jsonInput: `{"invalid": "json"}`,
displayOnlySummary: false,
displayRemediation: false,
expectedMD: "",
expectedErr: errors.New("unable to parse snyk json"),
},
{
testName: "valid snyk json with 1 vulnerability",
jsonInput: readTestFileContents("test-report-1-vuln.json", t),
displayOnlySummary: false,
displayRemediation: false,
expectedMD: readTestFileContents("expected-test-report-1-vuln.md", t),
expectedErr: nil,
},
}

for _, data := range tests {
t.Run(data.testName, func(t *testing.T) {
resultMD, resultErr := Convert(data.jsonInput, data.displayOnlySummary, data.displayRemediation, logger)
assert.Equal(t, data.expectedMD, resultMD)
assert.Equal(t, data.expectedErr, resultErr)
})
}
}

func readTestFileContents(fileName string, t *testing.T) string {
contents, err := os.ReadFile("../../test-data/" + fileName)
if err != nil {
t.Errorf("unable to read test file %s: %s", fileName, err)
}
return string(contents)
}
13 changes: 13 additions & 0 deletions pkg/service/template/markdown.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Snyk test report

{{ .DependencyCount }} dependencies

{{ with .Vulnerabilities }}
{{ range .}}

# {{ .Title }}

{{ .Description }}

{{ end }}
{{ end }}
34 changes: 34 additions & 0 deletions test-data/expected-test-report-1-vuln.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Snyk test report

428 dependencies




# Regular Expression Denial of Service (ReDoS)

## Overview
[`brace-expansion`](https://www.npmjs.com/package/brace-expansion) is a package that performs brace expansion as known from sh/bash.
Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS) attacks.
Running:
```js
const expand = require('brace-expansion');
expand('{,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,\n}')
```
Will hang for long periods of time.

## Details
The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Many Regular Expression implementations may reach edge cases that causes them to work very slowly (exponentially related to input size), allowing an attacker to exploit this and can cause the program to enter these extreme situations by using a Regex string and cause the service to hang for a large periods of time.

You can read more about `Regular Expression Denial of Service (ReDoS)` on our [blog](https://snyk.io/blog/redos-and-catastrophic-backtracking/).

## Remediation
Upgrade `brace-expansion` to version 1.1.7 or higher.

## References
- [Github PR](https://github.com/juliangruber/brace-expansion/pull/35)
- [Github Issue](https://github.com/juliangruber/brace-expansion/issues/33)
- [Github Commit](https://github.com/juliangruber/brace-expansion/pull/35/commits/b13381281cead487cbdbfd6a69fb097ea5e456c3)



78 changes: 78 additions & 0 deletions test-data/test-report-1-vuln.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
{
"ok": false,
"vulnerabilities": [
{
"title": "Regular Expression Denial of Service (ReDoS)",
"credit": [
"kamael"
],
"moduleName": "brace-expansion",
"packageName": "brace-expansion",
"language": "js",
"packageManager": "npm",
"description": "## Overview\n[`brace-expansion`](https://www.npmjs.com/package/brace-expansion) is a package that performs brace expansion as known from sh/bash.\nAffected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS) attacks.\nRunning:\n```js\nconst expand = require('brace-expansion');\nexpand('{,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,\\n}')\n```\nWill hang for long periods of time.\n\n## Details\nThe Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Many Regular Expression implementations may reach edge cases that causes them to work very slowly (exponentially related to input size), allowing an attacker to exploit this and can cause the program to enter these extreme situations by using a Regex string and cause the service to hang for a large periods of time.\n\nYou can read more about `Regular Expression Denial of Service (ReDoS)` on our [blog](https://snyk.io/blog/redos-and-catastrophic-backtracking/).\n\n## Remediation\nUpgrade `brace-expansion` to version 1.1.7 or higher.\n\n## References\n- [Github PR](https://github.com/juliangruber/brace-expansion/pull/35)\n- [Github Issue](https://github.com/juliangruber/brace-expansion/issues/33)\n- [Github Commit](https://github.com/juliangruber/brace-expansion/pull/35/commits/b13381281cead487cbdbfd6a69fb097ea5e456c3)\n",
"identifiers": {
"CWE": [
"CWE-400"
],
"CVE": [],
"NSP": 338,
"ALTERNATIVE": [
"SNYK-JS-BRACEEXPANSION-10483"
]
},
"semver": {
"unaffected": ">=1.1.7",
"vulnerable": "<1.1.7"
},
"patches": [],
"severity": "medium",
"CVSSv3": "CVSS:3.0/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"disclosureTime": "2017-03-01T22:00:00.000Z",
"publicationTime": "2017-04-26T09:19:21.663Z",
"modificationTime": "2017-04-26T09:19:21.663Z",
"creationTime": "2017-04-26T09:19:21.663Z",
"id": "npm:brace-expansion:20170302",
"alternativeIds": [
"SNYK-JS-BRACEEXPANSION-10483"
],
"from": [
"goof@0.0.3",
"tap@5.8.0",
"nyc@6.6.1",
"glob@7.0.3",
"minimatch@3.0.0",
"brace-expansion@1.1.4"
],
"upgradePath": [
false,
"tap@5.8.0",
"nyc@6.6.1",
"glob@7.0.3",
"minimatch@3.0.0",
"brace-expansion@1.1.7"
],
"version": "1.1.4",
"name": "brace-expansion",
"isUpgradable": true,
"isPatchable": false,
"__filename": "/Users/dror/work/repos/snyk/goof/node_modules/nyc/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/package.json",
"bundled": [
"goof@0.0.3",
"nyc@6.6.1",
"spawn-wrap@1.2.3"
],
"parentDepType": "prod"
}
],
"dependencyCount": 428,
"org": "deebugger",
"licensesPolicy": null,
"summary": "33 vulnerable dependency paths",
"filtered": {
"ignore": [],
"patch": []
},
"uniqueCount": 18,
"packageManager": "npm"
}

0 comments on commit d96aa8d

Please sign in to comment.