@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.
@@ -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.4.6",
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",
@@ -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?.summary) throw new Error(`Failed to retrieve analysis summary for scan '${scanID}'`)
184
- summary = analysis.summary.findingsBySeverity
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
  }
@@ -0,0 +1,6 @@
1
+ const git = require('../util/git')
2
+ module.exports = {
3
+ toolbox: {
4
+ git
5
+ }
6
+ }
@@ -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
+ }