@eurekadevsecops/radar 1.8.2 → 1.8.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eurekadevsecops/radar",
3
- "version": "1.8.2",
3
+ "version": "1.8.3",
4
4
  "description": "Radar is an open-source orchestrator of security scanners.",
5
5
  "homepage": "https://www.eurekadevsecops.com/radar",
6
6
  "keywords": [
@@ -27,7 +27,7 @@
27
27
  "url": "https://github.com/EurekaDevSecOps/radarctl.git"
28
28
  },
29
29
  "dependencies": {
30
- "@persistr/clif": "^1.11.1",
30
+ "@persistr/clif": "^1.11.2",
31
31
  "@persistr/clif-plugin-settings": "^2.3.1",
32
32
  "hosted-git-info": "^9.0.0",
33
33
  "humanize-duration": "^3.33.0",
@@ -17,6 +17,7 @@ module.exports = {
17
17
  },
18
18
  options: [
19
19
  { name: 'CATEGORIES', short: 'c', long: 'categories', type: 'string', description: 'list of scanner categories' },
20
+ { name: 'DEBUG', short: 'd', long: 'debug', type: 'boolean', description: 'log detailed debug info to stdout' },
20
21
  { name: 'ESCALATE', short: 'e', long: 'escalate', type: 'string', description: 'severities to treat as high/error' },
21
22
  { name: 'FORMAT', short: 'f', long: 'format', type: 'string', description: 'severity format' },
22
23
  { name: 'OUTPUT', short: 'o', long: 'output', type: 'string', description: 'output SARIF file' },
@@ -75,6 +76,8 @@ module.exports = {
75
76
  examples: [
76
77
  '$ radar scan ' + '(scan current working directory)'.grey,
77
78
  '$ radar scan . ' + '(scan current working directory)'.grey,
79
+ '$ radar scan -d' + '(turn debug mode on)'.grey,
80
+ '$ radar scan --debug' + '(turn debug mode on)'.grey,
78
81
  '$ radar scan /my/repo/dir ' + '(scan target directory)'.grey,
79
82
  '$ radar scan --output=scan.sarif ' + '(save findings in a file)'.grey,
80
83
  '$ radar scan -o scan.sarif /my/repo/dir ' + '(short versions of options)'.grey,
@@ -87,9 +90,12 @@ module.exports = {
87
90
  '$ radar scan -e moderate,low ' + '(treat lower severities as high)'.grey,
88
91
  '$ radar scan -f sarif -e warning,note ' + '(treat lower severities as errors)'.grey
89
92
  ],
90
- run: async (toolbox, args) => {
93
+ run: async (toolbox, args, globals) => {
91
94
  const { log, scanners: availableScanners, categories: availableCategories, telemetry, git } = toolbox
92
95
 
96
+ // Enable debug mode, if needed.
97
+ if (args.DEBUG) globals.debug = true
98
+
93
99
  // Set defaults for args and options.
94
100
  args.TARGET ??= process.cwd()
95
101
  args.FORMAT ??= 'security'
@@ -150,14 +156,24 @@ module.exports = {
150
156
  }
151
157
  catch (error) {
152
158
  log(`WARNING: Telemetry will be skipped for this scan run: ${error.message}\n`)
159
+ if (args.DEBUG) {
160
+ log(error)
161
+ if (error?.cause?.code === 'ECONNREFUSED') {
162
+ log(error.cause.errors)
163
+ log()
164
+ }
165
+ }
153
166
  }
154
167
  }
155
168
 
156
169
  // Send telemetry: git metadata.
157
170
  const metadata = git.metadata(target)
171
+ if (metadata.type === 'error') throw new Error(`${metadata.error.code}: ${metadata.error.details}`)
158
172
  if (telemetry.enabled && scanID) {
159
- await telemetry.send(`scans/:scanID/metadata`, { scanID }, { metadata })
160
- await telemetry.sendSensitive(`scans/:scanID/metadata`, { scanID }, { metadata })
173
+ let res = await telemetry.send(`scans/:scanID/metadata`, { scanID }, { metadata })
174
+ if (!res.ok) log(`WARNING: Scan metadata (stage 1) telemetry upload failed: [${res.status}] ${res.statusText}: ${await res.text()}`)
175
+ res = await telemetry.sendSensitive(`scans/:scanID/metadata`, { scanID }, { metadata })
176
+ if (!res.ok) log(`WARNING: Scan metadata (stage 2) telemetry upload failed: [${res.status}] ${res.statusText}: ${await res.text()}`)
161
177
  }
162
178
 
163
179
  // Run scanners.
@@ -170,7 +186,10 @@ module.exports = {
170
186
  catch (error) {
171
187
  log(`\n${error}`)
172
188
  if (!args.QUIET) log('Scan NOT completed!')
173
- if (telemetry.enabled) await telemetry.send(`scans/:scanID/failed`, { scanID })
189
+ if (telemetry.enabled) {
190
+ const res = await telemetry.send(`scans/:scanID/failed`, { scanID })
191
+ if (!res.ok) log(`WARNING: Scan status (not completed) telemetry upload failed: [${res.status}] ${res.statusText}: ${await res.text()}`)
192
+ }
174
193
  fs.rmSync(tmpdir, { recursive: true, force: true }) // Clean up.
175
194
  return 0x10 // exit code
176
195
  }
@@ -184,7 +203,8 @@ module.exports = {
184
203
 
185
204
  // Send telemetry: scan results.
186
205
  if (telemetry.enabled && scanID) {
187
- await telemetry.sendSensitive(`scans/:scanID/results`, { scanID }, { findings: results.sarif, log: results.log })
206
+ const res = await telemetry.sendSensitive(`scans/:scanID/results`, { scanID }, { findings: results.sarif, log: results.log })
207
+ if (!res.ok) log(`WARNING: Scan results telemetry upload failed: [${res.status}] ${res.statusText}: ${await res.text()}`)
188
208
  }
189
209
 
190
210
  // Analyze scan results: group findings by severity level.
@@ -199,7 +219,8 @@ module.exports = {
199
219
 
200
220
  // Send telemetry: scan summary.
201
221
  if (telemetry.enabled && scanID) {
202
- await telemetry.send(`scans/:scanID/completed`, { scanID }, summary)
222
+ const res = await telemetry.send(`scans/:scanID/completed`, { scanID }, summary)
223
+ if (!res.ok) log(`WARNING: Scan status (completed) telemetry upload failed: [${res.status}] ${res.statusText}: ${await res.text()}`)
203
224
  }
204
225
 
205
226
  // Display summarized findings.
@@ -49,7 +49,7 @@ git rev-list --abbrev=4 --abbrev-commit --all | \
49
49
  */
50
50
 
51
51
  // Return the repo metadata.
52
- return {
52
+ const metadata = {
53
53
  type: 'git',
54
54
  repo: {
55
55
  url: {
@@ -73,6 +73,21 @@ git rev-list --abbrev=4 --abbrev-commit --all | \
73
73
  tags
74
74
  }
75
75
  }
76
+
77
+ // Validate repo metadata.
78
+ if (!metadata.repo.url.origin) throw new Error('remote.origin.url not present')
79
+ if (!metadata.repo.url.https) throw new Error('remote.origin.url (https) not present')
80
+ if (!metadata.repo.source.type) throw new Error('unable to determine repository type')
81
+ if (!metadata.repo.source.domain) throw new Error('unable to determine repository domain')
82
+ if (!metadata.repo.owner) throw new Error('unknown repo owner')
83
+ if (!metadata.repo.name) throw new Error('unknown repo name')
84
+ if (!metadata.repo.abbrevs) throw new Error('unable to determine number of significant digits for commit IDs')
85
+ if (!metadata.repo.contributors) throw new Error('no repository contributors present')
86
+ if (!metadata.commit.id) throw new Error('commit ID not present')
87
+ if (!metadata.commit.time) throw new Error('commit time not present')
88
+ if (!metadata.commit.branch) throw new Error('branch not present')
89
+
90
+ return metadata
76
91
  } catch (error) {
77
92
  return {
78
93
  type: 'error',