Skip to content

Commit

Permalink
test: improve test coverage of snyk package
Browse files Browse the repository at this point in the history
  • Loading branch information
mcombuechen authored and garethr committed Aug 13, 2023
1 parent 52a3757 commit f74b3a6
Show file tree
Hide file tree
Showing 6 changed files with 260 additions and 15 deletions.
6 changes: 5 additions & 1 deletion lib/snyk/enrich_cyclonedx.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,11 @@ func enrichCycloneDX(bom *cdx.BOM) *cdx.BOM {
}
}
}
bom.Vulnerabilities = &vulns

if len(vulns) > 0 {
bom.Vulnerabilities = &vulns
}

return bom
}

Expand Down
117 changes: 117 additions & 0 deletions lib/snyk/enrich_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package snyk

import (
"testing"

cdx "github.com/CycloneDX/cyclonedx-go"
"github.com/jarcoal/httpmock"
spdx "github.com/spdx/tools-golang/spdx/v2/common"
spdx_2_3 "github.com/spdx/tools-golang/spdx/v2/v2_3"
"github.com/stretchr/testify/assert"

"github.com/snyk/parlay/lib/sbom"
)

func TestEnrichSBOM_CycloneDXWithVulnerabilities(t *testing.T) {
teardown := setupTestEnv(t)
defer teardown()

bom := &cdx.BOM{
Components: &[]cdx.Component{
{
BOMRef: "pkg:pypi/[email protected]",
Name: "numpy",
Version: "1.16.0",
PackageURL: "pkg:pypi/[email protected]",
},
},
}
doc := &sbom.SBOMDocument{BOM: bom}

EnrichSBOM(doc)

assert.NotNil(t, bom.Vulnerabilities)
assert.Len(t, *bom.Vulnerabilities, 1)
vuln := (*bom.Vulnerabilities)[0]
assert.Equal(t, "pkg:pypi/[email protected]", vuln.BOMRef)
assert.Equal(t, "SNYK-PYTHON-NUMPY-73513", vuln.ID)
}

func TestEnrichSBOM_CycloneDXWithoutVulnerabilities(t *testing.T) {
teardown := setupTestEnv(t)
defer teardown()

bom := &cdx.BOM{
Components: &[]cdx.Component{
{
BOMRef: "pkg:pypi/[email protected]",
Name: "werkzeug",
Version: "2.2.3",
PackageURL: "pkg:pypi/[email protected]",
},
},
}
doc := &sbom.SBOMDocument{BOM: bom}

EnrichSBOM(doc)

assert.Nil(t, bom.Vulnerabilities, "should not extend vulnerabilities if there are none")
}

func TestEnrichSBOM_SPDXWithVulnerabilities(t *testing.T) {
teardown := setupTestEnv(t)
defer teardown()

bom := &spdx_2_3.Document{
Packages: []*spdx_2_3.Package{
{
PackageSPDXIdentifier: "pkg:pypi/[email protected]",
PackageName: "numpy",
PackageVersion: "1.16.0",
PackageExternalReferences: []*spdx_2_3.PackageExternalReference{
{
Category: spdx.CategoryPackageManager,
RefType: "purl",
Locator: "pkg:pypi/[email protected]",
},
},
},
},
}
doc := &sbom.SBOMDocument{BOM: bom}

EnrichSBOM(doc)

vulnRef := bom.Packages[0].PackageExternalReferences[1]
assert.Equal(t, "SECURITY", vulnRef.Category)
assert.Equal(t, "advisory", vulnRef.RefType)
assert.Equal(t, "https://security.snyk.io/vuln/SNYK-PYTHON-NUMPY-73513", vulnRef.Locator)
assert.Equal(t, "Arbitrary Code Execution", vulnRef.ExternalRefComment)
}

func setupTestEnv(t *testing.T) func() {
t.Helper()

t.Setenv("SNYK_TOKEN", "asdf")

httpmock.Activate()
httpmock.RegisterResponder(
"GET",
`=~^https://api\.snyk\.io/rest/self`,
httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/self.json")),
)
httpmock.RegisterResponder(
"GET",
`=~^https://api\.snyk\.io/rest/orgs/[a-z0-9-]+/packages/pkg%3Apypi%2Fnumpy%401.16.0/issues`,
httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/numpy_issues.json")),
)
httpmock.RegisterResponder(
"GET",
`=~^https://api\.snyk\.io/rest/orgs/[a-z0-9-]+/packages/.*/issues`,
httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/no_issues.json")),
)

return func() {
httpmock.DeactivateAndReset()
}
}
16 changes: 2 additions & 14 deletions lib/snyk/self_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package snyk

import (
"net/http"
"testing"

"github.com/deepmap/oapi-codegen/pkg/securityprovider"
Expand All @@ -28,25 +27,14 @@ import (
)

func TestGetSnykOrg(t *testing.T) {
expectedOrg := uuid.New()
expectedOrg := uuid.MustParse("00000000-0000-0000-0000-000000000000")
auth, err := securityprovider.NewSecurityProviderApiKey("header", "name", "value")
require.NoError(t, err)

httpmock.Activate()
defer httpmock.DeactivateAndReset()
httpmock.RegisterResponder("GET", "https://api.snyk.io/rest/self",
func(req *http.Request) (*http.Response, error) {
jsonBody := `{
"data": {
"attributes": {
"default_org_context": "` + expectedOrg.String() + `"
}
}
}`
resp := httpmock.NewStringResponse(200, jsonBody)
resp.Header.Set("Content-Type", "application/json")
return resp, nil
},
httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/self.json")),
)

actualOrg, err := getSnykOrg(auth)
Expand Down
12 changes: 12 additions & 0 deletions lib/snyk/testdata/no_issues.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"jsonapi": {
"version": "1.0"
},
"data": [],
"links": {
"self": "/orgs/00000000-0000-0000-0000-000000000000/packages/pkg%3A/issues?version=2023-06-01&limit=1000&offset=0"
},
"meta": {
"package": {}
}
}
106 changes: 106 additions & 0 deletions lib/snyk/testdata/numpy_issues.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
{
"jsonapi": {
"version": "1.0"
},
"data": [
{
"id": "SNYK-PYTHON-NUMPY-73513",
"type": "issue",
"attributes": {
"key": "SNYK-PYTHON-NUMPY-73513",
"title": "Arbitrary Code Execution",
"type": "package_vulnerability",
"created_at": "2019-01-16T14:11:37.000761Z",
"updated_at": "2022-09-01T16:21:50.298458Z",
"description": "## Overview\n[numpy](https://github.com/numpy/numpy) is a fundamental package needed for scientific computing with Python.\n\nAffected versions of this package are vulnerable to Arbitrary Code Execution. It uses the pickle Python module unsafely, which allows remote attackers to execute arbitrary code via a crafted serialized object, as demonstrated by a `numpy.load` call.\r\n\r\nPoC by nanshihui:\r\n```py\r\nimport numpy\r\nfrom numpy import __version__\r\nprint __version__\r\nimport os\r\nimport pickle\r\nclass Test(object):\r\n def __init__(self):\r\n self.a = 1\r\n\r\n def __reduce__(self):\r\n return (os.system,('ls',))\r\ntmpdaa = Test()\r\nwith open(\"a-file.pickle\",'wb') as f:\r\n pickle.dump(tmpdaa,f)\r\nnumpy.load('a-file.pickle')\r\n```\n## Remediation\nUpgrade `numpy` to version 1.16.3 or higher.\n## References\n- [GitHub Commit](https://github.com/numpy/numpy/commit/89b688732b37616c9d26623f81aaee1703c30ffb)\n- [GitHub Issue](https://github.com/numpy/numpy/issues/12759)\n- [GitHub PR](https://github.com/numpy/numpy/pull/13359)\n- [PoC](https://github.com/RayScri/CVE-2019-6446)\n",
"problems": [
{
"id": "CVE-2019-6446",
"source": "CVE"
},
{
"id": "CWE-94",
"source": "CWE"
}
],
"coordinates": [
{
"remedies": [
{
"type": "indeterminate",
"description": "Upgrade the package version to 1.16.3 to fix this vulnerability",
"details": {
"upgrade_package": "1.16.3"
}
}
],
"representation": [
"[0,1.16.3)"
]
}
],
"severities": [
{
"source": "Snyk",
"level": "critical",
"score": 9.8,
"vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H/E:P"
},
{
"source": "NVD",
"level": "critical",
"score": 9.8,
"vector": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
},
{
"source": "Red Hat",
"level": "high",
"score": 8.8,
"vector": "CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H"
},
{
"source": "SUSE",
"level": "high",
"score": 7.8,
"vector": "CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H"
}
],
"effective_severity_level": "critical",
"slots": {
"disclosure_time": "2019-01-16T12:26:38Z",
"exploit": "Proof of Concept",
"publication_time": "2019-01-16T13:50:50Z",
"references": [
{
"url": "https://github.com/numpy/numpy/commit/89b688732b37616c9d26623f81aaee1703c30ffb",
"title": "GitHub Commit"
},
{
"url": "https://github.com/numpy/numpy/issues/12759",
"title": "GitHub Issue"
},
{
"url": "https://github.com/numpy/numpy/pull/13359",
"title": "GitHub PR"
},
{
"url": "https://github.com/RayScri/CVE-2019-6446",
"title": "PoC"
}
]
}
}
}
],
"links": {
"self": "/orgs/00000000-0000-0000-0000-000000000000/packages/pkg%3Apypi%2Fnumpy%401.16.0/issues?version=2023-06-01&limit=1000&offset=0"
},
"meta": {
"package": {
"name": "numpy",
"type": "pypi",
"url": "pkg:pypi/[email protected]",
"version": "1.16.0"
}
}
}
18 changes: 18 additions & 0 deletions lib/snyk/testdata/self.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"jsonapi": {
"version": "1.0"
},
"data": {
"type": "user",
"id": "00000000-0000-0000-0000-000000000000",
"attributes": {
"name": "[email protected]",
"default_org_context": "00000000-0000-0000-0000-000000000000",
"username": "[email protected]",
"email": "[email protected]"
}
},
"links": {
"self": "/self?version=2023-04-28~experimental"
}
}

0 comments on commit f74b3a6

Please sign in to comment.