Scan your supply chain without shipping your code
Safeguard CLI builds the SBOM, finds the vulnerabilities and license risks in it, and patches them — all on your machine. Only the results ever leave.
curl -fsSL https://cli.safeguard.sh/install | bash- checksum-verified
- macOS · Linux · Windows
- npm — coming soon
Terminal session. ~/acme/api $ safeguard scan --dir .. building SBOM from source…. ✓ 214 components across 9 ecosystems. matching against the advisory database…. ✓ scan complete — 3 critical · 7 high · 12 medium. ◆ CRITICAL lodash@4.17.11 CVE-2021-23337 → 4.17.21. ▲ HIGH axios@0.21.1 CVE-2021-3749 → 0.21.4. → safeguard fix --severity critical --create-pr. ↳ nothing left this machine — results are in ./output
[safeguard]0:scan*1:assistant
runner online~/acme/api
Everything runs where your code already is
The scan, the graph walk, and the patch all happen locally. The platform only ever sees what you send it.
Scan where the code already is
Point it at a directory, a Git repository, a container image, or an existing SBOM. The dependency graph, the vulnerabilities, the secrets and the license risks are all computed on this machine.
safeguard scan --dir .
Only the results leave
Your source is never uploaded. The SBOM and the findings are the entire payload the platform receives — and only when you upload them or the runner returns a job.
payload: sbom.json · findings.json
Patch, don't just report
safeguard fix updates the vulnerable packages, writes a patched SBOM, and opens the pull request. --dry-run shows you the diff before anything moves.
safeguard fix --create-pr
One static binary
No runtime, no daemon, no language toolchain to install first. The same one-line install works on a laptop and inside a CI job.
→ /usr/local/bin/safeguard
Your code never leaves this machine
Safeguard uploads SBOMs and findings — never your source. The scan does not need the internet to do its work, so the same binary behaves identically everywhere you run it:
- laptop
- corporate proxy
- on-prem
- air-gapped
◌ capture · what enters never leaves
A terminal that scans, fixes, and answers
Run safeguard on its own and it opens the runner session — the job poller and the assistant, in one prompt.
One command, a whole session
Run
safeguardwith no arguments and the runner terminal opens./loginauthenticates this machine;/helplists the rest.A runner that comes to you
It claims the scan jobs queued for your tenant, runs them here on your own infrastructure, and posts the results back. Your code stays put; the platform stays current.
The assistant, inline
Ask why a finding matters or what a version bump breaks, and act on the answer without leaving the prompt.
Continuous watch. The runner polls for queued jobs in the background — the platform schedules, this machine executes.
The commands you'll actually type
The core of the surface. Every command below is in the shipped binary — run safeguard --help for the rest.
Set up
safeguard loginAuthenticate this machine over the OAuth 2.0 device flow (RFC 8628).
whoamireports the current token,logoutclears it.safeguard initWrite the local scanner configuration for your organization.
config show/config setadjust it afterwards.
Scan
safeguard scan --dir . | --repo URL | --image REF | --sbom FILEBuild the SBOM and match it against the advisory database. Takes a local directory, a Git repository, a container image, or an existing SPDX/CycloneDX document.
safeguard resolve PURLResolve a package's dependencies and version constraints, including transitive resolution.
safeguard validate FILE…Validate SBOM documents against the SPDX and CycloneDX specifications before you ship them.
Remediate
safeguard fix --severity highUpdate vulnerable packages to safe versions, write a patched SBOM, and emit a fix report.
--dry-runpreviews;--create-propens the pull request.safeguard patch-imageRebuild a container image with the patched layers applied, rather than re-vendoring the source.
safeguard reportGenerate a report from an existing scan result — the artifact you hand an auditor.
Run it for the platform
safeguard runnerOpen the on-prem runner. It claims scan jobs queued for your tenant, runs them here, and returns the results.
runner statusshows the current registration.safeguard updateRefresh the local vulnerability databases the scanners match against.
The same binary your laptop runs
No agent to provision, no image to maintain. Install it in the job, scan, and gate on the artifacts it writes.
Pin the version
SAFEGUARD_VERSIONpins the release;SAFEGUARD_INSTALL_DIRpicks where the binary lands. Neither needs root unless you install to/usr/local/bin.Read the artifacts
Every run writes the SBOM plus
vuln.json,license.json,secret.jsonandscorecard.jsonper component — machine-readable, so the gate is whatever policy you write.Or let the runner do it
For scans the platform schedules, register a runner instead. Same binary, same isolation, and the queue lives on the platform side.
- name: Install the CLI
run: curl -fsSL https://cli.safeguard.sh/install | SAFEGUARD_VERSION=1.0.0 bash
- name: Scan the working tree
run: safeguard scan --dir . --output out/
- name: Gate the build
# vuln.json is grype-compatible under .data.matches
run: |
jq -e '[.data.matches[].vulnerability.severity | ascii_downcase]
| index("critical") | not' out/*/vuln.jsonShown for GitHub Actions; the three steps are shell, so they port to GitLab CI, Jenkins, or anything else that can run a script.
One command, one binary
The installer detects your OS and architecture, verifies the release checksum, and drops a single safeguard binary on your PATH.
curl -fsSL https://cli.safeguard.sh/install | bashirm https://cli.safeguard.sh/install.ps1 | iexWindowsWhat the installer does
Detect
Reads your OS and architecture; anything unsupported stops here, before a single byte downloads.
uname -s · uname -m → darwin|linux · amd64|arm64Resolve
Takes the latest release — or exactly the one you pinned.
GET /releases/latest.txt → safeguard_1.0.0_linux_amd64.tar.gzVerify
Checks the archive against the published checksums. A mismatch aborts before anything runs.
sha256sum -c checksums.txtInstall
One binary onto your PATH. No root unless you chose /usr/local/bin.
install -m 0755 safeguard → /usr/local/bin
Prefer to read it first?
curl -fsSL https://cli.safeguard.sh/install -o install.sh && less install.shNinety-one lines of plain bash — the same file the one-liner pipes. Never pipe anything you would not read.
- SAFEGUARD_VERSION
- pin a release instead of taking the latest
- SAFEGUARD_INSTALL_DIR
- choose where the binary lands
Platforms
darwin/amd64readydarwin/arm64readylinux/amd64readylinux/arm64readywindows/amd64readynpmsoon
Ship clean. Stay clean.
One command to install. Everything after that runs on hardware you control.
curl -fsSL https://cli.safeguard.sh/install | bash