Safeguard
Developer Tools•

Scripting with Safeguard CLI output: JSON, stdout, stderr and jq

Practical rules for scripting the Safeguard CLI: send JSON to a file, keep stdout clean, read the scan folder with jq, and handle redaction and exit codes.

Safeguard Security Team
3 min read

To script the Safeguard CLI safely, write machine output to a file with the output option, keep stdout and stderr separate, and read results with jq. Notices and logs go to stderr, so redirecting stdout alone gives clean JSON. Check the exit code before trusting any file.

Choose the output format

The detect command supports table, JSON and SARIF. Table is for people. Use JSON for your own scripts and SARIF for code scanning views.

safeguard detect --format json --output detect.json

If you leave out the output option, results go to stdout. In that case redirect only stdout:

safeguard detect --format json > detect.json

The troubleshooting docs note that JSON mixed with messages happens when both streams end up in one place. Do not use the combined redirect for this.

Read the scan folder

The scan command writes a folder per scan under the output directory. The vulnerability file follows the grype layout, with matches under a data field, and other files cover licences and the collection.

List severity counts:

jq -r '.data.matches[].vulnerability.severity' out/*/vuln.json | sort | uniq -c

List package and fixed versions where a match has one, for a quick worklist:

jq -r '.data.matches[] | [.artifact.name, .artifact.version, .vulnerability.id] | @tsv' out/*/vuln.json

Field names can differ between versions, so inspect one file with jq 'keys' before you rely on a path.

Redaction is on by default

Detect redacts sensitive values in its output unless you turn that off. Leave it on in CI. A secret printed to a build log is a second leak. If you disable redaction for a local investigation, make sure the output goes to a private file, then delete it.

Always check the exit code

Capture the code before you parse anything:

safeguard scan --dir . --output out/
rc=$?
echo "scan exit code: $rc"

Zero means the scan ran. Two means results were written but vulnerability matching did not run. One means the command failed. Do not parse a half finished folder and report it as clean.

Make scripts repeatable

  • Pin the CLI version in CI.
  • Print the version at the start of each run.
  • Write results to a fresh folder per run, such as one named with the commit.
  • Keep the raw files as artifacts, and treat your summaries as derived.
  • Set the variable that disables update checks, so no network call surprises a locked down runner.

Local only results

There is also a findings command that runs one scanner on the machine and prints a single normalized list. In the build we checked, it can print JSON lines and keeps nothing on the platform. It is handy for quick local scripts, though its help text should be read for your version.

Quick check

Why is my JSON file not valid?

Most likely stderr messages were mixed in. Redirect stdout only, or use the output file option so the CLI writes the file itself.

Should I disable redaction in CI?

No. Redaction keeps secrets out of build logs. Only turn it off for private local investigations.

Safeguard also offers a free scan at gold.safeguard.sh/scan.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.