Install the Safeguard CLI with its curl installer, run safeguard detect with SARIF output, then upload the file with GitHub's upload-sarif action. The job needs the security-events write permission. There is no published Safeguard GitHub Action yet, so the CLI is the supported route today.
What the job does
Safeguard's CI/CD documentation shows one GitHub Actions pattern: a single job on an Ubuntu runner that checks out the code, installs the CLI, runs detect to write a SARIF file, and uploads that file to the code scanning tab. Nothing else is required to get findings into the Security tab of a repository.
SARIF is a standard interchange format for static analysis results, so GitHub can render each result as an alert on the right file and line.
The workflow
name: safeguard-detect
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
jobs:
detect:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@<pin to a full commit SHA>
- name: Install the CLI
env:
SAFEGUARD_VERSION: "<version from the download page>"
run: curl -fsSL https://cli.safeguard.sh/install | bash
- name: Detect
run: safeguard detect --path . --format sarif --output safeguard.sarif
- uses: github/codeql-action/upload-sarif@<pin to a full commit SHA>
with:
sarif_file: safeguard.sarif
The top level permission is read only. The job then asks for the one extra scope it needs. That follows GitHub's own advice to default the token to read and grant more per job.
Permissions that trip people up
GitHub's SARIF upload documentation says security-events write is required for all workflows that upload. It adds that actions read is needed for private repositories. It also says code scanning on private and internal repositories needs GitHub's code security features enabled for that repository.
If the upload step fails with a permission error on a pull request from a fork, that is the token being read only for forks. Plan for that rather than widening permissions.
Pin what you run
Two things in this job come from outside your repository: the actions and the installer script. Pin the actions to a full commit SHA, taken from the action's own repository. Pin the CLI with the version variable, and update it on purpose. The version to use is on the Safeguard download page.
What this job does not do
A passing run does not mean the code is clean. The documentation states that detect exits zero whenever the scan ran, regardless of findings, and that the CLI has no severity threshold flag. To block merges, use a platform policy gate or add your own check. See how to gate a build when the CLI never fails it.
Running it on a schedule too
Pull request runs catch new problems, but new advisories appear against code that has not changed. Add a scheduled trigger, for example weekly, so the same workflow runs on the default branch. Note that the scheduled run uses the default branch's workflow file, so keep that file current.
Keep the job fast. If detect takes minutes on a large monorepo, scope the path to the changed directories on pull requests and run the full tree on the schedule.
Quick check
Do I need a Safeguard GitHub Action?
No. The documentation says none is published yet. The recipe above uses the installer and the CLI directly.
Why did the upload step fail?
Most often the job lacks security-events write, or the repository does not have code scanning available. Check both first.
Where Safeguard fits
The CLI is one surface of the same engine that powers the web app, IDE extensions and policy gates. You can also try a free scan without touching a pipeline.
Sources
- Safeguard docs: CI/CD Integration
- Safeguard docs: CLI
- Safeguard download page
- GitHub docs: Uploading a SARIF file to GitHub
- GitHub docs: Security hardening for GitHub Actions
Last reviewed: 19 October 2026.