Safeguard can reach your code in three ways. A repository connection lets Safeguard clone and scan the repository on its side with a token you scope. The CLI scans on your own machine and writes results locally. The local runner, built into the CLI, runs platform scan jobs on your machine and uploads only the SBOM and findings, never the source.
Which one you pick should follow from what the code is, who is allowed to process it, and where. That is a data protection and least-privilege decision before it is a tooling decision, so this post starts with the rules that shape it (GDPR, DORA, NIST SP 800-53 and the NIST SSDF), then walks through each access mode exactly as Safeguard's documentation describes it, and ends with a decision table and the limits you should know before you sign anything.
Key takeaways
- Repository connection (GA): GitHub, GitLab, Bitbucket Cloud and Azure DevOps Services connect with a token you scope. Scanning needs read access only; Safeguard deletes its temporary clone after the scan and keeps the SBOM and findings, not the source.
- CLI (GA):
safeguard scanruns on your machine and writes JSON results locally. Nothing is uploaded unless you scan while signed in from the interactive terminal. - Local runner (GA): part of the CLI. The machine polls Safeguard over outbound HTTPS for jobs, runs them locally, and uploads only the SBOM and findings. Nothing connects in to it.
- CI scan (GA):
safeguard ci scaneither asks Safeguard to scan the connected repository, or, with--local, scans the checkout on the build machine so only results leave it. - Zero AI mode and bring your own model (GA): run the platform with no LLM at all, or route Safeguard's AI features to a model you have already approved.
- Private VPC, on-prem and air-gapped deployment (GA): for data that cannot touch shared SaaS at all, including Safeguard's own models running inside your environment with signed offline snapshots.
- Autonomous remediation and fix pull requests (GA, ships off): only possible with write access on a repository connection. Every category starts on Manual.
- SAST (early access): included when Safeguard scans a connected repository in CI, but not part of the CI build failure threshold yet.
The three access modes at a glance
| Repository connection | CLI scan | Local runner | |
|---|---|---|---|
| Maturity | GA | GA | GA |
| Where the scan runs | Safeguard's infrastructure | Your machine or build agent | Your machine or build agent |
| What Safeguard receives | A token, then a shallow clone during the scan | Nothing, unless you scan while signed in | The SBOM and findings for each job |
| Source code stored by Safeguard | No (temporary clone, deleted after the scan) | No | No |
| Credential Safeguard holds | Your SCM token, encrypted at rest | None for local scans; a sign-in token stays on your machine | A sign-in token on your machine |
| Network direction | Safeguard reaches out to your SCM | None needed for the scan itself | Outbound HTTPS from your machine only |
| Can open fix pull requests | Yes, if you grant write access | No | The assistant can edit local code with your approval; nothing is pushed unless you push |
| Best for | Teams comfortable granting read access to a hosted SCM | Ad hoc scans, CI artifacts, offline checks | Private or firewalled code that must stay put, with results in the platform |
The rest of this post explains where each row comes from.
The problem: a security tool is also a third party that reads your code
Every scanner that reads source code is, from a compliance point of view, a supplier with access to one of your most sensitive assets. Source repositories hold proprietary logic, internal hostnames, infrastructure definitions and, very often, personal data: commit author names and email addresses, test fixtures copied from production, support scripts with customer identifiers. When a tool clones that repository, it processes all of it.
Security teams judge scanners on coverage and noise. Data protection and risk teams ask who processes the data, where, under what contract and with what access. Without good answers, the purchase stalls at review or goes through with broader access than anyone intended.
Three bodies of rules shape those questions for most buyers.
What GDPR Articles 28, 32 and 44 imply for a tool that reads your source
If a repository contains personal data and the tool processes it on your behalf, the vendor is acting as a processor under the GDPR, and three articles matter most.
Article 28 (processor). Article 28(1) says a controller may only use processors "providing sufficient guarantees" to implement appropriate technical and organisational measures. Article 28(2) says a processor cannot engage another processor without the controller's prior written authorisation, which is why buyers ask for a vendor's sub-processor list. Article 28(3) requires a binding contract that, among other things, limits processing to the controller's documented instructions, including on transfers to third countries (point (a)), requires the processor to take the measures in Article 32 (point (c)), deletes or returns the data at the end of the service (point (g)), and makes available the information needed to demonstrate compliance and allow audits (point (h)).
The EDPB's Guidelines 07/2020 on the concepts of controller and processor (final version adopted 7 July 2021) are the reference for working out which role a tool vendor plays in a given setup and what the Article 28 contract has to cover.
Article 32 (security of processing). Article 32(1) asks controller and processor to implement measures appropriate to the risk, listing encryption and pseudonymisation (point (a)), ongoing confidentiality, integrity, availability and resilience (point (b)), the ability to restore access after an incident (point (c)), and regular testing of the measures (point (d)). Article 32(2) points at the risks that matter most here: unauthorised disclosure of, or access to, data "transmitted, stored or otherwise processed".
Article 44 (transfers). Any transfer of personal data to a third country may only happen if the conditions in Chapter V are met, including for onward transfers. For a tool vendor, that turns into two concrete questions: in which region does the processing happen, and does any part of it (an AI model call, for example) leave that region?
The practical reading: the less of the repository a vendor processes and keeps, the smaller the Article 28 and 32 surface and the simpler the Article 44 answer.
What DORA's ICT third-party rules add for financial entities
Regulation (EU) 2022/2554, the Digital Operational Resilience Act, has applied since 17 January 2025 to EU financial entities, and Articles 28 to 30 set out how they manage ICT third-party risk. A scanning platform that reads code is an ICT service, so these articles apply to the purchase.
- Article 28(1)(a): the financial entity remains fully responsible for compliance even when it uses an ICT third-party service provider. Outsourcing the scan does not outsource the obligation.
- Article 28(4): before contracting, the entity must assess whether the service supports a critical or important function, identify and assess the relevant risks including concentration risk, and carry out due diligence on the provider.
- Article 28(8): for services supporting critical or important functions, the entity needs a tested exit strategy.
- Article 29: the preliminary assessment of ICT concentration risk, including, for providers established in a third country, consideration of compliance with Union data protection rules and the effective enforcement of the law in that country.
- Article 30(2)(b) and (c): the contract must state the regions or countries where the service is provided and where data is processed and stored, with advance notice of changes, and must include provisions on availability, authenticity, integrity and confidentiality of data.
For a scanning tool, Article 30(2)(b) is the line procurement reads first. If the source never leaves your environment, the location answer for the code itself becomes your own infrastructure.
Least privilege: NIST SP 800-53 AC-6 and SSDF PO.5
The US control catalogs make the same point from the access side.
NIST SP 800-53 Rev. 5, AC-6 (Least Privilege) asks organisations to allow only the accesses that users, or processes acting on their behalf, need for their tasks. The supplemental guidance extends this to system processes, which should operate at "privilege levels no higher than necessary". A scanning integration is exactly such a process. AC-6(5) adds that privileged accounts should be restricted to specific personnel or roles.
NIST SP 800-218, the Secure Software Development Framework (SSDF) Version 1.1, published February 2022, puts the development environment itself under protection. Practice PO.5 asks organisations to keep every environment involved in software development strongly protected. PO.5.1 is to separate and protect each environment; its examples include tightly restricting connections into and out of each environment and minimising internet access to what is necessary. PO.5.2 is to secure and harden development endpoints, including giving them the least functionality needed and enforcing least privilege.
Together they give six practical questions for any tool that touches your code:
- Does it need write access, or can it work read-only?
- Can the token be scoped to specific repositories, or does it reach everything a person can see?
- Does anything need to connect into the build or development environment, or is all traffic outbound?
- Does the tool keep a copy of the code, and if so, for how long and where?
- Does any AI model see the code, and whose model is it?
- Can we cut the tool off cleanly, rotate its credentials and get our data out?
The three access modes answer these questions differently.
Option 1: the repository connection
A repository connection is the simplest way to start. You give Safeguard a token, pick repositories, and Safeguard clones and scans them on its side. Repository connections for GitHub, GitLab, Bitbucket and Azure DevOps are GA.
What a repository connection grants
Each SCM card lives under Integrations, on the Project/Product tab. Per Safeguard's docs, each repository you select, at a branch or tag, becomes a project that Safeguard clones and scans for an SBOM and findings. With write access, Safeguard can also open fix and upgrade pull requests, comment on pull requests and set a commit or build status for the quality gate.
The important detail is that, for scanning, Safeguard only reads. Write access is optional and only needed for features you choose to use. Here is the least-privilege setup each docs page recommends:
| SCM | Credential type | Least privilege for scanning | Optional write access, for fix pull requests and quality gate |
|---|---|---|---|
| GitHub.com, GitHub Enterprise Cloud, GitHub Enterprise Server | Fine-grained personal access token (recommended) or classic token | Metadata: Read-only and Contents: Read-only, with Repository access set to Only select repositories | Contents: Read and write; Pull requests: Read and write; Commit statuses: Read and write |
| GitLab.com or self-managed GitLab | Group access token (recommended for teams), project token or personal token | Group access token with the Reporter role and the read_api and read_repository scopes | The api scope, with the Developer role |
| Bitbucket Cloud | Atlassian API token with Bitbucket scopes | read:user:bitbucket, read:workspace:bitbucket and read:repository:bitbucket | Write scopes for pull requests and build status |
| Azure DevOps Services | Personal access token scoped to one organisation | Code (Read) and Project and Team (Read) | Code (Read and write); Service Hooks for automatic webhook setup |
Some details matter for an access review:
- Tokens only, no app installs yet. Safeguard's docs say a GitHub App installation and "Sign in with GitHub" are not available; the dialog takes a personal access token. GitLab, Bitbucket and Azure DevOps sign-in through OAuth or Microsoft Entra ID are likewise listed as not available. That means the credential belongs to a person or a service account you control, and you choose its expiry.
- Classic GitHub tokens are broad. GitHub has no read-only classic scope for private repositories, so the
reposcope grants read and write to every private repository the account can reach. Safeguard's docs steer you to fine-grained tokens for that reason, and GitHub's own documentation recommends fine-grained tokens over classic ones whenever possible. - What Safeguard never needs. For GitHub, the docs list admin or organisation scopes, webhook scopes, Actions, Secrets, Administration and repository deletion as never needed, and no write access at all when you only scan. The Bitbucket page says the same of admin, delete, webhook, pipeline, runner and SSH key scopes.
- Self-hosted servers must be reachable. A GitHub Enterprise Server or self-managed GitLab must be reachable from the internet over a public address. Safeguard does not send a token to private or internal addresses. If your SCM sits behind a firewall with no public endpoint, a repository connection will not work, and the CLI or local runner is the route.
- Coverage gaps. Bitbucket Data Center appears in the dialog but is not supported yet; only Bitbucket Cloud repositories list. Azure DevOps Server (self-hosted) is not supported; only Azure DevOps Services connects. At the time of writing, the Bitbucket docs also carry a notice that Verify Credentials on the Private tab can fail with "Invalid credentials" even when a token is correct, because Bitbucket Cloud retired two endpoints the check uses. Public repositories are not affected.
- No webhooks by default. GitHub, GitLab and Bitbucket connections have no webhooks to set up. Each repository is scanned when you connect it; to rescan new commits you set a schedule under Integrations › Scheduled or choose Rescan. Azure DevOps can optionally use service hooks for scan on push and pull request review, and the docs show both the automatic and manual setup.
What Safeguard reads, stores and does not store
Each SCM docs page has a "What we read and store" section, and they say the same thing in substance:
- Read: your login and the repository list the token can see, repository details, branches and tags, and the contents of each selected repository at the chosen branch or tag. For pull request features, the pull request, its changed files and its comments.
- Stored: the connection's settings, the repositories you selected, the SBOM and findings of each scan, and the token, which is encrypted at rest with a per-workspace key and never shown again after you save it.
- Not stored: source code. The scanner makes a shallow clone into a temporary folder and deletes it when the scan ends.
- LLMs: the docs state that no customer data from these integrations is sent to third-party LLMs.
That answers most Article 32 storage questions, but your code is still processed, briefly, on Safeguard's infrastructure. If the transient clone itself is the problem, the next two modes are for you.
Rotation and disconnection
The docs document both flows. To rotate, create a new token with the same permissions, choose Update on the connection under Project Configurations, paste and Check it, save, then delete the old token in the SCM. To disconnect, choose Delete and then delete the token on the SCM side. Pick an expiry such as 90 days and put the rotation in a calendar, because scans fail when a token expires.
Option 2: the CLI, scanning on your own machine
The Safeguard CLI (GA) is a single static binary for macOS, Linux and Windows. Its docs say there is no runtime to install alongside it: no Node, no Python, no JVM. It downloads its scanner tools the first time you open the interactive terminal.
How the CLI scans locally
safeguard scan builds an SBOM for one target, matches it against vulnerability databases, and writes the results as JSON files under --output (default ./output). The docs list these targets:
# A local directory (your own or proprietary code)
safeguard scan --dir .
# A container image
safeguard scan --image nginx:latest
# A Git repository
safeguard scan --repo https://github.com/org/repo
# A private repository
safeguard scan --repo https://github.com/org/private-repo --git-token "$GIT_TOKEN"
# An SBOM you already have (SPDX or CycloneDX, detected automatically)
safeguard scan --sbom sbom.json
Results land in a folder per scan, including vuln.json, license.json and collection.json. The scan runs scanner tools that the CLI downloads and manages itself.
What leaves the machine
For a plain safeguard scan, the results stay in the output folder. The docs are explicit that to see results in the platform alongside your other projects, you scan from the interactive terminal (/scan .) while signed in, and the runner then uploads the SBOM and findings, never your source.
A few other network events are worth knowing about, because a data protection review will ask:
- First run downloads. The first interactive run downloads the scanner tools and the vulnerability database.
safeguard updaterefreshes the databases later. These are inbound downloads, not uploads of your data. - Offline databases. For a machine with no internet access,
safeguard update --importloads a vulnerability database you downloaded elsewhere. - Transitive resolution is opt-in and external. The
--resolve-transitiveflag resolves transitive dependencies through deps.dev, a public service. That sends package identifiers, not source, to that service. Leave the flag off if your policy forbids it. - Update checks.
SAFEGUARD_NO_UPDATE_CHECK=1skips the background release check. - Credential storage. The sign-in token is a file readable only by you (mode 0600) at
~/.scanner/token.jsonby default. SettingSAFEGUARD_CREDENTIAL_STORE=nativekeeps it in the operating system's credential store instead (macOS Keychain, the Linux Secret Service or Windows DPAPI).
An SBOM is not source code, but it reveals your stack. Treat uploaded SBOMs and findings as confidential data in your records of processing.
Installing it with integrity checks
Safeguard's installation docs encourage you to read the install script before piping it to a shell. They also document one security-relevant difference: when a release's checksums.txt is missing, the macOS and Linux installer fails closed, while the Windows installer warns and continues. SAFEGUARD_VERSION pins an exact release, which the docs recommend for CI.
Option 3: the local runner
The local runner (GA) is the answer for teams that will not grant a cloud service access to a repository but still want results in the platform. Safeguard's docs are careful to say the runner is not a separate product. It is part of the safeguard CLI.
How it works
The docs describe four steps:
- The runner sends a heartbeat and polls the platform for jobs assigned to this machine. All traffic is outbound HTTPS that the runner opens. Nothing connects to it.
- It executes a claimed job with its own local scan server.
- It uploads the result files (SBOM and findings) and reports the job status.
- Source code stays on the machine.
This matches Safeguard's stated network posture of polling only, with no open inbound connections. For a firewall review, nothing needs to reach into your network.
The runner docs list three situations it is built for: a private repository where you cannot or will not grant OAuth access to a cloud service; a restricted network where only outbound HTTPS is allowed; and having the assistant fix vulnerabilities in code you have not pushed yet.
Long polling or fixed interval
safeguard runner start long-polls by default. If your network forbids held connections, --poll-wait 0 polls at a fixed interval instead, set by SAFEGUARD_POLL_INTERVAL in seconds (default 10).
Signing in and approving the machine
Per the docs, you open the interactive terminal with safeguard, type /login, your browser opens, and you approve the session. The runner starts after that. /whoami shows the signed-in identity and /logout ends the session. There is no API key environment variable for the CLI: a machine is authorised by signing in once, and that identity is what the platform assigns jobs to.
For headless machines, SAFEGUARD_NO_BROWSER stops the terminal from opening a browser for /login. The local runner demo at the end of this post shows the approval step with a device code.
The assistant on the runner
The runner also serves assistant turns. safeguard agent runs the assistant interactively in a workspace, and safeguard exec runs one non-interactive turn for scripts and CI. The docs say safeguard exec defaults to strict permissions, where nothing is asked and anything the policy file has not pre-approved is denied. runner start takes --permission-mode to set how much the assistant may do without asking.
Treat assistant turns as a separate data flow from scans: an assistant asked to fix code has to read that code. If that matters, set the tenant's AI mode first (see below) and confirm the routing with Safeguard for your deployment.
Step by step: set up the local runner, run a first scan, then run it in CI
The steps below use only commands that appear in Safeguard's docs.
Part A: a first scan on your own machine
- Install the CLI. On macOS or Linux, run
curl -fsSL https://cli.safeguard.sh/install | bash. On Windows, runirm https://cli.safeguard.sh/install.ps1 | iex. Confirm it withsafeguard --version. If the version is not what you expect,which -a safeguardshows every copy on your PATH. - Open the interactive terminal. Run
safeguard. The first run downloads the scanner tools and the vulnerability database. - Sign in. Type
/login. Your browser opens; approve the session. The terminal picks it up and the machine starts polling the platform for work assigned to it. - Scan the current folder. From inside your repository, type
/scan .. The scan runs locally. Because you are signed in, the SBOM and findings are uploaded to the platform, and the source stays on the machine. - Review results in the platform. The project now appears alongside your other projects, with its SBOM and findings. Policies and gates are evaluated in the platform, not by the CLI, so this is where pass and fail decisions happen.
- Run it headless if you want a standing runner. On a machine that should serve jobs without the terminal UI:
# Start without the terminal UI and serve assistant turns for this workspace
safeguard runner start --workspace ./path/to/repo
# Is it running, and what is it doing
safeguard runner status
# Drain in-flight work and stop
safeguard runner stop
- Keep it current.
safeguard self-updateupdates the binary.safeguard updaterefreshes the vulnerability databases. The two are different commands, and the docs call that out.
Part B: the same scan in CI
CI uses safeguard ci scan. Here the authentication model changes: CI does not sign in through a browser, it uses a secret key.
- Create a secret key in Safeguard under Settings › Developer with the scopes
scans:triggerandscans:read. You can lock it to one project, which is the least-privilege choice. - Store it in your CI as a secret named
SAFEGUARD_API_KEY. - Choose where the scan runs. This is the access mode decision again, in CI form:
| Mode | Command | Needs | Scans |
|---|---|---|---|
| On Safeguard (default) | safeguard ci scan | The repository connected as an integration, or public on github.com, gitlab.com or bitbucket.org | SAST (early access), SBOM, dependency vulnerabilities |
| On the build machine | safeguard ci scan --local | A checkout in the job; no integration | SBOM, dependency vulnerabilities |
With --local, only the results leave the build machine, so it also works for self-hosted and firewalled Git servers. It reads dependencies from lockfiles and manifests such as package-lock.json, go.sum, requirements.txt and pom.xml.
- Add the step. For GitHub Actions, the docs give this workflow as
.github/workflows/safeguard.yml:
name: Safeguard
on:
push:
branches: [main]
pull_request:
branches: [main]
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 critical
As written, this runs the scan on Safeguard, which clones the repository, so no checkout step is needed. To keep the source on the build machine instead, the docs say to add uses: actions/checkout@v4 before the step and --local to the command.
- Decide what fails the build.
--waitwaits for the scan (default timeout 30 minutes).--fail-onfails on a dependency vulnerability at or above critical, high, medium or low.--fail-on-gatefails when a named policy gate, orall, is not Passed or Warning. Per the docs, SAST findings are scanned and shown in Safeguard but are not part of--fail-onyet. - Pin the CLI version. Add
SAFEGUARD_VERSIONto the step's environment so a new release does not change a build under you.
For any other CI that runs a shell step, the docs show the same command with the repository URL, branch and commit passed explicitly:
curl -fsSL https://cli.safeguard.sh/install | bash
SAFEGUARD_API_KEY=... safeguard ci scan --wait --fail-on critical \
--repository-url "$REPO_URL" --branch "$BRANCH" --commit "$COMMIT"
Each push becomes a new version of its Safeguard project, named after the branch and commit (for example main-a1b2c3d).
How Zero AI mode and bring your own model change what any model sees
Access mode decides where code is processed. AI mode decides whether any model is involved at all, and whose. Safeguard treats this as a per-tenant setting, and the options are GA.
| AI mode | What it means | What a model sees |
|---|---|---|
| Full AI | Safeguard's own models are in the loop | Safeguard's models process the data the AI features use |
| Zero AI | The platform runs deterministically with no LLM anywhere in the loop | No model sees anything; scanners still work |
| Bring your own model | Safeguard's AI features call a model you supply | Your approved provider or your own endpoint, under your agreement |
| Local and on-prem models | Safeguard's models run as quantized builds inside your environment | Only models running on your infrastructure |
Zero AI mode is the shortest answer to a hard no-AI policy. Per Safeguard's offering, the entire platform runs deterministically with no LLM, and every scanner still works. The AI models docs describe "Zero" as having no model weights and no inference, running in process on the platform to answer data questions. What you give up is the AI-driven work: model-written fix proposals, natural language chat and similar features.
Bring your own model fits teams that already have an approved model list. Safeguard's offering names Claude, OpenAI, Cohere and Mistral among the options. The docs describe the admin flow: in ESSCM, open Integrations › Configure Scanner, then Models; under Your own models, select Add model; choose the provider and whether it is a frontier vendor account or a self-hosted endpoint; choose which API it speaks (OpenAI-compatible, Anthropic Messages or Google Gemini); and enter the model name, endpoint where needed, and API key. The key is kept in Safeguard's credential vault, separate from the model settings, fetched only when a call is made, and never logged. Route jobs to this model sends work from Safeguard's AI features, such as search and chat, to that model.
Two details from the docs matter for a data protection review:
- Safeguard's servers make the call. A self-hosted endpoint must be reachable from Safeguard. If your model endpoint lives on an internal network with no route from outside, bring your own model on SaaS will not reach it; that is a case for on-prem deployment.
- Your provider's terms govern retention. When the call goes to your own provider account, your agreement with that provider decides what it keeps.
Separately, Safeguard states that customer source code, SBOMs and telemetry are never used to train shared models, and that per-tenant fine-tunes are opt-in and stay inside the tenant boundary. The AI models docs also say inference request bodies are not retained beyond 24 hours by default, with a configurable window for Enterprise.
The modes combine: access mode decides where scans happen, and AI mode decides what the AI features see when you use them.
When do you need private VPC, on-prem or air-gapped instead?
The local runner keeps source code in place, but SBOMs and findings still go to the platform. If those results or your audit logs cannot sit in a shared SaaS tenant, you need a different deployment, not a different access mode. All of these are GA.
- SaaS: multi-tenant, with US, EU and Gov regions. Enterprise customers get tenant-level data isolation; a shared tenant is only used for consumer single-plan users.
- Private VPC or dedicated tenancy: single-tenant isolation for Enterprise, not tied to one cloud provider.
- On-prem: the full platform in your own datacenter. Safeguard's models can run as quantized builds on your GPUs; Zero needs no model weights at all.
- Air-gapped: the complete offline stack, including the models, with signed offline snapshot delivery and no outbound dependency.
The air-gapped docs describe how updates reach an isolated site. A signed snapshot bundle ships from Safeguard on a cadence you choose, from hourly down to quarterly. A receiver service in a DMZ verifies the signatures and pushes deltas to the control plane, and no component inside the perimeter calls outbound. Each bundle carries vulnerability feed deltas (the docs list NVD, GitHub Advisory, OSV, Safeguard Research, CISA KEV and daily EPSS), Gold artifact deltas, model deltas, policy template updates and platform binaries. Delivery options include a one-way diode, signed removable media, a scheduled sync over a short outbound window on a separate DMZ, and a pull replica. The CLI and runner are both available inside the perimeter.
A rule of thumb that works for most buyers:
- If only the source code is the problem, use the local runner on SaaS.
- If the results and metadata must also stay in a specific jurisdiction you control, use private VPC or on-prem.
- If nothing may leave or enter except through a controlled one-way process, use air-gapped, and plan for the snapshot cadence as an operating cost.
Decision table: data class versus access mode
A starting point; your own classification scheme and legal advice decide the final answer.
| Data class | Example | Repository connection | CLI scan (local results only) | Local runner on SaaS | Private VPC or on-prem | Air-gapped |
|---|---|---|---|---|---|---|
| Public open source | Your public libraries | Fits (Public tab, no token) | Fits | Fits | Not needed | Not needed |
| Internal, low sensitivity | Internal tools, no personal data | Fits, read-only fine-grained token | Fits | Fits | Not needed | Not needed |
| Confidential, personal data present | Services with customer data in fixtures or commit metadata | Possible with an Article 28 contract and scoped token; transient clone on Safeguard's side | Fits | Preferred: source stays put, results only | Consider if results also need residency | Not usually needed |
| Regulated financial, critical or important function | Core banking, trading, payments code | Weigh DORA Article 30(2)(b) location terms carefully | Fits for local checks | Preferred on SaaS if result data may leave | Preferred if result data must stay in your jurisdiction | Where policy forbids any egress |
| Self-hosted SCM with no public address | Internal GitLab or GitHub Enterprise Server | Does not work (server must be internet reachable) | Fits | Fits (outbound HTTPS only) | Fits | Fits |
| Classified, export-controlled or sovereign | Defense, ITAR scope | No | Only on approved machines | Usually no | Possibly, depending on policy | Fits |
| Unpushed working copy | Code on a developer laptop | Not applicable | Fits | Fits, and the assistant can work on it with your approval | Fits | Fits |
Requirement versus what Safeguard does versus what you still own
| Requirement | What Safeguard does | What you still own |
|---|---|---|
| GDPR Art. 28(1) sufficient guarantees | Documents what each integration reads and stores; source not stored | Choosing the vendor, signing the data processing agreement, reviewing sub-processors |
| GDPR Art. 32(1)(a) and (b) encryption and confidentiality | Tokens encrypted at rest with a per-workspace key; outbound HTTPS from the runner | Your endpoint, CI and SCM security; classifying what is in your repositories |
| GDPR Art. 44 transfers | SaaS regions, private VPC, on-prem and air-gapped options; local runner keeps source in place | The transfer assessment and legal basis for any personal data in SBOMs or findings |
| DORA Art. 28(4) due diligence and Art. 28(8) exit | Token rotation and disconnect flows; results exportable from the platform | The register of information, the risk assessment, the tested exit plan |
| DORA Art. 30(2)(b) location of processing | Deployment choice decides where results live; runner decides where source is scanned | Negotiating the contract terms and notice of location changes |
| NIST SP 800-53 AC-6 least privilege | Read-only scopes documented per SCM; CI keys lockable to one project | Creating narrow tokens, using service accounts, reviewing access regularly |
| SSDF PO.5.1 restrict connections | Runner is outbound only; no inbound listener; fixed interval polling option | Egress rules, proxy configuration, network segmentation |
| SSDF PO.5.2 harden development endpoints | Static binary, checksum-verified installer, OS credential store option | Endpoint hardening, MFA, which machines may run the runner |
What Safeguard does not do
Honest limits, so you can plan around them:
- The local runner still sends results. The runner keeps source code on your machine, but it uploads the SBOM and findings for each job. An SBOM reveals your component list and versions. If those results cannot leave your environment either, you need private VPC, on-prem or air-gapped deployment, not just the runner.
- Safeguard does not give legal advice on residency or transfers. Whether a given setup satisfies GDPR Article 44, DORA Article 30 or a national rule is your legal team's call. Safeguard can describe what each mode does with data; it cannot tell you whether that is lawful for your data.
- Repository connection scope depends on the SCM's permission model. Safeguard cannot make a token narrower than the SCM allows. A classic GitHub token with the
reposcope reaches every private repository the account can access, with write, because GitHub offers no read-only classic scope for private repositories. Use fine-grained or group tokens where you can. The dialogs also take tokens only (no GitHub App or OAuth installs yet), so plan for token ownership and rotation. - Some SCM deployments are not supported. Bitbucket Data Center and Azure DevOps Server cannot be connected today, and self-hosted GitHub Enterprise Server or GitLab must be reachable from the internet. For these, use the CLI with
--localin CI, or the runner. - Air-gapped is only as current as your snapshots. Vulnerability data inside an air-gapped deployment arrives through signed offline snapshots on the cadence you set. A quarterly cadence means quarter-old advisory data between drops. That is an operating decision with a security cost.
- CI build failure covers dependency vulnerabilities and policy gates, not SAST yet.
--fail-oncovers dependency vulnerabilities, and--fail-on-gatecovers policy gates. SAST (early access) findings appear in Safeguard but do not fail the build through--fail-ontoday. - Fix pull requests need write access. Autonomous remediation (GA, ships off) opens pull requests through a repository connection with write permissions. Read-only connections and local scans do not get automatic pull requests. With the runner, the assistant can edit a local working copy with your approval, and nothing is pushed unless you push it.
Common mistakes
- Using a classic token "because it is easier". It is broader than needed and grants write on every private repository the account can see. A fine-grained token limited to selected repositories with Contents read-only is all scanning needs.
- Granting write access on day one. Start read-only. Add write scopes when you actually turn on fix pull requests or the quality gate commit status, and remember autonomous remediation ships with every category on Manual.
- Tying the token to a person who might leave. Use a service account or a group access token, and record who owns the rotation.
- Assuming the runner means "nothing leaves". Results leave. Classify SBOMs and findings, and include them in your records of processing.
- Letting CI float on the latest CLI. Pin
SAFEGUARD_VERSIONso a new release does not change a build without review. - Treating
safeguard scanexit code 0 as a pass. It means the scan ran, whatever it found. Gate in the platform or check the JSON output. - Turning on bring your own model for an internal endpoint on SaaS. Safeguard's servers make the call, so the endpoint has to be reachable from Safeguard. If it is not, the deployment model needs to change.
FAQ
Does Safeguard store my source code when I connect a repository?
No. Per Safeguard's docs for GitHub, GitLab, Bitbucket and Azure DevOps, the scanner makes a shallow clone into a temporary folder and deletes it when the scan ends. Safeguard stores the connection settings, the selected repositories, the SBOM and findings of each scan, and the token, encrypted at rest with a per-workspace key.
What permissions does Safeguard need on GitHub?
For scanning, a fine-grained personal access token with Metadata read-only and Contents read-only, limited to the repositories you select. Write permissions for contents, pull requests and commit statuses are optional and only needed for fix pull requests and the quality gate status.
Does the Safeguard CLI upload my code?
No. A plain safeguard scan writes results to a local folder. When you scan from the interactive terminal while signed in, the runner uploads the SBOM and findings, never the source. Options such as --resolve-transitive contact an external service with package identifiers, so leave them off if your policy requires it.
What is the difference between the Safeguard CLI and the local runner?
The runner is part of the CLI, not a separate product. The CLI scans on demand. The runner is the CLI signed in and polling Safeguard for jobs assigned to that machine, running them locally and uploading only the results.
Does the local runner need inbound firewall rules?
No. Per the docs, all traffic is outbound HTTPS that the runner opens, and nothing connects to it. If your network cuts long-held connections, --poll-wait 0 switches to polling at a fixed interval.
Can I scan a self-hosted GitLab or GitHub Enterprise Server that is not on the internet?
Not with a repository connection, because the server must be reachable over a public address. Use safeguard ci scan --local in your pipeline or run the local runner inside your network instead.
Can Safeguard run with no AI at all?
Yes. Zero AI mode (GA) runs the platform deterministically with no LLM in the loop, and the scanners still work. You lose AI-driven features such as model-written fixes and chat.
Is the local runner enough for DORA?
It helps with the part about where source code is processed, but DORA obligations sit with the financial entity: the register of information, the risk assessment, contract terms on data location and a tested exit strategy. The runner changes what data the provider processes; it does not complete those obligations for you.
When should I choose air-gapped over the local runner?
When results, logs and metadata also may not leave your environment, or when policy forbids any outbound connection. Air-gapped deployment runs the whole platform, including models, inside your perimeter, with signed offline snapshots for updates.
Try it on one repository
The fastest way to settle the access mode question is to run the local runner against one repository and look at exactly what appears in the platform. Download the CLI from safeguard.sh/download and keep the documentation open for the CLI, runner and CI pages quoted above. For more depth on each route, see our earlier posts on keeping source on your machine with the local runner, whether the CLI uploads your source code, running the CLI in CI or connecting the repository and choosing between SaaS, private VPC, on-prem and air-gapped by data class. This batch also covers every capability with its maturity label and autonomous remediation and its off-by-default settings.
Whichever access mode you choose, it decides how Safeguard finds vulnerable dependencies, not what you do about them once found. Fix pull requests need a repository connection with write access, while the Gold options below work the same whether you scan through a connection, the CLI or the runner.
Fix it without waiting for upstream
Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.
1. Autonomous remediation: pull requests, not tickets
When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.
2. Gold Open Source: the safe version in seconds, free
gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.
3. Gold Registry: start from components that are already fixed
registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.
When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.
| Your situation | What to use |
|---|---|
| A fixed version exists | Autonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version |
| You need to know today whether you are affected | Gold Open Source lookup and "Am I affected?" checker, free and without login |
| You want vulnerable versions to stop shipping | The Gold scan GitHub Action in CI, plus Safeguard policies and gates |
| Upstream has no fix yet, or will not ship one | A custom Gold request; fork and patch (early access) |
| You want to start clean on new projects | Pull hardened components and images from Gold Registry |
One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.
See how Safeguard would help
The first demo is the local runner itself. It shows setting up the runner on your own machine, approving it with its device code, and then scanning from the terminal. This is the flow from Part A of the step by step section, and it is the one to show a data protection reviewer who wants to see that the scan happens on your hardware.
Click through it at your own pace, or open it full screen.
The second demo is a real CLI session: install, open the interactive terminal with safeguard, and ask it to fix the lodash CVE in a repository. The assistant reads the finding and advisory, asks before each command, edits package.json to lodash 4.17.21, runs npm install and npm test with approval, prints a summary and pushes nothing, then shows /permissions, /model and /scan .. It illustrates the "unpushed working copy" row of the decision table: the change happens locally, under your approval, and nothing reaches your repository until you push it.
Click through it at your own pace, or open it full screen.
Quick check
With the local runner, what does Safeguard receive from a scan job?
The SBOM and findings for that job, plus its status. Per Safeguard's runner docs, the job runs on your machine over outbound HTTPS that the runner opens, and the source code stays on the machine.
Your GitLab server has no public address. Which access modes still work?
The CLI and the local runner. A repository connection needs the self-managed GitLab server to be reachable from the internet, but safeguard ci scan --local in your pipeline, or the runner inside your network, scans the checkout locally and sends only results.
Sources
- Safeguard docs: Local Runner
- Safeguard docs: Safeguard CLI
- Safeguard docs: CLI installation
- Safeguard docs: CLI usage guide
- Safeguard docs: CLI configuration
- Safeguard docs: CI/CD integration
- Safeguard docs: GitHub Actions
- Safeguard docs: GitHub integration
- Safeguard docs: GitLab integration
- Safeguard docs: Bitbucket integration
- Safeguard docs: Azure DevOps integration
- Safeguard docs: AI models
- Safeguard docs: Bring your own model
- Safeguard docs: Air-gapped deployment
- Regulation (EU) 2016/679, General Data Protection Regulation (Articles 28, 32, 44)
- Regulation (EU) 2022/2554, Digital Operational Resilience Act (Articles 28 to 30, 64)
- EDPB Guidelines 07/2020 on the concepts of controller and processor in the GDPR
- NIST SP 800-53 Rev. 5, Security and Privacy Controls (AC-6)
- NIST SP 800-53 Rev. 5 control catalog in OSCAL (usnistgov/oscal-content)
- NIST SP 800-218, Secure Software Development Framework Version 1.1
- NIST SP 800-218 full text (PDF)
- GitHub Docs: Managing your personal access tokens
Last reviewed: 24 October 2026. Product capabilities change; check docs.safeguard.sh for the current state.