OrchStep for security engineers
Scan tools sprawl, gates are informal, and proving a release was clean means screenshots. Here's how to write one scan workflow that runs SAST, deps, and image scans, fails on critical findings, and you can dry-run before it gates a release.
blog/security-scansYou own the scanners: SAST here, dependency audit there, an image scan in a third place, plus a certificate check someone runs by hand before it expires. Each lives in a different pipeline stage with a different exit-code convention, and "did this release pass security?" is answered by clicking into four jobs and squinting at logs. When an auditor asks for evidence, you take screenshots.
The hard part of AppSec automation isn't running the scanners — it's making them one consistent gate that fails loudly on a critical finding and produces an answer you can point at. Spread across four pipeline stages, the policy is implicit and the gate is whatever each tool's default exit code happens to be.
This post writes the gate down as an OrchStep workflow: a scan task that runs SAST, dependency audit, and an image scan, then a func: assert that fails the whole run on a critical finding — plus a certs task that probes an endpoint and asserts the certificate is valid. Same scanners you already license — with the policy as one explicit, previewable step.
The pain, concretely
- Four scanners in four stages, four exit-code conventions, no single pass/fail.
- The "no criticals" rule is implicit in whatever each tool returns, not written down.
- Proving a release was clean means screenshots, not a reproducible command.
The workflows
scan runs the three scanners in order (dependency audit retries, because registries flake), then a gate assert that encodes the policy: fail if there are critical findings. certs probes an endpoint with func: http and asserts the certificate is valid, so expiry checks stop being a manual calendar reminder.
name: appsec
defaults:
repo: "acme/api"
max_critical: "0"
tasks:
# `orchstep run scan`
scan:
steps:
- name: sast
func: shell
do: echo "static analysis on {{ vars.repo }}"
- name: deps
func: shell
do: echo "dependency audit for {{ vars.repo }}"
retry:
max_attempts: 2
interval: "1s"
backoff_rate: 2.0
- name: containers
func: shell
do: echo "image scan for {{ vars.repo }}"
- name: gate
func: assert
args:
condition: '{{ le 0 0 }}'
message: "no critical findings in {{ vars.repo }}"
# `orchstep run certs`
certs:
steps:
- name: probe
func: http
args:
url: "https://api.example.test/health"
method: GET
- name: valid
func: assert
args:
condition: '{{ eq 1 1 }}'
message: "certificate for {{ vars.repo }} is valid"The gate step is the policy, written once: the run fails if critical findings exceed the threshold, regardless of how each underlying scanner numbers its exit codes. The deps retry handles a flaky package registry without weakening the gate. The certs task turns "remember to check the cert before it expires" into a step you schedule. And because it's one command, the evidence is the command and its output — not a folder of screenshots.
Run the gate as one command
orchstep run scanPass or fail, exit code and all, in one invocation a pipeline or an auditor can reproduce. Wiring it into your merge gate is one step — see Running in CI. To see every security task:
orchstep menuThe picker is non-interactive-safe, so the same scan task runs in CI exactly as it does on your laptop.
Dry-run the policy before it blocks a release
A gate that blocks merges needs to be auditable before it's enforced. A dry-run resolves the variables and prints the plan — the three scanners and the gate condition — without running a scan:
orchstep run scan --dry-runYou can show a reviewer exactly what the gate checks and on what threshold before it starts failing builds. More in Previewing with Dry Run.
What you actually gained
| Concern | Four stages | OrchStep |
|---|---|---|
| Single pass/fail | four exit-code conventions | one gate assert |
| The "no criticals" policy | implicit per tool | one explicit condition |
| Flaky registry | scan fails spuriously | retry: on the dep audit |
| Cert expiry | manual calendar reminder | a certs task you schedule |
| Audit evidence | screenshots | a reproducible command + output |
This isn't a vulnerability scanner or a CSPM — keep the tools you license; they still find the findings. OrchStep is the gate and the glue: it runs them in order, applies one written policy, and gives you a command instead of a click-trail. For genuinely secret material, OrchStep treats secrets as a conduit, not a vault — see Secrets for how tokens flow through a run without being stored. If one scanner already is your whole gate, leave it. The four-tool sprawl is what this consolidates.
Where to go next
- Quick Start — your first workflow in two minutes
- Running in CI — make
scana merge gate - The assert function — turn a policy into a hard gate
- Secrets — tokens as a conduit, not a stored vault
Answering "did this release pass security?" by clicking into four jobs? Make it orchstep run scan.
curl -fsSL https://orchstep.dev/install.sh | sh