@eurekadevsecops/radar 1.6.2 → 1.7.1

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.6.2",
3
+ "version": "1.7.1",
4
4
  "description": "Radar is an open-source orchestrator of security scanners.",
5
5
  "homepage": "https://www.eurekadevsecops.com/radar",
6
6
  "keywords": [
@@ -4,4 +4,15 @@
4
4
  # $3 - Path to the output folder where scan results should be stored
5
5
 
6
6
  set -e
7
- docker run --rm -v $1:/app -v $2:/input -v $3:/output ghcr.io/eurekadevsecops/radar-depscan 2>&1
7
+
8
+ trap cleanup TERM INT
9
+
10
+ cleanup()
11
+ {
12
+ PID=$(cat $3/depscan.cid)
13
+ docker stop $PID
14
+ rm $3/depscan.cid
15
+ exit 1
16
+ }
17
+
18
+ docker run --cidfile $3/depscan.cid --rm -v $1:/app -v $2:/input -v $3:/output ghcr.io/eurekadevsecops/radar-depscan 2>&1
@@ -4,4 +4,15 @@
4
4
  # $3 - Path to the output folder where scan results should be stored
5
5
 
6
6
  set -e
7
- docker run --rm -v $1:/app -v $2:/input -v $3:/output zricethezav/gitleaks dir --exit-code 0 -f sarif -r /output/gitleaks.sarif /app 2>&1
7
+
8
+ trap cleanup TERM INT
9
+
10
+ cleanup()
11
+ {
12
+ PID=$(cat $3/gitleaks.cid)
13
+ docker stop $PID
14
+ rm $3/gitleaks.cid
15
+ exit 1
16
+ }
17
+
18
+ docker run --cidfile $3/gitleaks.cid --rm -v $1:/app -v $2:/input -v $3:/output zricethezav/gitleaks dir --exit-code 0 -f sarif -r /output/gitleaks.sarif /app 2>&1
@@ -4,4 +4,15 @@
4
4
  # $3 - Path to the output folder where scan results should be stored
5
5
 
6
6
  set -e
7
- docker run --rm -v $1:/app -v $2:/input -v $3:/output ghcr.io/eurekadevsecops/radar-grype 2>&1
7
+
8
+ trap cleanup TERM INT
9
+
10
+ cleanup()
11
+ {
12
+ PID=$(cat $3/grype.cid)
13
+ docker stop $PID
14
+ rm $3/grype.cid
15
+ exit 1
16
+ }
17
+
18
+ docker run --cidfile $3/grype.cid --rm -v $1:/app -v $2:/input -v $3:/output ghcr.io/eurekadevsecops/radar-grype 2>&1
@@ -4,4 +4,15 @@
4
4
  # $3 - Path to the output folder where scan results should be stored
5
5
 
6
6
  set -e
7
- docker run --rm -v $1:/app -v $2:/input -v $3:/output ghcr.io/eurekadevsecops/radar-opengrep 2>&1
7
+
8
+ trap cleanup TERM INT
9
+
10
+ cleanup()
11
+ {
12
+ PID=$(cat $3/opengrep.cid)
13
+ docker stop $PID
14
+ rm $3/opengrep.cid
15
+ exit 1
16
+ }
17
+
18
+ docker run --cidfile $3/opengrep.cid --rm -v $1:/app -v $2:/input -v $3:/output ghcr.io/eurekadevsecops/radar-opengrep 2>&1
@@ -11,16 +11,40 @@ const runAll = async ({ scanners, target, assets, outdir, quiet, log }) => {
11
11
  // Results will include the stdout log and the final combined SARIF object.
12
12
  const results = { log: '' }
13
13
 
14
- // Run all scanners. This will produce one output SARIF file per scanner.
14
+ // Run all scanners (concurrently). This will produce one output SARIF file per scanner.
15
+ const jobs = []
16
+ const processes = []
15
17
  for (const scanner of scanners) {
16
- results.log += await runScanner({ scanner, target, assets, outdir, quiet, log, display: {
18
+ jobs.push(runScanner(processes, { scanner, target, assets, outdir, quiet, log, display: {
17
19
  begin: () => scanner.name,
18
20
  progress: (label, duration) => `${scanner.name} [${humanize.duration(duration)}]`,
19
21
  success: (label) => label,
20
22
  error: (label) => label
21
- }})
23
+ }}))
22
24
  }
23
25
 
26
+ // Wait for scanner runs to complete.
27
+ await Promise.all(jobs)
28
+ .then(async (result) => {
29
+ for (const job of jobs) {
30
+ results.log += await job
31
+ }
32
+ })
33
+ .catch((error) => {
34
+ // Early exit: If a job fails, kill all the other jobs. This ensures
35
+ // that the CLI doesn't hang waiting for all jobs to complete when
36
+ // we know already that the scan failed.
37
+ let exitCode = null
38
+ for (const p of processes) {
39
+ if (p.killed || p.exitCode !== null) {
40
+ exitCode = p.exitCode
41
+ continue
42
+ }
43
+ p.kill('SIGKILL')
44
+ }
45
+ if (exitCode) throw `Command exited with exit code ${exitCode}: ${error}`
46
+ })
47
+
24
48
  // Merge all output SARIF files into one and load it into a JS object.
25
49
  const consolidated = path.join(outdir, 'scan.sarif')
26
50
  await SARIF.transforms.merge(consolidated, scanners.map(s => path.join(outdir, `${s.name}.sarif`)))
@@ -29,7 +53,7 @@ const runAll = async ({ scanners, target, assets, outdir, quiet, log }) => {
29
53
  return results
30
54
  }
31
55
 
32
- const runScanner = async ({ scanner, target, assets, outdir, quiet, log, display }) => {
56
+ const runScanner = async (processes, { scanner, target, assets, outdir, quiet, log, display }) => {
33
57
  let label = display.begin()
34
58
  const spinner = new Spinner()
35
59
  if (!quiet) spinner.start(label)
@@ -51,12 +75,19 @@ const runScanner = async ({ scanner, target, assets, outdir, quiet, log, display
51
75
  cmd = cmd.replaceAll('${output}', outdir)
52
76
  /* eslint-enable no-template-curly-in-string */
53
77
 
54
- const { stdout } = await exec(cmd)
78
+ // Run the child process. Store the process information (like pid)
79
+ // in case we need to kill the process. Capture stdout log.
80
+ const promise = exec(cmd)
81
+ processes.push(promise.child)
82
+ const { stdout } = await promise
55
83
  runLog = stdout
56
84
 
57
85
  if (!quiet) spinner.success(display.success(label))
58
86
  } catch (error) {
59
- if (!quiet) spinner.error(display.error(label))
87
+ // Display an error spinner, but if the child process
88
+ // was killed then don't display anything.
89
+ if (!quiet && !error.killed) spinner.error(display.error(label))
90
+ if (error.killed) spinner.stop()
60
91
 
61
92
  let message = `${error}`
62
93
  if (error.stdout) message += error.stdout
@@ -5,14 +5,18 @@ module.exports = (sarif, dir, git, root) => {
5
5
 
6
6
  // Record the source repo location and the relative target subfolder within the repo.
7
7
  run.originalUriBaseIds = {
8
- "SOURCE": {
9
- "uri": git.repo.url.https,
10
- "description": "Source origin for the target being scanned (ie. git repo URL)."
8
+ SOURCE: {
9
+ uri: git.repo.url.https,
10
+ description: {
11
+ text: "Source origin for the target being scanned (ie. git repo URL)."
12
+ }
11
13
  },
12
- "TARGET": {
13
- "uri": `${path.relative(root, dir)}`,
14
- "uriBaseId": "SOURCE",
15
- "description": "Scan target (subfolder) within the source repo or folder."
14
+ TARGET: {
15
+ uri: `${path.relative(root, dir)}`,
16
+ uriBaseId: "SOURCE",
17
+ description: {
18
+ text: "Scan target (subfolder) within the source repo or folder."
19
+ }
16
20
  }
17
21
  }
18
22