Safeguard.sh Documentation Center

Workflows

Safeguard's workflow engine — chain discovery, scanning, policy, remediation, and notification steps into repeatable automations.

Workflows

A workflow is a sequence of Safeguard steps triggered by an event. Workflows let you encode "when this happens, do these things" without glue code — for example, "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."

Concepts

A workflow is composed of:

  • Trigger — what starts the workflow. Triggers are events, schedules, or manual runs.
  • Steps — the actions to execute, in order or in parallel.
  • Inputs and outputs — each step reads from the workflow context and can write to it.
  • Conditions — step-level if expressions that decide whether a step runs.
  • Concurrency — limits on how many instances of a workflow run simultaneously.

Workflows are defined in YAML, live in a Git repository (or inside the Safeguard UI), and run on Safeguard's managed runner or a self-hosted runner.

Triggers

TriggerFires on
on.image.pushedNew image or tag in a connected registry
on.repo.pushedNew commit or tag on a connected Git repository
on.sbom.receivedSBOM uploaded to Portal or via API
on.vulnerability.publishedNew vulnerability affects one of your components
on.zero_day.publishedSafeguard publishes a new zero-day advisory
on.policy.violationA guardrail records a BLOCK or WARN
on.vendor.sbom_updatedTPRM vendor sends a new SBOM
on.scheduleCron expression (UTC)
on.manualTriggered from the UI, CLI, or API

Triggers can be combined — a workflow can declare multiple on.* handlers.

Example: Auto-fix critical CVEs on main

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 != '' }}

Example: Gate every production admission

apiVersion: safeguard.sh/workflows/v1
kind: Workflow
metadata:
  name: prod-admission-gate
spec:
  on:
    policy.violation:
      filters:
        policy: prod-admission-policy
        decision: BLOCK
  steps:
    - id: open-ticket
      uses: safeguard/jira-create@v2
      with:
        project: SEC
        summary: "Blocked production admission: ${{ trigger.image }}"
        severity: ${{ trigger.severity }}

    - id: page-oncall
      uses: safeguard/pagerduty-trigger@v1
      with:
        service: prod-admission-failures
      if: ${{ trigger.severity == 'critical' }}

Example: Weekly SBOM freshness audit

apiVersion: safeguard.sh/workflows/v1
kind: Workflow
metadata:
  name: weekly-sbom-freshness
spec:
  on:
    schedule:
      cron: "0 9 * * 1"   # Mondays 09:00 UTC
  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 }}

Built-In Step Library

Steps are published as versioned uses: references. Major categories:

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

See the step reference for the full list with inputs/outputs.

Runners

Workflows execute on runners:

  • Safeguard Cloud runner (default) — fully managed, runs in the Safeguard FedRAMP-HIGH environment.
  • Self-hosted runner — runs inside your VPC / cluster, useful for accessing private networks, air-gapped sites, or regulated data. See Runner for installation.

A workflow can target either with runs-on: cloud (default) or runs-on: self-hosted.

Observability

Every workflow run produces:

  • A step-by-step timeline in the Workflows tab.
  • Structured logs streamed to the UI and archived for 90 days (Enterprise: configurable up to 7 years).
  • OpenTelemetry spans emitted to your configured OTLP endpoint.
  • Audit records signed by Safeguard for every external side-effect (PR opened, ticket created, notification sent).

Versioning and Promotion

Workflows are versioned via Git — you can require that all workflow changes go through code review before they land. The Safeguard UI shows a diff between the running version and the proposed version for any change.

Environments (dev, staging, prod) can each pin to different workflow versions for safe rollout.

On this page