CI: GitHub Actions & scanning in pipelines
Wire Cybros into CI to scan on every PR and block deploys when policy is violated. This page shows three recipes:
- Deployment gate — fail a job on blocking findings.
- Scan on PR with
gh cybros. - Generic "CLI in CI" — the
cybrosCLI in any runner.
Store your org API key as the CYBROS_API_KEY repository secret first (see
Authentication). Mint a least-privilege key with
cybros keys create ... --role member.
1. Deployment gate
Cybros exposes a deployment-gate endpoint that evaluates a commit against
your policy and returns an approved boolean. Use it as a required check.
A ready-to-adapt snippet lives in the repo at
cybros-api/docs/github-actions.yml.
The core job:
name: cybros-security-gate
on:
push:
branches: [main]
pull_request:
jobs:
deployment-gate:
runs-on: ubuntu-latest
steps:
- name: Cybros deployment gate
env:
CYBROS_API_KEY: ${{ secrets.CYBROS_API_KEY }}
CYBROS_API_URL: ${{ vars.CYBROS_API_URL || 'https://backend.cybros.hacktigerlabs.com' }}
run: |
set -euo pipefail
REPO="${GITHUB_REPOSITORY}"
SHA="${GITHUB_SHA}"
# The scan may still be running just after a push — poll the gate.
for i in $(seq 1 30); do
RESP="$(curl -sS \
-H "Authorization: Bearer ${CYBROS_API_KEY}" \
"${CYBROS_API_URL}/api/v1/deployment-gate?repo=${REPO}&sha=${SHA}")"
APPROVED="$(echo "$RESP" | jq -r '.approved')"
STATUS="$(echo "$RESP" | jq -r '.status')"
if [ "$APPROVED" = "true" ]; then
echo "Cybros security gate passed."; exit 0
fi
if [ "$STATUS" = "no_completed_scan" ]; then
echo "Scan not complete yet; retrying ($i/30)..."; sleep 10; continue
fi
echo "Cybros security gate FAILED — blocking findings present."
echo "$RESP" | jq '{security_score, blocking_findings, report_url}'
exit 1
done
echo "Timed out waiting for a completed Cybros scan."; exit 1
Make deployment-gate a required status check on the branch so PRs can't
merge (and deploys can't proceed) until it passes.
CYBROS_API_URLhere is the host (no/api/v1suffix) because the script appends the path. The CLI/SDK env var, by contrast, expects the full.../api/v1base — see Authentication.
2. Scan on PR with gh cybros
If you prefer to drive the scan from CI (rather than relying on webhook-triggered
scans), use the gh cybros extension. gh and jq are
preinstalled on GitHub-hosted runners.
name: cybros-scan
on: pull_request
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install gh-cybros
run: gh extension install ayushtenguria/gh-cybros
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Scan and fail on critical/high
env:
CYBROS_API_KEY: ${{ secrets.CYBROS_API_KEY }}
run: |
set -euo pipefail
RESULT="$(gh cybros scan --json)"
echo "$RESULT" | jq '.findings_summary'
BLOCKING="$(echo "$RESULT" | jq '(.findings_summary.critical // 0) + (.findings_summary.high // 0)')"
if [ "$BLOCKING" -gt 0 ]; then
echo "::error::$BLOCKING critical/high findings — failing the build."
exit 1
fi
3. Generic "CLI in CI"
The cybros CLI works in any runner. It resolves the key from CYBROS_API_KEY,
exits 2 when unauthenticated, and supports --json for scripting.
name: cybros-cli
on: pull_request
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # so the CLI can read the git ref/remote
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install cybros
- name: Scan and gate on policy
env:
CYBROS_API_KEY: ${{ secrets.CYBROS_API_KEY }}
run: |
set -euo pipefail
# Trigger + wait; the CLI streams progress and exits non-zero on error.
SCAN_ID="$(cybros --json scan | jq -r '.id')"
# Fail the build if any critical findings remain:
COUNT="$(cybros --json findings --scan "$SCAN_ID" --severity critical | jq 'length')"
echo "Critical findings: $COUNT"
test "$COUNT" -eq 0
The same pattern works in GitLab CI, CircleCI, Jenkins, or any container — set
CYBROS_API_KEY in the environment and call the CLI.
Tips
- Full history. Use
fetch-depth: 0on checkout so the CLI/extension can read the git ref and remote. - Least privilege. Use a
member-role key for CI. - Machine-readable everywhere.
--jsonon every read command → pipe intojq. - Exit codes.
0success,1error,2unauthenticated — see the CLI reference.