@eurekadevsecops/radar 1.10.0 → 2.0.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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.0.0](https://github.com/EurekaDevSecOps/radarctl/compare/v1.11.0...v2.0.0) (2026-03-04)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### ⚠ BREAKING CHANGES
|
|
7
|
+
|
|
8
|
+
* **scan:** Exit codes have changed. When vulnerabilities are found, instead of returning exit codes in the range 8-15, Radar CLI now only returns 8.
|
|
9
|
+
|
|
10
|
+
### Improvements
|
|
11
|
+
|
|
12
|
+
* **scan:** Add THRESHOLD option ([#67](https://github.com/EurekaDevSecOps/radarctl/issues/67)) ([47a0b7b](https://github.com/EurekaDevSecOps/radarctl/commit/47a0b7bdc2b9f59d13cc6d35d6b1367b00b4ebc3))
|
|
13
|
+
* **scans:** Display link to scan in Eureka dashboard ([#68](https://github.com/EurekaDevSecOps/radarctl/issues/68)) ([0b33b79](https://github.com/EurekaDevSecOps/radarctl/commit/0b33b79420a6589b33b1dc4370e4733bf872eaae))
|
|
14
|
+
|
|
15
|
+
## [1.11.0](https://github.com/EurekaDevSecOps/radarctl/compare/v1.10.0...v1.11.0) (2026-02-27)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Improvements
|
|
19
|
+
|
|
20
|
+
* Add support for Veracode Pipeline (SAST) scanner ([#2](https://github.com/EurekaDevSecOps/radarctl/issues/2)) ([bf7f04b](https://github.com/EurekaDevSecOps/radarctl/commit/bf7f04b4fd8bfc5fd3e13b25365809209db80cec))
|
|
21
|
+
|
|
3
22
|
## [1.10.0](https://github.com/EurekaDevSecOps/radarctl/compare/v1.9.8...v1.10.0) (2026-02-25)
|
|
4
23
|
|
|
5
24
|
|
package/package.json
CHANGED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Parameters:
|
|
4
|
+
# $1 - Path to the source code folder that should be scanned
|
|
5
|
+
# $2 - Path to the assets folder
|
|
6
|
+
# $3 - Path to the output folder where scan results should be stored
|
|
7
|
+
|
|
8
|
+
# Requirements:
|
|
9
|
+
#
|
|
10
|
+
# Environment variables VERACODE_API_KEY_ID and VERACODE_API_KEY_SECRET must be set:
|
|
11
|
+
# [Veracode Platform](https://docs.veracode.com/r/c_api_credentials3#generate-api-credentials).
|
|
12
|
+
#
|
|
13
|
+
# EXAMPLE:
|
|
14
|
+
# export VERACODE_API_KEY_ID=123456789
|
|
15
|
+
# export VERACODE_API_KEY_SECRET=REDACTED
|
|
16
|
+
# radar scan /path/to/repo
|
|
17
|
+
# (Prefer setting these via your CI/secret manager; avoid typing real secrets into shell history.)
|
|
18
|
+
#
|
|
19
|
+
# Optional:
|
|
20
|
+
#
|
|
21
|
+
# (A) The repo has already been packaged for Veracode as per https://docs.veracode.com/r/compilation_packaging
|
|
22
|
+
# and stored into a ZIP file somewhere within the repo. Set the environment variable VERACODE_ZIPFILE to the
|
|
23
|
+
# path/to/repo/veracode-package.zip file, relative to the root folder of the repo.
|
|
24
|
+
#
|
|
25
|
+
# -or-
|
|
26
|
+
#
|
|
27
|
+
# (B) Set the environment variable VERACODE_PACKAGE_CMD to the command that can create the Veracode package ZIP.
|
|
28
|
+
# We will run the command from the root of the repo. It should create veracode-package.zip and save it into
|
|
29
|
+
# the root folder of the repo. We will submit this ZIP to Veracode Pipeline SAST scanner for a scan.
|
|
30
|
+
#
|
|
31
|
+
# Examples:
|
|
32
|
+
# export VERACODE_PACKAGE_CMD="zip -qr veracode-package.zip lib"
|
|
33
|
+
# export VERACODE_PACKAGE_CMD="npm run build && zip -qr veracode-package.zip dist"
|
|
34
|
+
# export VERACODE_PACKAGE_CMD="make && zip -qr veracode-package.zip out"
|
|
35
|
+
#
|
|
36
|
+
# -or-
|
|
37
|
+
#
|
|
38
|
+
# (C) Your project does not need a build step. Omit both VERACODE_ZIPFILE and VERACODE_PACKAGE_CMD. We will
|
|
39
|
+
# automatically ZIP up the repo, excluding any files referenced in .gitignore, and submit to Veracode Pipeline
|
|
40
|
+
# SAST scanner for a scan. This is the default action if you don't set VERACODE_ZIPFILE and VERACODE_PACKAGE_CMD.
|
|
41
|
+
# This is appropriate for interpreted languages (Javascript, Python, etc) that don't need to be compiled.
|
|
42
|
+
|
|
43
|
+
set -e
|
|
44
|
+
|
|
45
|
+
if [ "$#" -ne 3 ]; then
|
|
46
|
+
echo "Usage: $0 <source_dir> <assets_dir> <output_dir>" >&2
|
|
47
|
+
exit 1
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# Expand relative paths
|
|
51
|
+
if ! APP_DIR="$(cd -- "$1" && pwd)"; then
|
|
52
|
+
echo "Error: source directory not found: $1" >&2
|
|
53
|
+
exit 1
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
if ! CFG_DIR="$(cd -- "$2" && pwd)"; then
|
|
57
|
+
echo "Error: assets directory not found: $2" >&2
|
|
58
|
+
exit 1
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
if ! OUT_DIR="$(cd -- "$3" && pwd)"; then
|
|
62
|
+
echo "Error: output directory not found: $3" >&2
|
|
63
|
+
exit 1
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
# The ghcr.io/eurekadevsecops/radar-veracode-sast image is currently published for linux/amd64 only.
|
|
67
|
+
# On non-amd64 hosts (e.g., Apple Silicon), Docker will use emulation which may be slower.
|
|
68
|
+
docker run --platform linux/amd64 --rm \
|
|
69
|
+
-v "${APP_DIR}":/opt/eureka/radar/temp/repo \
|
|
70
|
+
-v "${CFG_DIR}":/opt/eureka/radar/temp/input \
|
|
71
|
+
-v "${OUT_DIR}":/opt/eureka/radar/temp/output \
|
|
72
|
+
-e VERACODE_API_KEY_ID="${VERACODE_API_KEY_ID}" \
|
|
73
|
+
-e VERACODE_API_KEY_SECRET="${VERACODE_API_KEY_SECRET}" \
|
|
74
|
+
-e VERACODE_ZIPFILE="${VERACODE_ZIPFILE}" \
|
|
75
|
+
-e VERACODE_PACKAGE_CMD="${VERACODE_PACKAGE_CMD}" \
|
|
76
|
+
ghcr.io/eurekadevsecops/radar-veracode-sast 2>&1
|
package/src/commands/scan.js
CHANGED
|
@@ -6,6 +6,18 @@ const SARIF = require('../util/sarif')
|
|
|
6
6
|
const runner = require('../util/runner')
|
|
7
7
|
const { DateTime } = require('luxon')
|
|
8
8
|
|
|
9
|
+
function is_error(threshold) {
|
|
10
|
+
return is_warning(threshold) || threshold === 'high' || threshold === 'error'
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function is_warning(threshold) {
|
|
14
|
+
return is_note(threshold) || threshold === 'moderate' || threshold === 'warning'
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function is_note(threshold) {
|
|
18
|
+
return threshold === 'low' || threshold === 'note'
|
|
19
|
+
}
|
|
20
|
+
|
|
9
21
|
module.exports = {
|
|
10
22
|
summary: 'scan for vulnerabilities',
|
|
11
23
|
args: {
|
|
@@ -22,11 +34,12 @@ module.exports = {
|
|
|
22
34
|
{ name: 'DEBUG', short: 'd', long: 'debug', type: 'boolean', description: 'log detailed debug info to stdout' },
|
|
23
35
|
{ name: 'ESCALATE', short: 'e', long: 'escalate', type: 'string', description: 'severities to treat as high/error' },
|
|
24
36
|
{ name: 'FORMAT', short: 'f', long: 'format', type: 'string', description: 'severity format' },
|
|
37
|
+
{ name: 'ID', short: 'i', long: 'id', type: 'string', description: 'scan ID to associate results with' },
|
|
25
38
|
{ name: 'LOCAL', short: 'l', long: 'local', type: 'boolean', description: 'local scan (no upload of findings to Eureka)' },
|
|
26
39
|
{ name: 'OUTPUT', short: 'o', long: 'output', type: 'string', description: 'output SARIF file' },
|
|
27
40
|
{ name: 'QUIET', short: 'q', long: 'quiet', type: 'boolean', description: 'suppress stdout logging' },
|
|
28
41
|
{ name: 'SCANNERS', short: 's', long: 'scanners', type: 'string', description: 'list of scanners to use' },
|
|
29
|
-
{ name: '
|
|
42
|
+
{ name: 'THRESHOLD', short: 't', long: 'threshold', type: 'string', description: 'severity threshold for non-zero exit code' }
|
|
30
43
|
],
|
|
31
44
|
description: `
|
|
32
45
|
Scans a target for vulnerabilities. Defaults to displaying findings on stdout.
|
|
@@ -72,36 +85,33 @@ module.exports = {
|
|
|
72
85
|
Radar CLI from uploading scan findings even when you have 'EUREKA_AGENT_TOKEN' set,
|
|
73
86
|
you can pass the LOCAL option on the command line.
|
|
74
87
|
|
|
88
|
+
Use the THRESHOLD option to return a non-zero exit code for severities at or
|
|
89
|
+
above the threshold. For example, setting THRESHOLD to "high" would result in
|
|
90
|
+
a non-zero exit code only if high or critical vulnerabilities were found by the
|
|
91
|
+
scan. Available values are low, moderate, high, and critical - or note, warning,
|
|
92
|
+
and error if using the SARIF native severity levels.
|
|
93
|
+
|
|
75
94
|
Exit codes:
|
|
76
|
-
0 - Clean and successful scan. No
|
|
95
|
+
0 - Clean and successful scan. No vulnerabilities.
|
|
77
96
|
1 - Bad command, arguments, or options. Scan not completed.
|
|
78
|
-
|
|
79
|
-
9 - Scan completed with errors (no warnings or notes).
|
|
80
|
-
10 - Scan completed with warnings (no errors or notes).
|
|
81
|
-
11 - Scan completed with errors and warnings (no notes).
|
|
82
|
-
12 - Scan completed with notes (no errors or warnings).
|
|
83
|
-
13 - Scan completed with errors and notes (no warnings).
|
|
84
|
-
14 - Scan completed with warnings and notes (no errors).
|
|
85
|
-
15 - Scan completed with errors, warnings, and notes.
|
|
97
|
+
8 - Scan completed with vulnerabilities (>= THRESHOLD severity, if set).
|
|
86
98
|
>= 16 - Scan aborted due to unexpected error.
|
|
87
99
|
`,
|
|
88
100
|
examples: [
|
|
89
101
|
'$ radar scan ' + '(scan current working directory)'.grey,
|
|
90
102
|
'$ radar scan . ' + '(scan current working directory)'.grey,
|
|
103
|
+
'$ radar scan /my/repo/dir ' + '(scan target directory)'.grey,
|
|
91
104
|
'$ radar scan --local ' + '(run a local scan / no uploads to Eureka)'.grey,
|
|
92
105
|
'$ radar scan -d' + '(turn debug mode on)'.grey,
|
|
93
106
|
'$ radar scan --debug' + '(turn debug mode on)'.grey,
|
|
94
|
-
'$ radar scan /my/repo/dir ' + '(scan target directory)'.grey,
|
|
95
107
|
'$ radar scan --output=scan.sarif ' + '(save findings in a file)'.grey,
|
|
96
108
|
'$ radar scan -o scan.sarif /my/repo/dir ' + '(short versions of options)'.grey,
|
|
97
109
|
'$ radar scan -s depscan,opengrep ' + '(use only given scanners)'.grey,
|
|
98
110
|
'$ radar scan -c sca,sast ' + '(use all scanners from given categories)'.grey,
|
|
99
111
|
'$ radar scan -c sca,sast -s all ' + '(use all scanners from given categories)'.grey,
|
|
100
112
|
'$ radar scan -c sast -s opengrep ' + '(use only the opengrep scanner)'.grey,
|
|
101
|
-
'$ radar scan -
|
|
102
|
-
'$ radar scan -
|
|
103
|
-
'$ radar scan -e moderate,low ' + '(treat lower severities as high)'.grey,
|
|
104
|
-
'$ radar scan -f sarif -e warning,note ' + '(treat lower severities as errors)'.grey
|
|
113
|
+
'$ radar scan -e moderate,low ' + '(treat moderate and low severities as high)'.grey,
|
|
114
|
+
'$ radar scan -t moderate ' + '(non-zero exit code for severities moderate and higher)'.grey,
|
|
105
115
|
],
|
|
106
116
|
run: async (toolbox, args, globals) => {
|
|
107
117
|
const { log, scanners: availableScanners, categories: availableCategories, telemetry, git } = toolbox
|
|
@@ -135,6 +145,10 @@ module.exports = {
|
|
|
135
145
|
if (args.FORMAT === 'security' && severity !== 'moderate' && severity !== 'low') throw new Error(`Severity to escalate must be 'moderate' or 'low'`)
|
|
136
146
|
if (args.FORMAT === 'sarif' && severity !== 'warning' && severity !== 'note') throw new Error(`Severity to escalate must be 'warning' or 'note'`)
|
|
137
147
|
})
|
|
148
|
+
if (args.THRESHOLD) {
|
|
149
|
+
if (args.FORMAT === 'security' && !['critical', 'high', 'moderate', 'low'].includes(args.THRESHOLD)) throw new Error(`THRESHOLD must be one of 'critical', 'high', 'moderate' or 'low'`)
|
|
150
|
+
if (args.FORMAT === 'sarif' && !['error', 'warning', 'note'].includes(args.THRESHOLD)) throw new Error(`THRESHOLD must be one of 'error', 'warning' or 'note'`)
|
|
151
|
+
}
|
|
138
152
|
|
|
139
153
|
// Derive scan parameters.
|
|
140
154
|
const target = args.TARGET // target to scan
|
|
@@ -166,16 +180,17 @@ module.exports = {
|
|
|
166
180
|
if (metadata.type === 'error') throw new Error(`${metadata.error.code}: ${metadata.error.details}`)
|
|
167
181
|
|
|
168
182
|
// Send telemetry: scan started.
|
|
169
|
-
let scanID = args.
|
|
183
|
+
let scanID = args.ID ?? undefined
|
|
184
|
+
let scanURL = undefined
|
|
170
185
|
const timestamp = DateTime.now().toISO()
|
|
171
186
|
|
|
172
187
|
if (telemetry.enabled && !args.LOCAL) {
|
|
173
|
-
// TODO: Should pass scanID to the server; not read it from the server.
|
|
174
188
|
try {
|
|
175
189
|
const res = await telemetry.send(`scans/started`, {}, { scanners: scanners.map((s) => s.name), scanID, metadata, timestamp })
|
|
176
190
|
if (!res.ok) throw new Error(`[${res.status}] ${res.statusText}: ${await res.text()}`)
|
|
177
191
|
const data = await res.json()
|
|
178
192
|
scanID = data.scan_id
|
|
193
|
+
scanURL = data.scan_url
|
|
179
194
|
}
|
|
180
195
|
catch (error) {
|
|
181
196
|
log(`WARNING: Telemetry will be skipped for this scan run: ${error.message}\n`)
|
|
@@ -250,15 +265,24 @@ module.exports = {
|
|
|
250
265
|
SARIF.visualizations.display_totals(summary, args.FORMAT, log, telemetry.enabled && scanID && !args.LOCAL)
|
|
251
266
|
}
|
|
252
267
|
|
|
268
|
+
// Display link to scan results in the dashboard.
|
|
269
|
+
if (telemetry.enabled && scanURL && !args.QUIET) {
|
|
270
|
+
log(`View scan findings in the Eureka dashboard: ${scanURL}`)
|
|
271
|
+
}
|
|
272
|
+
|
|
253
273
|
// Determine the correct exit code.
|
|
254
274
|
let exitCode = 0
|
|
255
275
|
if (!summary.errors.length && !summary.warnings.length && !summary.notes.length) {
|
|
276
|
+
// No vulnerabilities.
|
|
256
277
|
exitCode = 0
|
|
278
|
+
} else if (args.THRESHOLD) {
|
|
279
|
+
// Set the exit code to 8 if there are any vulnerabilities with severities at or above the given threshold.
|
|
280
|
+
if (is_error(args.THRESHOLD) && summary.errors.length > 0) exitCode = 0x8
|
|
281
|
+
if (is_warning(args.THRESHOLD) && summary.warnings.length > 0) exitCode = 0x8
|
|
282
|
+
if (is_note(args.THRESHOLD) && summary.notes.length > 0) exitCode = 0x8
|
|
257
283
|
} else {
|
|
284
|
+
// Set the exit code to 8 if there are any vulnerabilities.
|
|
258
285
|
exitCode = 0x8
|
|
259
|
-
if (summary.errors.length > 0) exitCode |= 0x1
|
|
260
|
-
if (summary.warnings.length > 0) exitCode |= 0x2
|
|
261
|
-
if (summary.notes.length > 0) exitCode |= 0x4
|
|
262
286
|
}
|
|
263
287
|
|
|
264
288
|
// Display the exit code.
|
|
Binary file
|