@eurekadevsecops/radar 1.4.6 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/depscan/scan.sarif +70 -0
- package/package.json +2 -1
- package/src/commands/scan.js +10 -3
- package/src/index.js +1 -0
- package/src/plugins/git.js +6 -0
- package/src/telemetry/index.js +2 -0
- package/src/util/git/index.js +89 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "2.1.0",
|
|
3
|
+
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
|
|
4
|
+
"runs": [
|
|
5
|
+
{
|
|
6
|
+
"tool": {
|
|
7
|
+
"driver": {
|
|
8
|
+
"name": "depscan",
|
|
9
|
+
"semanticVersion": "5.5.0",
|
|
10
|
+
"informationUri": "https://github.com/owasp-dep-scan/dep-scan",
|
|
11
|
+
"properties": {
|
|
12
|
+
"protocol_version": "v1.0.0",
|
|
13
|
+
"scanner_name": "depscan",
|
|
14
|
+
"scanner_version": "5.5.0",
|
|
15
|
+
"db": "https://github.com/AppThreat/vulnerability-db",
|
|
16
|
+
"scan_mode": "source"
|
|
17
|
+
},
|
|
18
|
+
"rules": [
|
|
19
|
+
{
|
|
20
|
+
"id": "CVE-2022-33987Y/pkg:npm/got@9.6.0",
|
|
21
|
+
"shortDescription": {
|
|
22
|
+
"text": "Vulnerable pkg: npm/got@9.6.0\nCVE: CVE-2022-33987\nFix: Update to 11.8.5 or later\n\ndepscan:insights: Indirect dependency\ndepscan:prioritized: false\naffectedVersionRange: got@<11.8.5\n"
|
|
23
|
+
},
|
|
24
|
+
"fullDescription": {
|
|
25
|
+
"text": "# Got allows a redirect to a UNIX socket\nThe got package before 11.8.5 and 12.1.0 for Node.js allows a redirect to a UNIX socket.\nUpgrade to version 11.8.5 or later"
|
|
26
|
+
},
|
|
27
|
+
"help": {
|
|
28
|
+
"text": "Update to 11.8.5 or later"
|
|
29
|
+
},
|
|
30
|
+
"helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2022-33987",
|
|
31
|
+
"properties": {
|
|
32
|
+
"tags": [
|
|
33
|
+
"CVE-2022-33987"
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"results": [
|
|
42
|
+
{
|
|
43
|
+
"ruleId": "CVE-2022-33987Y/pkg:npm/got@9.6.0",
|
|
44
|
+
"level": "warning",
|
|
45
|
+
"message": {
|
|
46
|
+
"text": "Vulnerability CVE-2022-33987 in pkg npm/got@9.6.0. Update to 11.8.5 or later"
|
|
47
|
+
},
|
|
48
|
+
"locations": [
|
|
49
|
+
{
|
|
50
|
+
"physicalLocation": {
|
|
51
|
+
"artifactLocation": {
|
|
52
|
+
"uri": "package-lock.json",
|
|
53
|
+
"uriBaseId": "%SRCROOT%"
|
|
54
|
+
},
|
|
55
|
+
"region": {
|
|
56
|
+
"startLine": 1
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"message": {
|
|
60
|
+
"text": "Vulnerability CVE-2022-33987 in pkg npm/got@9.6.0. Update to 11.8.5 or later"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eurekadevsecops/radar",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Radar is an open-source orchestrator of security scanners.",
|
|
5
5
|
"homepage": "https://www.eurekadevsecops.com/radar",
|
|
6
6
|
"keywords": [
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@persistr/clif": "^1.11.0",
|
|
31
31
|
"@persistr/clif-plugin-settings": "^2.3.1",
|
|
32
|
+
"hosted-git-info": "^9.0.0",
|
|
32
33
|
"humanize-duration": "^3.33.0",
|
|
33
34
|
"jwt-decode": "^4.0.0",
|
|
34
35
|
"luxon": "^3.7.1",
|
package/src/commands/scan.js
CHANGED
|
@@ -87,7 +87,7 @@ module.exports = {
|
|
|
87
87
|
'$ radar scan -f sarif -e warning,note ' + '(treat lower severities as errors)'.grey
|
|
88
88
|
],
|
|
89
89
|
run: async (toolbox, args) => {
|
|
90
|
-
const { log, scanners: availableScanners, categories: availableCategories, telemetry } = toolbox
|
|
90
|
+
const { log, scanners: availableScanners, categories: availableCategories, telemetry, git } = toolbox
|
|
91
91
|
|
|
92
92
|
// Set defaults for args and options.
|
|
93
93
|
args.TARGET ??= process.cwd()
|
|
@@ -149,6 +149,13 @@ module.exports = {
|
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
+
// Send telemetry: git metadata.
|
|
153
|
+
if (telemetry.enabled && scanID) {
|
|
154
|
+
const metadata = git.metadata()
|
|
155
|
+
await telemetry.send(`scans/:scanID/metadata`, { scanID }, { metadata })
|
|
156
|
+
await telemetry.sendSensitive(`scans/:scanID/metadata`, { scanID }, { metadata })
|
|
157
|
+
}
|
|
158
|
+
|
|
152
159
|
// Run scanners.
|
|
153
160
|
log(`Running ${scanners.length} of ${availableScanners.length} scanners:`)
|
|
154
161
|
let results = { /* log, sarif */ }
|
|
@@ -180,8 +187,8 @@ module.exports = {
|
|
|
180
187
|
let summary
|
|
181
188
|
if (telemetry.enabled && scanID) {
|
|
182
189
|
const analysis = await telemetry.receiveSensitive(`scans/:scanID/summary`, { scanID })
|
|
183
|
-
if (!analysis?.
|
|
184
|
-
summary = analysis.
|
|
190
|
+
if (!analysis?.findingsBySeverity) throw new Error(`Failed to retrieve analysis summary for scan '${scanID}'`)
|
|
191
|
+
summary = analysis.findingsBySeverity
|
|
185
192
|
} else {
|
|
186
193
|
summary = await SARIF.analysis.summarize(results.sarif, target)
|
|
187
194
|
}
|
package/src/index.js
CHANGED
|
@@ -6,6 +6,7 @@ const path = require('node:path')
|
|
|
6
6
|
// Plugins.
|
|
7
7
|
const plugins = {
|
|
8
8
|
settings: require('@persistr/clif-plugin-settings'),
|
|
9
|
+
git: require(path.join(__dirname, 'plugins', 'git')),
|
|
9
10
|
scanners: require(path.join(__dirname, 'plugins', 'scanners')),
|
|
10
11
|
telemetry: require(path.join(__dirname, 'plugins', 'telemetry'))
|
|
11
12
|
}
|
package/src/telemetry/index.js
CHANGED
|
@@ -83,6 +83,7 @@ class Telemetry {
|
|
|
83
83
|
if (path === `scans/started`) return `${claims.aud}/scans/started`
|
|
84
84
|
if (path === `scans/:scanID/completed`) return `${claims.aud}/scans/${params.scanID}/completed`
|
|
85
85
|
if (path === `scans/:scanID/failed`) return `${claims.aud}/scans/${params.scanID}/completed`
|
|
86
|
+
if (path === `scans/:scanID/metadata`) return `${claims.aud}/scans/${params.scanID}/metadata`
|
|
86
87
|
if (path === `scans/:scanID/results`) return `${claims.aud}/scans/${params.scanID}/results`
|
|
87
88
|
throw new Error(`Internal Error: Unknown telemetry event: POST ${path}`)
|
|
88
89
|
}
|
|
@@ -102,6 +103,7 @@ class Telemetry {
|
|
|
102
103
|
if (path === `scans/started`) body = { ...body, timestamp: DateTime.now().toISO(), profile_id: process.env.EUREKA_PROFILE }
|
|
103
104
|
if (path === `scans/:scanID/completed`) body = { ...this.#toFindings(body), timestamp: DateTime.now().toISO(), status: 'success', log: { sizeBytes: 0, warnings: 0, errors: 0, link: 'none' }, params: { id: '' }}
|
|
104
105
|
if (path === `scans/:scanID/failed`) body = { ...body, timestamp: DateTime.now().toISO(), status: 'failure', findings: { total: 0, critical: 0, high: 0, med: 0, low: 0 }, log: { sizeBytes: 0, warnings: 0, errors: 0, link: 'none' }, params: { id: '' }}
|
|
106
|
+
if (path === `scans/:scanID/metadata`) body = { metadata: body.metadata, profileId: process.env.EUREKA_PROFILE }
|
|
105
107
|
if (path === `scans/:scanID/results`) body = { findings: body.findings /* SARIF */, profileId: process.env.EUREKA_PROFILE, log: Buffer.from(body.log, 'utf8').toString('base64') }
|
|
106
108
|
return JSON.stringify(body)
|
|
107
109
|
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
const { execSync } = require('node:child_process')
|
|
2
|
+
const hostedGitInfo = require('hosted-git-info')
|
|
3
|
+
|
|
4
|
+
function metadata() {
|
|
5
|
+
try {
|
|
6
|
+
// Determine if we're scanning a valid git repo.
|
|
7
|
+
const isGitRepo = execSync('git rev-parse --is-inside-work-tree').toString().trim()
|
|
8
|
+
if (isGitRepo !== 'true') {
|
|
9
|
+
return { type: 'folder' }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Get the repo name and owner.
|
|
13
|
+
const originUrl = execSync('git config --get remote.origin.url').toString().trim()
|
|
14
|
+
const info = hostedGitInfo.fromUrl(originUrl, { noGitPlus: true })
|
|
15
|
+
const ownerPath = info.user.split('/')
|
|
16
|
+
|
|
17
|
+
// Get the branch name.
|
|
18
|
+
const branch = execSync('git rev-parse --abbrev-ref HEAD').toString().trim()
|
|
19
|
+
|
|
20
|
+
// Get the commit identifier and timestamp.
|
|
21
|
+
const shortCommitId = execSync('git rev-parse --short HEAD').toString().trim()
|
|
22
|
+
const fullCommitId = execSync('git rev-parse HEAD').toString().trim()
|
|
23
|
+
const commitTime = execSync('git show -s --format=%cI HEAD').toString().trim()
|
|
24
|
+
|
|
25
|
+
// Get the tags for the current commit.
|
|
26
|
+
let tags = execSync('git tag --points-at HEAD').toString().trim()
|
|
27
|
+
tags = '["' + tags.split('\n').join('","') + '"]'
|
|
28
|
+
tags = JSON.parse(tags).filter(tag => tag)
|
|
29
|
+
|
|
30
|
+
// Get the list of unique repo contributors (authors and committers).
|
|
31
|
+
const template = '"{\\\"name\\\":\\\"%cn\\\",\\\"email\\\":\\\"%ce\\\"}%n{\\\"name\\\":\\\"%an\\\",\\\"email\\\":\\\"%ae\\\"}"'
|
|
32
|
+
let contributors = execSync(`git log --pretty=${template} | sort -u`).toString().trim()
|
|
33
|
+
contributors = '[' + contributors.split('\n').join(',') + ']'
|
|
34
|
+
contributors = JSON.parse(contributors)
|
|
35
|
+
|
|
36
|
+
const script = `MAX_LENGTH=4;
|
|
37
|
+
git rev-list --abbrev=4 --abbrev-commit --all | \
|
|
38
|
+
( while read -r line; do
|
|
39
|
+
if [ \${#line} -gt $MAX_LENGTH ]; then
|
|
40
|
+
MAX_LENGTH=\${#line};
|
|
41
|
+
fi
|
|
42
|
+
done && printf %s\\\\n "$MAX_LENGTH"
|
|
43
|
+
)`
|
|
44
|
+
const abbrevs = Number(execSync(script).toString().trim())
|
|
45
|
+
|
|
46
|
+
/*
|
|
47
|
+
// Get the total lines of code in the repo.
|
|
48
|
+
const loc = execSync('git ls-files -z ${1} | xargs -0 cat | wc -l').toString().trim()
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
// Return the repo metadata.
|
|
52
|
+
return {
|
|
53
|
+
type: 'git',
|
|
54
|
+
repo: {
|
|
55
|
+
url: {
|
|
56
|
+
origin: originUrl,
|
|
57
|
+
https: info.https()
|
|
58
|
+
},
|
|
59
|
+
source: {
|
|
60
|
+
type: info.type,
|
|
61
|
+
domain: info.domain
|
|
62
|
+
},
|
|
63
|
+
owner: ownerPath[0],
|
|
64
|
+
path: ownerPath.slice(1).join('/'),
|
|
65
|
+
name: info.project,
|
|
66
|
+
abbrevs,
|
|
67
|
+
contributors
|
|
68
|
+
},
|
|
69
|
+
commit: {
|
|
70
|
+
id: fullCommitId,
|
|
71
|
+
time: commitTime,
|
|
72
|
+
branch,
|
|
73
|
+
tags
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
} catch (error) {
|
|
77
|
+
return {
|
|
78
|
+
type: 'error',
|
|
79
|
+
error: {
|
|
80
|
+
code: 'E_GIT_METADATA',
|
|
81
|
+
details: error
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
module.exports = {
|
|
88
|
+
metadata
|
|
89
|
+
}
|