Safeguard
Product•

Safeguard Workflows: triggers, approvals and the template library

How to turn security runbooks into versioned, reviewable Safeguard workflows: triggers, steps, conditions, approvals, runners and the template library.

Safeguard Security Team
43 min read

Yes. In Safeguard a response runbook becomes a workflow: a YAML definition with a trigger (an event, a schedule or a manual run), ordered steps, step-level conditions and a concurrency limit. Workflows live in a Git repository or the Safeguard UI, so every change can go through code review, and every external side effect a run causes leaves a signed audit record.

This post is for the security platform owner or DevSecOps lead who is asked to make the program run without a person pressing buttons every morning, and for the head of AppSec who has to sign off on what that automation is allowed to do. It covers how a workflow is built according to Safeguard's documentation, the triggers and steps that exist, four runbooks written as workflows (fix criticals, respond to a blocked gate, weekly SBOM freshness and vendor risk), where the human approvals sit, how the template library is installed and upgraded, and a staged rollout that starts in notify-only mode.

Key takeaways

  • A workflow is "when this happens, do these things." A trigger, steps in order or in parallel, a shared context for inputs and outputs, if conditions per step and a concurrency limit, written in YAML.
  • Triggers cover the events a program reacts to: image and repository pushes, SBOM uploads, new vulnerabilities affecting your components, guardrail BLOCK or WARN decisions, vendor SBOM updates, cron schedules in UTC and manual runs.
  • Steps are versioned building blocks referenced as safeguard/step-name@v2, so a step upgrade is a deliberate, reviewed edit.
  • Approvals sit in several places. Workflow changes can require code review, remediation by Griffin, Safeguard's security model, can require approval before a pull request is created, policy exceptions go to approvers with an expiry, and breakglass needs two people.
  • Every run is observable: a step timeline, structured logs, OpenTelemetry spans and signed audit records for every external side effect.
  • The template library is the fast start. Complete YAML templates install from Workflows, Library in the web app, and upgrades keep your edits through a three-way merge.
  • Remediation starts switched off. Every Autonomous Remediation category defaults to Manual until the master toggle is on, so a workflow that calls Griffin does what your settings allow and no more.

Why do security runbooks stop working as documents?

Every security team has runbooks: "when a KEV-listed critical shows up in production, check reachability and open the upgrade," or "every Monday, chase the owners of stale production SBOMs."

Written down, each is clear. Run by hand, each decays the same way: it depends on who is on shift, it drifts from the tooling ("check reachability" without saying which branch or threshold), it leaves no trail an auditor can follow, and it does not scale when one widely used library publishes a fix that touches dozens of repositories.

NIST's incident response guidance, SP 800-61 Revision 3 (April 2025), is written as a CSF 2.0 Community Profile, which places incident response inside cybersecurity risk management rather than beside it. The practical implication for a platform owner is that the routine parts of response (detect, route, contain, fix, report) should be consistent and repeatable. NIST's Secure Software Development Framework, SP 800-218, asks for the same on the development side: practice PO.3 (Implement Supporting Toolchains) says to use automation to reduce human effort and improve the accuracy and reproducibility of security practices, and RV.1 and RV.2 cover identifying, assessing, prioritizing and remediating vulnerabilities on an ongoing basis. A runbook in a wiki satisfies neither in a way you can show.

The answer is not "automate everything." It is to encode what should be identical every time, keep human judgment where it matters, and make both visible.

What is a Safeguard workflow?

Safeguard's documentation defines a workflow as a sequence of Safeguard steps triggered by an event. The docs' own one-line example is close to a runbook: "when a new image appears in prod-registry, generate an SBOM, evaluate the production policy, and open a PR if Griffin can auto-fix any findings."

A workflow has five parts:

PartWhat it doesWhere it shows up in YAML
TriggerWhat starts the workflow: an event, a schedule or a manual runspec.on
StepsThe actions, in order or in parallelspec.steps
Inputs and outputsEach step reads from the workflow context and can write to itwith: and steps.<id>.outputs
ConditionsStep-level if expressions that decide whether a step runsif: on a step
ConcurrencyA limit on how many instances of the workflow run at the same timespec.concurrency

Workflows are written in YAML, the human-readable data format defined by the YAML 1.2.2 specification. They live in a Git repository or inside the Safeguard UI, and they run on Safeguard's managed cloud runner or on a self-hosted runner you operate.

Every workflow starts with the same header:

apiVersion: safeguard.sh/workflows/v1
kind: Workflow
metadata:
  name: weekly-sbom-freshness
spec:
  on:
    # one or more triggers
  steps:
    # ordered steps

The workflow context: how steps talk to each other

Each step has an id. Later steps read earlier outputs through expressions in ${{ }} form. The documentation's examples use three kinds of reference:

  • ${{ trigger.<field> }} reads data from the event that started the run, such as trigger.repository, trigger.ref, trigger.vulnerability_id, trigger.image or trigger.severity.
  • ${{ steps.<id>.outputs.<field> }} reads what an earlier step wrote, such as steps.scan.outputs.sbom or steps.reachability.outputs.reachable.
  • ${{ workflow.<field> }} reads properties of the workflow run itself, such as workflow.repository, which the docs use to build a concurrency group name.

There is no glue code: you name the step and pass it what it needs.

Conditions: the if on each step

A step with if: runs only when its expression is true. The docs' examples use conditions in three distinct ways, and each one encodes a piece of runbook judgment:

  1. Only continue if there is something to act on. if: ${{ steps.scan.outputs.found == true }} skips reachability analysis when the scan did not find the vulnerability.
  2. Only act if the evidence says it matters. if: ${{ steps.reachability.outputs.reachable == true }} sends only reachable findings to remediation.
  3. Only notify if the action happened. if: ${{ steps.open-pr.outputs.pr_url != '' }} posts to chat only when a pull request URL exists.

The third pattern keeps a chat channel trusted. A notification that fires whether or not anything happened trains people to ignore it.

Concurrency: one run per repository, not twenty

A vulnerability that affects a popular library can produce many trigger events close together. Without a limit, a workflow could start several runs against the same repository and open competing branches. The docs show the fix:

concurrency:
  group: "auto-fix-${{ workflow.repository }}"
  cancelInProgress: true

Runs that share a group value are limited together. With cancelInProgress: true, a new run in the same group cancels the one already in progress, so the newest data wins. The idea matches CI concurrency groups: GitHub's Actions documentation describes a group in which only a single job or workflow runs at a time, with cancel-in-progress to cancel the running one. Group by repository when runs would collide on the same branch. Group by vulnerability when you want one remediation run per CVE across the estate.

Which triggers start a workflow?

The Workflows documentation lists these triggers. Each maps to a question a security program asks repeatedly.

TriggerFires onRunbook question it answers
on.image.pushedA new image or tag in a connected registry"What is in the image we just built?"
on.repo.pushedA new commit or tag on a connected Git repository"Did this change introduce risk?"
on.sbom.receivedAn SBOM uploaded to Portal or via the API"Does this SBOM meet our policy?"
on.vulnerability.publishedA new vulnerability that affects one of your components"Which of our services does this hit, and can we fix it?"
on.policy.violationA guardrail records a BLOCK or WARN"Who needs to know that a gate stopped something?"
on.vendor.sbom_updatedA third-party risk vendor sends a new SBOM"Has our supplier's risk changed?"
on.scheduleA cron expression, evaluated in UTC"What should we check every week regardless of events?"
on.manualA run started from the UI, CLI or API"Run this now, on demand."

Triggers can be combined. A workflow can declare several on.* handlers, which is useful when the same steps should run on a schedule and on demand, or on both a push and a newly published vulnerability.

Filters narrow the trigger

Event triggers take filters. The documented auto-fix example narrows vulnerability.published with four of them:

on:
  vulnerability.published:
    filters:
      severity: ["critical", "high"]
      kev: true
      repositories: ["org/api", "org/webapp"]
      branch: main

Read as policy, that says: only critical and high vulnerabilities, only those on CISA's Known Exploited Vulnerabilities catalog, only in two named repositories, only on the main branch. CISA describes the KEV catalog as the authoritative source of vulnerabilities that have been exploited in the wild, and recommends that organizations use it as an input to their vulnerability management prioritization framework. A filter on kev: true turns that recommendation into a rule the workflow applies the same way every time.

The docs' gate example filters policy.violation by policy name and decision (shown here with a release policy name):

on:
  policy.violation:
    filters:
      policy: prod-release-policy
      decision: BLOCK

Filtering by decision: BLOCK keeps warnings out of the paging path. Warnings can go to a separate, quieter workflow.

Cron schedules: read the five fields carefully

on.schedule takes a standard five-field cron expression, evaluated in UTC. The POSIX crontab specification defines the fields in this order: minute (0 to 59), hour (0 to 23), day of the month (1 to 31), month of the year (1 to 12) and day of the week (0 to 6, with 0 as Sunday).

The documented weekly audit uses 0 9 * * 1: minute 0, hour 9, any day of the month, any month, Monday. That is 09:00 UTC every Monday: 14:30 in India Standard Time and 10:00 in Frankfurt during winter time. 0 2 * * * would run at 02:00 UTC daily, and 0 6 1 * * at 06:00 UTC on the first of each month.

Write the UTC value and add a comment with the local time so reviewers can check it.

What steps can a workflow run?

Steps come from a built-in library and are referenced as versioned uses: values, for example safeguard/scan-repository@v2. The Workflows documentation groups them like this:

CategorySteps
Scanningscan-repository, scan-image, scan-sbom, scan-model
Analysisreachability-analyze, license-analyze, eagle-classify
Remediationgriffin-remediate, open-pull-request, pin-dependency
Policyevaluate-policy, apply-guardrail
Notificationsslack-notify, teams-notify, email-owners, pagerduty-trigger
Ticketsjira-create, jira-comment, linear-create
Exportexport-sbom, export-attestation, s3-upload
Integrationgithub-check, gitlab-pipeline-emit, bitbucket-comment

The docs point to a step reference for the full list with inputs and outputs. Treat that reference as the contract. The examples in this post use only the inputs and outputs the documentation shows; when you build something new, check each step's inputs and outputs there before you depend on them.

Two things about the step library are worth noting for a platform owner.

First, the major version is in the reference. griffin-remediate@v3 and scan-repository@v2 are pinned to a major version. A breaking change to a step arrives as a new major version, and your workflow does not move to it until someone edits the line and that edit passes review.

Second, most runbooks fit inside the library: scanning and analysis steps detect, conditions and evaluate-policy decide, remediation and ticket steps act, notification steps tell someone, and the run's audit records keep the trail.

Runbook 1: fix critical, exploited vulnerabilities on main

This is the documentation's first example, and the best one to read line by line because it shows every feature at once.

This is a Safeguard Workflows definition. It runs in Safeguard's runner, not in GitHub Actions.

apiVersion: safeguard.sh/workflows/v1
kind: Workflow
metadata:
  name: auto-fix-critical-on-main
spec:
  on:
    vulnerability.published:
      filters:
        severity: ["critical", "high"]
        kev: true
        repositories: ["org/api", "org/webapp"]
        branch: main
  concurrency:
    group: "auto-fix-${{ workflow.repository }}"
    cancelInProgress: true
  steps:
    - id: scan
      uses: safeguard/scan-repository@v2
      with:
        repository: ${{ trigger.repository }}
        ref: ${{ trigger.ref }}
    - id: reachability
      uses: safeguard/reachability-analyze@v1
      with:
        sbom: ${{ steps.scan.outputs.sbom }}
        vulnerability: ${{ trigger.vulnerability_id }}
      if: ${{ steps.scan.outputs.found == true }}
    - id: remediate
      uses: safeguard/griffin-remediate@v3
      with:
        vulnerability: ${{ trigger.vulnerability_id }}
        repository: ${{ trigger.repository }}
        strategy: conservative
      if: ${{ steps.reachability.outputs.reachable == true }}
    - id: open-pr
      uses: safeguard/open-pull-request@v1
      with:
        repository: ${{ trigger.repository }}
        branch: safeguard/auto-fix/${{ trigger.vulnerability_id }}
        title: "Auto-fix ${{ trigger.vulnerability_id }}"
        body-template: remediation-summary
      if: ${{ steps.remediate.outputs.fixed == true }}
    - id: notify
      uses: safeguard/slack-notify@v1
      with:
        channel: "#security-ops"
        template: remediation-posted
      if: ${{ steps.open-pr.outputs.pr_url != '' }}

Here is what each step encodes, in runbook language.

StepRunbook line it replacesThe judgment it keeps
Trigger with filters"When a KEV-listed critical or high lands on main in api or webapp"Scope stays narrow until you choose to widen it
scan"Rescan the repository at the affected ref"Works from current data, not the last nightly scan
reachability"Check whether our code actually calls the vulnerable path"Runs only if the scan confirms the vulnerability is present
remediate"Prepare the upgrade"Runs only for reachable findings, with a conservative strategy
open-pr"Open the pull request on a predictable branch"Runs only if Griffin reports the fix succeeded
notify"Tell the security channel"Runs only if a pull request exists

Three details matter.

The branch name is deterministic. A second run for the same CVE lands on the same branch, and a repository rule can require security review for any branch under safeguard/.

The workflow opens a pull request; it does not merge one. Merging stays with your existing review process. Safeguard's AI Remediate documentation is direct about this in its best practices: enable tests, start with safe fixes, review major changes and do not auto-merge breaking changes.

strategy: conservative is a choice, not a default to forget. It is the value the documented example passes to the step. The Autonomous Remediation settings, covered in the post linked below, offer the strategies Safest, Balanced, Aggressive and Smart. For a workflow that runs without a person starting it, pick the most cautious option your settings offer and widen it per repository once the team trusts the results.

What the Griffin step actually does

The griffin-remediate step calls Griffin, Safeguard's security model, through the same AI Remediate capability you can use by hand. The documentation describes the sequence as analysis of the vulnerability and your codebase, choosing the safest upgrade path, an impact assessment for breaking changes and compatibility, pull request creation and validation by running automated tests.

For dependency upgrades, the docs say Griffin can upgrade vulnerable packages to fixed versions, handle transitive dependency conflicts, update lock files and maintain compatibility with existing code. Supported package managers listed in the docs include npm, yarn and pnpm for JavaScript, pip, poetry and pipenv for Python, Maven and Gradle for Java, Go modules, Cargo, Bundler, NuGet and Composer.

Each change is classified for breaking-change risk:

LevelMeaning in the docsSensible workflow handling
SafeNo breaking changes expectedLet the workflow open the pull request
MinorMinor API changes, low riskOpen the pull request and request review from the owning team
MajorSignificant changes, review recommendedOpen the pull request as a draft or route to a ticket
CriticalHigh risk of breaking, manual review requiredDo not open automatically; create a ticket for a person

The pull request carries the CVE reference, a description of the vulnerability, a change summary, breaking-change warnings, test results when configured and advisory links: what a reviewer needs to decide.

The settings that sit underneath the step

A workflow cannot do more than your settings allow. AI Remediate is configured under Settings, AI Remediate:

SettingWhat it controls
Auto-Create PRsWhether pull requests are created automatically for safe fixes
Require ApprovalWhether a person must approve before a pull request is created
Test IntegrationWhether tests run before a pull request is created
Breaking Change PolicyHow breaking changes are handled
Branch NamingThe branch naming convention for remediation pull requests

Above those sits the Autonomous Remediation master toggle. Safeguard ships remediation switched off: every category starts at Manual, and strategy selections are saved but not applied until the toggle is on. Write the workflow, run it with Require Approval on, read what it proposes for a few weeks, and only then decide which categories may run without approval.

For a deeper look at the categories and strategies, see Autonomous remediation in Safeguard: eight categories, four strategies, off by default.

Runbook 2: respond when a release gate blocks

The second runbook is about what happens after a policy stops something. The gate decision itself belongs to policies and gates; the workflow handles the response.

How the gate decides

Gates are evaluated by the platform on the scans it runs for your connected repositories. Each linked policy has one Action:

ActionWhen the policy fails
BlockThe gate fails
WarnThe gate still passes, with a warning that names the policy
NotifyThe gate still passes, and Safeguard sends a notification to the workspace's configured channels

The documentation spells out how the gate's own outcome is worked out from its policies, in order: no linked policies means Not evaluated; any failed Block policy means Failed; otherwise any policy that could not be evaluated means Error; otherwise any policy still awaiting evaluation means Not evaluated; otherwise any failed Warn policy means Warning; otherwise Passed. An Error is never counted as a pass, and a gate that has never been evaluated shows Not evaluated, never Passed. Those two rules are what you want from a gate an auditor will look at: missing data does not quietly become a green light.

Notify fires when a policy starts failing or finds new matches, not on every evaluation of the same failure.

To fail a CI job on a gate, the documented command is:

safeguard ci scan --wait --fail-on-gate "production release"

With --wait, the CLI waits for the scan to finish and for the gate's policies to be evaluated on the new data. It exits 0 when the gate is Passed or Warning, and non-zero when the gate is Failed, Error or Not evaluated, or when its policies were not evaluated before the timeout, printing the reason. --fail-on <severity> can be combined with it. The plain safeguard scan reports findings without failing the build, and the CLI has no separate gate command, so pipelines that must stop use ci scan with --fail-on-gate.

Policy outcomes are turned on per workspace by Safeguard. If the Outcome column is missing from your Gates and Policies tables, ask your Safeguard contact to turn it on.

The response workflow

When a guardrail records a BLOCK or WARN, on.policy.violation fires. The documentation's example opens a Jira ticket and pages on-call only for critical blocks. Adapted to a release policy, it reads:

This is a Safeguard Workflows definition. It runs in Safeguard's runner, not in GitHub Actions.

apiVersion: safeguard.sh/workflows/v1
kind: Workflow
metadata:
  name: release-gate-response
spec:
  on:
    policy.violation:
      filters:
        policy: prod-release-policy
        decision: BLOCK
  steps:
    - id: open-ticket
      uses: safeguard/jira-create@v2
      with:
        project: SEC
        summary: "Blocked production release: ${{ trigger.image }}"
        severity: ${{ trigger.severity }}
    - id: page-oncall
      uses: safeguard/pagerduty-trigger@v1
      with:
        service: prod-release-failures
      if: ${{ trigger.severity == 'critical' }}

Every block gets a ticket and only critical blocks wake someone, the same split most incident programs make between a queue and a page, applied identically at 03:00 and at 15:00. The ticket is created by the workflow, so the developer whose release was blocked does not need to know which project or fields the security team uses.

The jira-create step relies on the Jira integration, which connects Safeguard to one Jira Cloud project, so set that up first.

A sibling workflow can send decision: WARN to chat with slack-notify or teams-notify, keeping warnings visible without tickets.

Exceptions are approvals, with an expiry

A blocked release sometimes has a legitimate reason to proceed. The Policies and Gates documentation describes the flow: a developer requests an exception, selects the policy and finding, gives a business justification and sets an expiration date; approvers are notified, review and decide; and the decision is recorded in the audit trail.

The Guardrails and Enforcement documentation adds two rules for blocking guardrails. Exceptions are time-boxed per asset and expire automatically. Emergency breakglass exceptions require two-person approval and trigger alerts in the security channel. One person cannot quietly open a permanent hole, and everyone can see when the door was opened and for how long.

For the difference between policies, gates and guardrails, and where each runs, see Policies vs gates vs guardrails in Safeguard.

Runbook 3: the weekly SBOM freshness audit

An SBOM is only as useful as it is current. CISA's SBOM program describes the SBOM as a key building block of software security and supply chain risk management, and the value depends on the inventory reflecting what is actually running. A production service whose SBOM was generated months ago tells you what it contained then, not now.

The documented workflow is short:

This is a Safeguard Workflows definition. It runs in Safeguard's runner, not in GitHub Actions.

apiVersion: safeguard.sh/workflows/v1
kind: Workflow
metadata:
  name: weekly-sbom-freshness
spec:
  on:
    schedule:
      cron: "0 9 * * 1"   # Mondays 09:00 UTC (14:30 IST)
  steps:
    - id: audit
      uses: safeguard/sbom-freshness-audit@v1
      with:
        max-age-days: 30
        environments: ["production"]
    - id: email-owners
      uses: safeguard/email-owners@v1
      with:
        assets: ${{ steps.audit.outputs.stale_assets }}
        template: sbom-stale-reminder
      if: ${{ steps.audit.outputs.stale_count > 0 }}

Every Monday at 09:00 UTC, the audit checks production assets for SBOMs older than 30 days and emails the owners of the stale ones. The if means no email goes out on a week when everything is current, which matters: the owners who get this email should be the ones who need to act.

Two adjustments are common. Tune max-age-days per environment or asset class, since a service that ships daily should never have a month-old SBOM while a quarterly vendor appliance always will. And pair the audit with regeneration on push: an on.repo.pushed or on.image.pushed workflow that calls scan-repository or scan-image and then export-sbom removes most of the reasons the audit would find anything.

The template library ships the same runbook as weekly-sbom-freshness-audit, and adds vendor-sbom-freshness-sla for suppliers (covered next).

Runbook 4: vendor risk, driven by the vendor's SBOM

Third-party risk is usually run on an annual questionnaire cycle. SBOMs let it run on events instead: when a vendor sends a new SBOM, re-evaluate them. Safeguard's Third Party Risk Manager is where vendor SBOMs arrive, and on.vendor.sbom_updated fires when a vendor sends a new one.

The Guardrails and Enforcement documentation lists the procurement guardrails that TPRM extends to vendor intake:

  • Require a signed SBOM from the vendor before contract signing.
  • Block vendors whose SBOMs contain components with active critical CVEs.
  • Require attestation of NIST SSDF practices for vendors handling regulated data.

The template library's vendor risk group turns these into running automation. A practical vendor runbook chains its templates:

EventTemplateSuggested human decision
Vendor uploads a new SBOMvendor-sbom-intake evaluates policy and scores riskProcurement or security reviews a changed risk score
A vendor component appears on KEVvendor-kev-watchlist flags the vendorVendor manager asks the supplier for their remediation plan
A vendor's license set changesvendor-license-diff alertsLegal reviews whether the new license is acceptable
A vendor's SBOM goes stalevendor-sbom-expiry-reminder emails the vendorEscalation only if reminders are ignored
The contract endsvendor-offboarding revokes access, purges data, archives historyThe vendor owner confirms the contract has ended before running it

For financial entities in the EU, the template dora-register-of-information keeps the DORA Register of Information current from TPRM data. The European Banking Authority's DORA pages describe the registers of information that financial entities must maintain on their ICT third-party arrangements and report to their competent authorities. Keeping that register current from the same vendor data that drives risk decisions avoids a second spreadsheet that drifts from the first.

Where do the approvals sit?

The question in the title of this post was not only "can we automate it" but "with approvals, versioned and auditable." Approvals in Safeguard are not one switch. They sit at each point where a change leaves the security team's hands.

Approval pointWhat is approvedHow, per the docs
Workflow definitionThe automation itselfWorkflows are versioned in Git, and you can require code review before any change lands; the UI shows a diff between the running and proposed versions
Environment promotionWhich version runs whereDev, staging and prod can each pin to a different workflow version
Template upgradeLibrary changes merged into your copyThree-way merge keeps your customizations; conflicts are flagged in the UI for review before apply
RemediationWhether Griffin's fix becomes a pull requestAI Remediate's Require Approval setting; categories stay Manual until the master toggle is on
MergeWhether the fix shipsYour repository's existing review and branch protection rules
Policy exceptionA finding allowed past a gateRequest with justification and expiry, reviewed by approvers, recorded in the audit trail
BreakglassAn emergency override of a blocking guardrailTwo-person approval, with an alert in the security channel
Assistant on a runnerWhat the CLI assistant may do on a machine--permission-mode picks one of the separate modes (supervised by default); safeguard exec defaults to strict, denying anything the policy file has not pre-approved

Read top to bottom, that is separation of duties: the author of a workflow is not its only approver, a person or a setting a person chose decides whether a fix becomes a pull request, the repository decides whether it merges, and an exception has an owner, a reason and an end date.

NIST SP 800-53 Revision 5 describes configuration change control (control CM-3) as determining the types of changes that are configuration-controlled, reviewing proposed changes and approving or disapproving them with explicit consideration of security impact, documenting decisions, and retaining records. Workflows in Git with required review, plus signed run records, are a direct way to show that control operating on your security automation itself.

Environments make rollback simple: pin dev to a new version, then staging, then prod, and re-pin to the previous version if it misbehaves. The definition you roll back to is in Git history, so there is no doubt about what ran before.

How do you see what a workflow did?

Every workflow run produces four kinds of record, according to the Workflows documentation:

  • A step-by-step timeline in the Workflows tab.
  • Structured logs streamed to the UI and archived.
  • OpenTelemetry spans emitted to your configured OTLP endpoint. OTLP, the OpenTelemetry Protocol, specifies the encoding, transport and delivery of telemetry between sources, collectors and backends, so spans can flow into the observability stack you already run.
  • Audit records signed by Safeguard for every external side effect: a pull request opened, a ticket created, a notification sent.

Guardrail decisions have their own trail. The Guardrails and Enforcement documentation says every guardrail produces a signed audit record and auditors can replay any enforcement decision. Every decision is logged to the Safeguard audit stream, emitted as an OpenTelemetry span for SIEM ingestion and counted in the Enforcement dashboard, which shows allow, warn and block trends by policy, team and asset class.

The docs' tuning rule: a policy that fires BLOCK thousands of times a week probably needs auto-fix or refinement, and a workflow responding to it will be just as noisy.

Measure what workflows change (pull requests opened and merged, blocks by policy, open exceptions) during your own evaluation. The results depend on your codebase, policies and review habits, so treat any number as yours to establish.

Which runner should a workflow use?

Workflows run on runners. The documentation describes two:

  • Safeguard's cloud runner, the default, fully managed by Safeguard.
  • A self-hosted runner inside your VPC or cluster, useful for reaching private networks, air-gapped sites or regulated data.

A workflow chooses with runs-on: cloud (the default) or runs-on: self-hosted.

The local runner in the CLI

Safeguard also documents a local runner built into the CLI. It is not a separate product. When you open the interactive terminal and sign in, the machine starts polling the platform for work assigned to it. It runs each scan job locally and uploads only the resulting SBOM and findings, never your source code. All traffic is outbound HTTPS that the runner opens, and nothing connects to it.

Install and first run, from the documentation:

# macOS and Linux
curl -fsSL https://cli.safeguard.sh/install | bash

# Windows (PowerShell)
irm https://cli.safeguard.sh/install.ps1 | iex

# Open the interactive terminal, then type /login
safeguard

The first run downloads the scanner tools and vulnerability database. On servers, run it headless:

# Start without the terminal UI and serve work for this workspace
safeguard runner start --workspace ./path/to/repo

# Check what it is doing
safeguard runner status

# Drain in-flight work and stop
safeguard runner stop

runner start long-polls by default. On a network that forbids held connections, pass --poll-wait 0 to poll at a fixed interval set by SAFEGUARD_POLL_INTERVAL (default 10 seconds). --permission-mode picks one of the separate permission modes (supervised by default, edits, plan, guarded, strict or autonomous), which are not a ladder.

NeedRunner choice
Public or OAuth-connected repositories, no network constraintsCloud runner (default)
Private network, regulated data or an air-gapped siteSelf-hosted runner
Source code must not leave the machine; only outbound HTTPS allowedThe CLI's local runner
Developers want fixes on unpushed codeThe CLI's local runner with the assistant

What is in the template library?

The Workflow Library holds complete YAML templates you can install with one click, edit and promote to your organization. Install from Workflows, Library in the web app. Templates are edited there after installation; the CLI does not install, edit or enable workflows.

Here are the templates that match the runbooks above, grouped as the library groups them and described as the documentation describes them.

Auto-fix and remediation

TemplateWhat it does
auto-fix-critical-kev-in-prodTriggers on any new KEV-listed critical finding on production assets, runs reachability and opens a Griffin fix pull request
auto-fix-daily-backlogRuns nightly against the top N reachable findings and opens up to N pull requests
auto-fix-transitive-onlyRestricted to transitive-dependency upgrades only, the safer choice for stable teams
griffin-review-assistantGriffin comments on open security pull requests, explaining the change and any remaining risk
remediate-stale-dependencyOpens pull requests for dependencies unchanged for more than 365 days with any open CVE

auto-fix-daily-backlog is underrated: a nightly cap of N pull requests shrinks the backlog at a pace reviewers can keep up with.

Self-healing

TemplateWhat it does
self-heal-base-imagesWatches container base images and rebuilds when new CVEs land
self-heal-staged-rolloutCanary-based self-heal with automatic rollback on metric regression
self-heal-ai-model-depsSelf-heal for the AI-side dependency chain (transformers, torch, tokenizers)

For how self-healing containers work end to end, see Safeguard self-healing containers.

Scanning and discovery

TemplateWhat it does
weekly-sbom-freshness-auditAudits SBOM freshness across assets and emails owners of stale ones
shadow-asset-sweepFinds repositories, images and workloads missing ownership and opens tickets
vendor-sbom-freshness-slaReminds vendors whose SBOMs are approaching their SLA
deep-scan-on-pushRuns a full deep scan on every push to main
mono-repo-project-splitEmits per-service SBOMs from a monorepo push

Put shadow-asset-sweep in the first wave: every other workflow routes work to owners.

Compliance evidence

TemplateWhat it does
eo-14028-sbom-validationRuns SBOM minimum-elements validation and blocks non-compliant releases
cra-readiness-checkEvaluates each product against the EU Cyber Resilience Act's essential requirements and opens gaps as tickets
ssdf-evidence-exportExports NIST SSDF evidence as OSCAL for auditors
soc2-change-controlProduces SOC 2 change-control artifacts for every production push
iso-27001-control-rollupRolls ISO 27001 Annex A control coverage into a dashboard
dora-register-of-informationKeeps the DORA Register of Information current from TPRM data

These templates collect evidence; they do not make you compliant. A readiness check that opens gaps as tickets tracks the work and is not a conformity assessment, and SOC 2 change-control artifacts are inputs your auditor reviews.

Operations and observability

TemplateWhat it does
daily-digest-to-leadsA per-team email digest of open urgent findings and this week's remediations
slack-triage-botA triage channel bot that claims, escalates or suppresses findings through slash commands
pagerduty-p0-bridgePages on-call for P0 findings in production
jira-ticket-syncKeeps Jira and Safeguard in sync: create, update and transition
metric-export-otelExports Safeguard metrics to your OTLP endpoint

AI and ML dependencies

TemplateWhat it does
ai-bom-generate-on-deployGenerates an AI-BOM on every model push to the registry
model-weight-verifyVerifies model-weight signatures before deployment
training-data-license-checkValidates training data licenses against policy

Upgrading a template without losing your edits

Templates pin to an SDK version, so the library can change without changing what you installed. Each template has a version. When you upgrade, Safeguard pulls the new version and keeps your customizations by three-way merge; conflicts are flagged in the UI for review before they apply.

Three-way merge is the idea behind git merge-file, which incorporates all changes that lead from a base file to another file into the current one. Here the base is the template version you installed, the current file is your edited copy and the other is the new version. Where both changed the same lines, you get a conflict to resolve, not a silent overwrite.

So keep edits to the lines that genuinely differ for you (filters, channels, project keys, thresholds); fewer changed lines means fewer conflicts.

Asking for a template

If you need a template that is not in the library, the documentation says to request it by email at workflows@safeguard.sh. Safeguard maintains the library, and community templates are reviewed, signed and published under a community/ namespace once approved.

Workflow, guardrail, gate or setting: which tool for which job?

Picking the wrong automation feature is the most common design error.

You want toUseWhy
Stop a release that fails policyA gate with Block policies, failed in CI with safeguard ci scan --wait --fail-on-gateGates are the enforcement point; outcomes are recorded
Respond when a gate or guardrail blocksA workflow on on.policy.violationTickets, pages and notifications are side effects the workflow records
Open fix pull requests for reachable, exploited vulnerabilitiesA workflow calling griffin-remediate, or an auto-fix templateScope, conditions and concurrency are explicit
Let a CI guardrail fix instead of failAn auto-fix guardrail (effect AUTO_FIX) with a pre-approved scopeThe docs describe Griffin pinning to the last safe version, updating the lockfile and rerunning tests
Decide which remediation categories may run without approvalAutonomous Remediation settingsThe master toggle and per-category Manual or Auto apply everywhere
Run a recurring auditA workflow on on.scheduleCron in UTC, with owners emailed only when something is stale
Allow a one-off exceptionA policy exception with an expiryApprovers, justification and audit trail, without changing the policy

The rule of thumb: policies decide, gates enforce, workflows respond and remediate, settings bound what remediation may do.

Auto-fix guardrails require a pre-approved scope (repositories, package ecosystems, severity bands). Start narrow.

Step by step: move one runbook into a workflow

Here is a rollout that a platform owner can run in a few weeks, starting with the lowest risk.

Step 1: pick the first runbooks

Write each runbook as "when X, do Y, tell Z" and start with the frequent, low-judgment ones: the weekly SBOM audit, routing gate blocks to tickets, the daily digest. Remediation comes later.

Step 2: keep definitions in a reviewed repository

Put workflow YAML in a repository with a CODEOWNERS entry that makes the security team approve changes, and branch protection that requires that review.

security-workflows/
  workflows/
    weekly-sbom-freshness.yaml
    release-gate-response.yaml
    auto-fix-critical-on-main.yaml
  CODEOWNERS

Step 3: install the first template

In the web app, go to Workflows, Library and install weekly-sbom-freshness-audit. Edit only the environments, threshold and email template, and commit the result so what runs is what was reviewed.

Step 4: start every new workflow in notify-only mode

Before a workflow takes any action, have it only tell you what it would have done. For the auto-fix workflow, that means keeping scan and reachability and replacing remediate, open-pr and notify with a single notification step:

This is a Safeguard Workflows definition. It runs in Safeguard's runner, not in GitHub Actions.

    - id: would-fix
      uses: safeguard/slack-notify@v1
      with:
        channel: "#security-automation-dryrun"
        template: remediation-posted
      if: ${{ steps.reachability.outputs.reachable == true }}

Run it for two weeks. Read every notification. If you disagree with what it would have done, change the filters before it can act.

Step 5: pin dev, then staging, then prod

Pin the dev environment to the new version. Watch the timeline in the Workflows tab and the spans in your observability stack. Promote to staging, then prod, one environment at a time.

Step 6: add remediation with approval on

Restore the remediate and open-pr steps with strategy: conservative. In Settings, AI Remediate, turn on Require Approval and Test Integration. Leave the Autonomous Remediation categories at Manual. Every proposed fix now needs a person before it becomes a pull request.

Step 7: widen with evidence

After a few weeks of reviewing proposed fixes, decide category by category whether to move from Manual to Auto, starting with the narrowest scope: transitive-only upgrades (the auto-fix-transitive-only template), safe breaking-change level, one repository group. Measure how many proposed fixes were accepted, edited or rejected, and widen only where the answer supports it.

Step 8: wire the CI gate

Add safeguard ci scan --wait --fail-on-gate to release pipelines (the CI/CD Integration docs cover the secret key setup), then turn on release-gate-response so every block becomes a ticket and critical blocks page on-call.

What Workflows does not do, and where the edges are

  • The CLI does not manage workflows. Install, edit and enable them in the web app.
  • Policy outcomes are turned on per workspace. If the Outcome column is missing, ask your Safeguard contact.
  • A workflow opens pull requests; your repository merges them. Keep human review on anything classified Major or Critical.
  • Code you do not build is outside the loop. A vendor appliance, hosted service or operating system runtime still needs its fix from that vendor. Vendor risk workflows track and escalate it; they cannot patch it.

Common mistakes

  1. Automating the action before the decision. Teams write griffin-remediate first and filters second. Write the filters first, run notify-only and only add actions when the filters pick the right findings.
  2. Notifying unconditionally. A notification without an if that checks something happened trains people to mute the channel. Every notify step should depend on an output.
  3. Writing cron in local time. Schedules are UTC. Convert and comment.
  4. One giant workflow. A single workflow that scans, gates, fixes, tickets and reports is hard to review and hard to roll back. Split by runbook, and use triggers to connect them.
  5. Turning on Auto before reading Manual. The remediation master toggle and categories exist so you can read proposed fixes first. Skipping that step means discovering your breaking-change tolerance in production.

FAQ

How do I automate vulnerability remediation without auto-merging pull requests?

Use a workflow that calls griffin-remediate and open-pull-request, with if conditions on reachability and fix success. The workflow opens the pull request; your repository's review rules decide the merge. Safeguard's AI Remediate guidance recommends not auto-merging breaking changes.

What triggers can start a Safeguard workflow?

Image pushes, repository pushes, SBOM uploads, newly published vulnerabilities affecting your components, guardrail BLOCK or WARN decisions, vendor SBOM updates, cron schedules in UTC and manual runs from the UI, CLI or API. One workflow can declare several triggers.

Can security automation require approval before it changes code?

Yes. AI Remediate has a Require Approval setting, and every Autonomous Remediation category starts at Manual until the master toggle is on. Workflow definitions themselves can require code review in Git before changes land.

How do I audit what an automated workflow did?

Each run produces a step-by-step timeline in the Workflows tab, structured logs, OpenTelemetry spans to your OTLP endpoint and signed audit records for every pull request opened, ticket created or notification sent.

Can workflows run inside our own network?

Yes. A workflow can target a self-hosted runner with runs-on: self-hosted. The CLI's local runner keeps source code on the machine, uploads only the SBOM and findings, and uses outbound HTTPS only.

How do I fail a CI pipeline when a Safeguard gate fails?

Run safeguard ci scan --wait --fail-on-gate with the gate name or ID. It exits non-zero when the gate is Failed, Error or Not evaluated, and zero when it is Passed or Warning.

What happens to my edits when a workflow template is upgraded?

Safeguard pulls the new template version and keeps your customizations with a three-way merge. Conflicts are flagged in the UI for review before they apply.

How do security exceptions work with automated gates?

A developer requests an exception with a justification and expiry date; approvers review it; the decision is recorded. Exceptions on blocking guardrails expire automatically, and breakglass exceptions need two-person approval.

Fixing what the workflows find

Workflows make response consistent, but they still depend on a fix existing for the component they flag. The faster a fixed version is available and verified, the more of a runbook can run on its own, so the remediation options below are what the automation ultimately calls on.

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, Griffin, Safeguard's security model, opens a policy gated pull request that moves the affected dependency to the safe version, and your own CI runs your tests on it before anyone merges. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation categories include dependencies, licenses, security posture and findings, and each one is set separately. 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. Auto-merge is a separate switch and stays off by default, so your team decides what merges 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.

3. Gold Registry: start from components that are already fixed

Safeguard Gold rebuilds patched versions of open-source packages and images from source, signs each build, attaches an SBOM, SLSA provenance and VEX, and serves them from registry.safeguard.sh to your organization. Every Gold artifact is held continuously to zero exploitable critical or high CVEs and a completed license check, with signed build provenance (signed with Safeguard's key and verifiable with cosign, SLSA Build Level 3 as the design target) 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 build of a specific package. Ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingSafeguard policies and gates in CI
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch
You want to start clean on new projectsPull 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 sets up the local runner on your own machine, approves it with its device code, then scans from the terminal. It shows how jobs run where the code lives, with only the SBOM and findings sent back.

Click through it at your own pace, or open it full screen.

The second demo is a real Safeguard CLI session. A developer asks the assistant to fix a lodash CVE; it reads the finding and advisory, asks before any command that changes something, updates the dependency, runs the install and tests with approval, prints a summary and pushes nothing. It is the hands-on version of what a workflow's remediation steps prepare.

Click through it at your own pace, or open it full screen.

The third demo is a real Android session: work is sent to a computer running the CLI, and the command is approved on the phone with Allow once, Allow for turn or Deny. Automation prepares the work and a person decides, even away from a desk.

Click through it at your own pace, or open it full screen.

To try Safeguard yourself, download the apps or start with the CLI documentation. For how this fits the wider governance model, read Security governance in Safeguard and Safeguard CLI approval modes.

Quick check

A workflow's notify step has no if condition. What goes wrong?

It posts whether or not the earlier steps did anything, so the channel fills with messages about nothing and people stop reading it. Make the notify step depend on an output, such as a pull request URL not being empty.

You write cron "0 9 * * 1" expecting 09:00 in Bengaluru. When does it run?

At 09:00 UTC on Mondays, which is 14:30 IST. Safeguard evaluates schedules in UTC, so convert first and add a comment with the local time.

A gate's only Block policy could not be evaluated because its search timed out. Does the release pass?

No. The gate's outcome is Error, an Error is never counted as a pass, and safeguard ci scan --wait --fail-on-gate exits non-zero with the reason.

Sources

Last reviewed: 27 October 2026.

Never miss an update

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

We email you a link to confirm, and only then add you to the list. Unsubscribe in one click. Privacy

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.