To check open source licences with Safeguard, run safeguard scan --dir . and read output/license.json, then open the project's Suppliers & Licenses tab to see each component's licence, obligations and compliance status. Write a licence policy with allow, deny and review lists, link it to a gate, and let CI fail the build on a denied licence.
You keep the AI tools you already pay for while you do this. Bring the Claude, ChatGPT or Codex plan you already pay for and use it inside the Safeguard CLI. Safeguard adds no extra charge for that usage; your plan's own usage limits and terms still apply. You can also connect Claude or ChatGPT to the Safeguard MCP server and ask about your licence findings from the chat you already use.
This guide follows a sample service called payments-api from the first local scan to a licence gate in CI.
What you will have at the end:
- A local scan of your repository with a
license.jsonfile you can read and keep. - A clear picture of each component's licence in the platform, including obligations and attribution needs.
- A written licence policy with allow, deny and review lists, scoped to the right products.
- A gate that fails a build when a denied licence enters the dependency tree.
- An exception process with a named approver and an expiry date.
- An attribution notice you can ship with a release.
- A short weekly routine.
A note before we start: this is a how-to for the tooling, not legal advice. What a licence asks of you depends on how you ship your software, and only your counsel can tell you how it applies to your product. Safeguard helps you find, sort and track licences so that conversation starts from facts.
Licence basics you need first
Two shared vocabularies make every later step easier: SPDX identifiers and the OSI list.
SPDX identifiers. The SPDX License List catalogues commonly found licences and exceptions used in free and open or collaborative software, data, hardware and documentation. Each entry has a short identifier, a full name, the licence text and a permanent URL. The list also marks which licences are OSI approved and which are FSF free/libre. The current version on the SPDX site is 3.29.0, dated 16 September 2026.
SPDX tries never to change identifiers, but it deprecates some, and a deprecated identifier stays valid while it "should no longer be used." The GNU licences are the case you will meet most: release 3.0 replaced the old identifiers with more explicit ones, so GPL-2.0 is deprecated in favour of GPL-2.0-only and GPL-2.0-or-later. Use the current identifiers in policy.
OSI approval. The Open Source Initiative says open source licences are licences that comply with the Open Source Definition, and that a licence must go through OSI's review process to be approved. That is a useful filter, but it does not tell you what a licence requires of you. Two OSI approved licences can carry very different obligations.
Licence expressions. Many packages carry more than one licence. SPDX expressions describe how they combine:
| Operator | Meaning | Example from the SPDX spec |
|---|---|---|
OR | A choice between licences | LGPL-2.1-only OR MIT |
AND | You must comply with all of them | LGPL-2.1-only AND MIT |
WITH | A licence plus an exception | GPL-2.0-or-later WITH Bison-exception-2.2 |
+ | This version or any later version | CDDL-1.0+ |
LicenseRef- | A licence not on the SPDX list | LicenseRef-MIT-Style-1 |
Precedence matters. The default order is +, then WITH, then AND, then OR, so LGPL-2.1-only OR BSD-3-Clause AND MIT means LGPL-2.1-only, or the pair BSD-3-Clause and MIT. Parentheses override that. Operators are case sensitive; licence identifiers are not, although SPDX recommends the canonical case.
How Safeguard finds and sorts licences
Safeguard combines several sources and reconciles them:
- Package metadata: licence fields in manifests such as
package.json,pyproject.toml,Cargo.tomland the licences section of a Maven POM. - SPDX identifiers: recognised against the SPDX License List.
- Full text matching: LICENSE, COPYING and NOTICE files compared with known licence texts.
- Header detection: licence declarations in source file headers.
- Binary extraction: copyright files under
/usr/share/docin container layers, and embedded licence strings.
When those sources disagree, Safeguard raises a license-discrepancy finding. The docs note this often points to a packaging error or a relabelling, so treat it as a question to answer, not noise to hide.
Each licence then lands in an obligation category. This is Safeguard's classification from its License Compliance docs:
| Category | Examples | Risk as Safeguard rates it |
|---|---|---|
| Permissive | MIT, BSD-2/3, Apache-2.0, ISC | Low |
| Weak copyleft | MPL-2.0, LGPL-2.1, LGPL-3.0, EPL-2.0 | Medium |
| Strong copyleft | GPL-2.0, GPL-3.0 | High for proprietary products |
| Network copyleft | AGPL-3.0, SSPL-1.0 | High for SaaS |
| Commercial or proprietary | Custom, vendor specific | Depends |
| Public domain or dedication | CC0-1.0, Unlicense | Low |
| Unknown or unidentified | None | Review required |
Each classification links to an explanation of obligations such as attribution, source disclosure and patent grants. Compound expressions are supported in full. For an OR expression, Safeguard picks the most permissive option that matches your policy. For AND, both licences apply. For WITH, the exception is carried with the licence.
Step by step: check licences on your own machine
Start local. A scan on your laptop shows you the licence picture before anything else is set up, and your source stays on the machine.
-
Install the CLI. On macOS or Linux:
curl -fsSL https://cli.safeguard.sh/install | bash safeguard --versionOn Windows, in PowerShell:
irm https://cli.safeguard.sh/install.ps1 | iexIt is a single static binary, so you need no Node, Python or JVM. If you want a walkthrough with screenshots, see installing the Safeguard CLI on macOS.
-
Sign in. Run
safeguardwith no arguments to open the interactive terminal and type/login. It signs you in through the browser. -
Scan the repository. From the root of
payments-api:safeguard scan --dir .The scan builds an SBOM and matches it against vulnerability databases. Results are written as JSON files under
./output, includingvuln.jsonandlicense.json. Use--outputto pick another folder:safeguard scan --dir . --output ./scan-2026-10-21 -
Mark your own packages. If your company publishes internal packages under a namespace, tell the scan so it can identify them as private rather than leave them looking like unknown third party code:
safeguard scan --dir . --org-namespace @mycompanyThere is a matching
--third-party-namespaceflag for vendor namespaces. -
Open
license.json. List the folder, then pretty print the file with Python's standard library so it is easy to read:ls output python3 -m json.tool output/license.json | lessOn the first pass, look for unknown licences, anything in the strong or network copyleft categories, and anything you do not recognise.
-
Ask the assistant to sort it. Open
safeguardin the same folder and attach the file with@:@output/license.json list every component whose licence is not MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause or ISC, grouped by licenceReading a file runs without changing anything. You get a short list to take to whoever owns licence decisions.
-
Scan images and SBOMs too. Licences ride along in containers and vendor deliveries. The same command takes other inputs:
safeguard scan --image registry.example.com/payments-api:1.8.0 safeguard scan --sbom vendor-sbom.spdx.jsonCheck a vendor's SBOM first with
safeguard validate vendor-sbom.spdx.json, which checks CycloneDX, SPDX and VEX documents.
One limit to know up front: the docs say there is no CLI command yet for licence listing, reports or policy evaluation. The CLI writes license.json; reports, policies and gates live in the platform.
Read the licence views in the platform
Once a project is in Safeguard, the licence data gets a home where your whole team can see it.
The Suppliers & Licenses tab. Open a project and go to the Suppliers & Licenses tab. The summary at the top shows Total Licenses, License Types, Compliance Status and Attribution Required. Click a component to see its SPDX identifier, licence text, obligations, attribution requirements and a compatibility analysis.
Each component carries one of four compliance statuses:
| Status | What to do |
|---|---|
| Compliant | Nothing, it matches your policy |
| Review Needed | Someone who owns licence decisions looks at it |
| Violation | It matches a deny rule; replace it or file an exception |
| Unknown | Find the licence before you ship |
The Licenses dashboard. For a view across every project, the Licenses dashboard shows licence distribution across your fleet, new licence introductions over time, and the policy violation count and its trend. "New licence introductions" is the line to watch week to week, because it tells you when a dependency change brought something new in.
Exports. From a project you can export:
- Attribution Notice (Export, then Attribution Notice) as TXT, HTML or Markdown, from a template you can change. It includes component name and version, licence type, copyright notices, licence text where required and supplier information.
- License Report (Export, then License Report), with Summary, Detailed, Attribution and Compliance report types.
- Per asset licence manifests from the Licenses dashboard in Excel, CSV, SPDX and CycloneDX formats.
For a redistributed artifact, Safeguard can also produce a NOTICE or THIRD-PARTY-NOTICES.txt file, a licenses/ folder with copies of the required licence texts, and a machine readable SPDX document for each release. There is no CLI command for these yet, so generate them in the platform.
Write a licence policy and enforce it
Seeing licences is half the job. The other half is deciding which ones are fine.
Create the policy
- Go to Settings, then License Policies, then + New Policy.
- Pick the scope: the whole organisation or a single project.
- Add rules. There are three rule types: Allowlist, Blocklist and Review List.
- Save, and check the Suppliers & Licenses tab on a project in scope. The statuses update against your new rules.
If you prefer to keep policy in version control, the same rules can be written in YAML. This is the example from Safeguard's docs:
apiVersion: safeguard.sh/v1
kind: LicensePolicy
metadata:
name: default
spec:
allow:
- MIT
- BSD-2-Clause
- BSD-3-Clause
- Apache-2.0
- ISC
- MPL-2.0
deny:
- GPL-3.0-or-later
- AGPL-3.0-or-later
- SSPL-1.0
require_review:
- GPL-2.0-only
- LGPL-3.0-or-later
- "Custom/*"
context_overrides:
- apply_to: { env: sdk }
deny:
- LGPL-3.0-or-later # LGPL tricky in SDK distribution
- apply_to: { env: server }
allow:
- LGPL-3.0-or-later # fine for a service binary
The lists are examples, not a recommendation. Build yours with your counsel. Two parts deserve attention.
require_review sends a licence to a person instead of deciding automatically, and accepts wildcards like Custom/*.
context_overrides lets one policy treat the same licence differently depending on how you ship. Policies can be scoped to asset labels, so an SDK you hand to customers and a service you run yourself can follow different rules.
Where it is enforced
Licence policies plug into Guardrails and Enforcement at three points:
- CI time: builds fail if a denied licence appears in the dependency tree.
- Pull request time: a new direct dependency with a denied licence triggers a blocking check.
- Admission: images with denied licences cannot deploy to production.
Findings show the transitive path to the component, so you can see which direct dependency pulled it in.
Wire the gate into CI
Link the licence policy to a gate, for example one called Release. Then add a job that scans each push and waits for the gate. Create a secret key with the scans:trigger and scans:read scopes and store it in CI as SAFEGUARD_API_KEY:
# .github/workflows/safeguard.yml
name: Safeguard
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- name: Safeguard scan
env:
SAFEGUARD_API_KEY: ${{ secrets.SAFEGUARD_API_KEY }}
SAFEGUARD_INSTALL_DIR: ${{ runner.temp }}/safeguard-bin
run: |
set -eu
curl -fsSL https://cli.safeguard.sh/install | bash
"$SAFEGUARD_INSTALL_DIR/safeguard" ci scan --wait --fail-on-gate Release
safeguard ci scan runs the scan on Safeguard and records it as version <branch>-<sha7>. With --fail-on-gate, the step fails when the gate is Failed, Error or Not evaluated, and passes on Passed or Warning, printing any warn and notify policies that failed. The default timeout is 30 minutes for the scan and the gate together. Gate outcomes need the policy outcomes feature turned on for your workspace. Make the job a required check on your main branch so a failure actually stops a merge.
Exceptions
Sometimes the answer is "yes, for now." Licence exceptions use the same workflow as vulnerability exceptions. Each one needs a named approver, an expiry date and a written business justification. Exceptions expire on their own and the finding is evaluated again at expiry, so a temporary yes cannot quietly become permanent.
Do the work properly with the Safeguard CLI
Finding a denied licence is the easy part. Replacing the dependency and proving nothing broke is where time goes. The Safeguard CLI does that work with you, on your machine.
Install and first session
Install with the commands above, run safeguard, and sign in with /login. Type /scan . to scan the current folder from inside the session. You can ask in plain language, and the assistant picks the tools the question needs: your local files, your Safeguard data, or both.
Writing and fixing code
The assistant can write files, edit code and run commands, and each of those asks before it acts. For a licence finding, a request like this works well:
the platform flags a dependency in payments-api with a denied licence. find which direct dependency pulls it in, suggest a replacement with a permissive licence, update package.json and run the tests
The recorded demo below shows the same loop on a vulnerability. You install with the curl command, check safeguard --version, open the interactive terminal and ask it to fix the lodash CVE. The assistant reads the finding, the files and the advisory, then asks before each command. It edits package.json, runs npm install and npm test with your approval, prints a summary with a suggested commit message and pushes nothing. It ends with /permissions, /model and /scan ..
Click through it at your own pace, or open it full screen.
After the change, run safeguard scan --dir . again and compare the new license.json with the old one before you open the pull request. If the swap was written by any coding agent, the same check applies; see reviewing AI generated code before merge.
Using your Claude, ChatGPT or Codex plan
You do not have to change assistants to use Safeguard. Bring the plan you already pay for into the CLI, with no extra Safeguard charge for that usage and your plan's own limits and terms still in force. Use /model to see or switch the model, and see the CLI docs for connecting one. If you live in a chat app instead, connect Claude to the Safeguard MCP server and ask about licence findings there.
Approvals
/permissions sets how much the assistant may do on its own:
| Mode | What runs without asking |
|---|---|
| Ask | Reads run; edits and commands ask first |
| Accept edits | Edits in this folder and read only commands; other commands ask |
| Plan | Nothing changes; it reads and plans only |
| Auto (default) | Read only commands and what the policy allows; anything else asks |
| Strict | Pre-approved actions only, for CI |
There is also a --yolo flag that approves everything. Keep it for throwaway sandboxes. For dependency swaps, Ask or Accept edits keeps you in the loop on every install command.
Approving from your phone
A CLI session is live. It shows in the web app, the desktop app and the phone app, and those devices can send work to a computer running the CLI. In the recorded Android session below, the same conversations appear on the phone. "Work on my computer" picks a computer running the CLI and a folder, the command waits for Allow once, Allow for turn or Deny on the phone, and the answer shows the tests passed.
Click through it at your own pace, or open it full screen.
More on the phone app is in Safeguard on Android phones and tablets.
CI with safeguard exec
safeguard exec runs one non-interactive assistant turn, which suits a scheduled job that writes a summary for humans:
safeguard scan --dir . --output ./output
safeguard exec "read output/license.json and summarise any component that is not permissive, with its licence and the package that pulls it in"
Use it for summaries and keep the pass or fail decision with the gate. The CLI does not evaluate policies or gates; the platform does. There is a full walkthrough in running the Safeguard CLI in CI with safeguard exec.
Your source code never leaves the machine when the local runner runs platform scan jobs; only SBOMs and findings are uploaded.
A weekly routine that keeps licences checked
- Monday, ten minutes: open the Licenses dashboard. Check new licence introductions and the violation trend.
- Work the Review Needed list. Decide each one, then move the licence into the allow or deny list so the same question does not come back.
- Chase Unknowns. Ask the maintainer, check the repository's LICENSE file, or replace the package.
- Check exceptions due to expire. Renew with a fresh justification or fix the finding.
- On release day: export the Attribution Notice and the SPDX document for that release and ship them with the artifact.
Troubleshooting and common mistakes
Troubleshooting
- A component shows Unknown. None of the detection sources found a licence. Look for a LICENSE, COPYING or NOTICE file in the package. If the licence is custom, add a
Custom/*pattern to your review list. - A
license-discrepancyfinding appears. Two sources disagree, for example the manifest says one licence and the LICENSE file another. Read the actual text and record your decision. - The CI step fails with Not evaluated. No policy is linked to the gate yet, or evaluation did not finish before
--timeout. Link the licence policy and run again. - A script against the licence API returns 404. The docs say the
/v1REST endpoints for licences, suppliers and attribution are not available yet. Use the platform exports for now.
Common mistakes
- Using deprecated identifiers in policy. Write
GPL-2.0-onlyorGPL-2.0-or-later, notGPL-2.0. - Treating OSI approved as "no obligations." OSI approval says a licence meets the Open Source Definition. Attribution and other obligations still apply.
- Blocking on day one. Start with a review list, clear the backlog, then deny. A gate that blocks every build in week one gets switched off.
- One policy for every product. Use
context_overridesand asset labels so an SDK and a hosted service follow the rules that fit how each one ships. - Ignoring transitive dependencies. Most surprises arrive two or three levels down. Use the transitive path in the finding to find the direct dependency you control.
- Forgetting containers. Base images bring their own packages. Scan the image too.
Frequently asked questions
Does the Safeguard CLI check licences?
Yes, in the sense that safeguard scan writes license.json with the licences it found, next to the other scan results. Licence listing, reports and policy evaluation are not CLI commands yet; they run in the platform.
Where do I see licences in the platform?
Open a project and go to the Suppliers & Licenses tab for per component detail and status. Use the Licenses dashboard for the view across all projects, including new licence introductions and the violation trend.
Can Safeguard tell me whether I comply with a licence?
It identifies each licence, classifies its obligations and checks it against your policy, then gives each component a status of Compliant, Review Needed, Violation or Unknown. Whether your product meets a licence's terms is a legal question for your counsel. Safeguard gives them the inventory to start from.
How does Safeguard handle dual licensed packages?
It supports full SPDX expression syntax. For an OR expression, it picks the most permissive option that matches your policy. For AND, both licences apply. WITH keeps the exception attached to the licence.
Can I keep using Claude, ChatGPT or Codex?
Yes. Bring the Claude, ChatGPT or Codex plan you already pay for and use it inside the Safeguard CLI. Safeguard adds no extra charge for that usage; your plan's own usage limits and terms still apply. You can also connect Claude or ChatGPT to the Safeguard MCP server and use Safeguard from the chat you already use.
Can I generate a NOTICE file?
Yes, in the platform. Export an Attribution Notice as TXT, HTML or Markdown, or generate a NOTICE or THIRD-PARTY-NOTICES.txt file with a licenses/ folder for a release. There is no CLI command for it yet.
Does my source code leave my machine?
A local safeguard scan runs on your machine and writes results to ./output. When the local runner runs platform scan jobs, your source code never leaves the machine; only SBOMs and findings are uploaded.
What about licences in vendor software?
Ingest the vendor's SBOM. Safeguard applies the same classification, checks whether the vendor's licences are compatible with your product and hit your deny list, flags licence changes between versions, which can mean a relicensing, and feeds the result into your third party risk assessments.
Try it yourself
This demo sets up the runner on your own machine: pick the platform, start it, approve it with its device code, then use the same CLI to scan from the terminal.
Click through it at your own pace, or open it full screen.
When you are ready, download Safeguard for the CLI, the desktop app or your phone, and keep the CLI docs open for your first scan.
Quick check
Where does a local Safeguard scan write its licence results?
To license.json under ./output, next to vuln.json and the other result files. Use --output to choose a different folder.
In SPDX, what does LGPL-2.1-only OR BSD-3-Clause AND MIT mean?
LGPL-2.1-only, or the combination of BSD-3-Clause and MIT. AND binds tighter than OR unless parentheses say otherwise.
Who evaluates licence policies and gates, the CLI or the platform?
The platform. The CLI produces the scan results; the platform applies your licence policy and decides the gate outcome, which safeguard ci scan --fail-on-gate then reports in CI.
Sources
- Safeguard docs: CLI
- Safeguard docs: License Compliance
- Safeguard docs: Suppliers & Licenses
- Safeguard download page
- SPDX License List
- SPDX Specification 2.3.1, Annex D: SPDX license expressions
- Open Source Initiative: Licenses
Last reviewed: 21 October 2026.