Skip to content

Quality Gate Workflows

Each workflow in this page produces SARIF evidence (or a JSON report) that is signed as a digest-bound attestation by the attestation seam. All SARIF findings land in the GitHub code-scanning Security tab; the code-scanning required check is the merge gate for soft-fail workflows.

Predicate namespace: https://attested-delivery.github.io/attestations/<gate>/v1

Calling convention: reference every workflow by the .github repo’s full 40-char commit SHA:

uses: attested-delivery/.github/.github/workflows/<name>.yml@<sha> # vX.Y.Z

Resolve the SHA at use time (gh api repos/attested-delivery/.github/git/ref/tags/<tag>). pin-check enforces SHA-pinning on every caller.


SAST via CodeQL code scanning. Builds a CodeQL database and runs security queries, emitting merged SARIF 2.1.0 into the code-scanning hub and uploading a sast-sarif artifact for the seam.

Predicate type: https://attested-delivery.github.io/attestations/sast/v1

NameTypeRequiredDefaultDescription
languagesstringyesComma-separated CodeQL languages (e.g. javascript-typescript,python)
build-modestringnononeCodeQL build mode: none, autobuild, or manual
config-filestringno''Optional path to a codeql-config.yml
queriesstringno''Optional query suite (e.g. security-extended)
NameValue
sarif-artifactsast-sarif
sarif-filenameresults.sarif
permissions:
security-events: write
contents: read
actions: read

github/codeql-action (confirm it is permitted in the org allow-list before use).

jobs:
sast:
permissions:
security-events: write
contents: read
actions: read
packages: read
uses: attested-delivery/.github/.github/workflows/reusable-sast-codeql.yml@<sha>
with:
languages: 'javascript-typescript,python'

Software composition analysis via OSV-Scanner and GitHub dependency review. Runs two complementary layers: OSV-Scanner produces SARIF uploaded to code scanning and the OSV Scanner SARIF file artifact; dependency-review blocks PRs that introduce vulnerable or disallowed-license dependencies.

Predicate type: https://attested-delivery.github.io/attestations/sca/v1

NameTypeRequiredDefaultDescription
fail-on-severitystringnohighDependency-review threshold: low, moderate, high, or critical
scan-argsstringno--recursive\n./OSV-Scanner arguments (block scalar)
NameValue
sarif-artifactOSV Scanner SARIF file
sarif-filenameresults.sarif
permissions:
actions: read
contents: read
security-events: write
pull-requests: write

The dependency-review job runs only on pull_request events.

google/osv-scanner-action/* (the subpath form).

jobs:
sca:
permissions:
actions: read
contents: read
security-events: write
pull-requests: write
uses: attested-delivery/.github/.github/workflows/reusable-sca-osv.yml@<sha>
with:
fail-on-severity: high

Container image vulnerability scan, IaC misconfiguration scan, and license scan via Trivy. The IaC+license job is soft-fail (code-scanning check is the gate); the image job is fail-closed on findings at or above severity.

Predicate types (seam-assigned by caller):

  • IaC+license: https://attested-delivery.github.io/attestations/iac-license/v1
  • Container image: caller-assigned predicate for the image SARIF
NameTypeRequiredDefaultDescription
image-refstringno''Image to scan by digest; empty skips the image job
severitystringnoHIGH,CRITICALSeverities to report and fail on
scan-iacbooleannotrueScan the repo for IaC misconfiguration and license issues
NameValue
sarif-artifactiac-license-sarif
sarif-filenametrivy-iac-license.sarif
image-sarif-artifactcontainer-scan-sarif (when image-ref is set)
image-sarif-filenametrivy-image.sarif (when image-ref is set)
permissions:
contents: read
security-events: write
actions: read

The image job additionally needs packages: read.

aquasecurity/trivy-action — release-critical. A caller’s release fails at startup if this action is not on the org allow-list.

jobs:
trivy:
permissions:
contents: read
security-events: write
actions: read
uses: attested-delivery/.github/.github/workflows/reusable-trivy.yml@<sha>
with:
image-ref: ghcr.io/attested-delivery/app@sha256:... # omit to scan repo only

IaC policy-as-code via Checkov (graph-based, complements Trivy). Soft-fail; findings land in code scanning under the checkov-iac-policy category. Installs Checkov via pip into an isolated virtualenv — no third-party action; no allow-list entry required.

Predicate type: https://attested-delivery.github.io/attestations/iac-policy/v1

NameTypeRequiredDefaultDescription
directorystringno.Directory to scan
frameworkstringnoterraformCheckov framework(s) to run (e.g. terraform, terraform_plan)
checkov-versionstringno3.2.524Exact Checkov version to install (pinned, no range)
NameValue
sarif-artifactiac-policy-sarif
sarif-filenamecheckov-iac-policy.sarif
permissions:
contents: read
security-events: write
actions: read

None — all actions are GitHub-created.

jobs:
checkov:
permissions:
contents: read
security-events: write
actions: read
uses: attested-delivery/.github/.github/workflows/reusable-checkov.yml@<sha>
with:
directory: .

OpenSSF Scorecard supply-chain posture analysis. Scores 0–10 heuristics (Branch-Protection, Code-Review, Token-Permissions, Dangerous-Workflow, Pinned-Dependencies, Signed-Releases, …) and uploads SARIF to code scanning. With publish-results: true, results are published to the OpenSSF REST API.

This is a repo-level posture signal, not an artifact verdict.

Recommended caller triggers: branch_protection_rule, schedule (weekly), and push to the default branch.

Predicate type: https://attested-delivery.github.io/attestations/scorecard/v1

NameTypeRequiredDefaultDescription
publish-resultsbooleannotruePublish to the OpenSSF API (public repos only)
NameValue
sarif-artifactscorecard-sarif
sarif-filenamescorecard.sarif
permissions:
security-events: write
id-token: write
contents: read
actions: read

id-token: write is required to publish results to the OpenSSF API.

ossf/scorecard-action.

jobs:
scorecard:
permissions:
security-events: write
id-token: write
contents: read
actions: read
uses: attested-delivery/.github/.github/workflows/reusable-scorecard.yml@<sha>

SAST for shell scripts (plugin hooks) via Red Hat Differential ShellCheck (full-tree mode). Plugin hooks run with full user privileges; this gate produces SARIF that feeds the seam as a shellcheck/v1 verdict.

Predicate type: https://attested-delivery.github.io/attestations/shellcheck/v1

NameTypeRequiredDefaultDescription
strict-on-pushbooleannofalseFail the job on ShellCheck defects for push events
NameValue
sarif-artifactsast-hooks-sarif
sarif-filenameshellcheck.sarif
permissions:
contents: read
security-events: write

redhat-plumbers-in-action/* — must be added before a caller runs this gate.

jobs:
shellcheck:
permissions:
contents: read
security-events: write
uses: attested-delivery/.github/.github/workflows/reusable-shellcheck.yml@<sha>

SAST for bundled MCP-server and plugin source code via Semgrep. Detects command injection, eval/new Function, os.system, subprocess shell=True, unsafe deserialization, and similar patterns. Soft-fail; findings land in code scanning under the semgrep category. Installs Semgrep via pip in an isolated virtualenv — no third-party action; no allow-list entry required.

Predicate type: https://attested-delivery.github.io/attestations/semgrep/v1

NameTypeRequiredDefaultDescription
directorystringno.Directory to scan
configstringnop/security-audit p/secrets p/command-injectionSemgrep rule configs, space-separated
semgrep-versionstringno1.139.0Exact Semgrep version to install (pinned, no range)
NameValue
sarif-artifactsast-code-sarif
sarif-filenamesemgrep.sarif
permissions:
contents: read
security-events: write
actions: read

None — pip-installed in an isolated virtualenv; GitHub-created actions only.

jobs:
semgrep:
permissions:
contents: read
security-events: write
actions: read
uses: attested-delivery/.github/.github/workflows/reusable-semgrep.yml@<sha>
with:
directory: .

Secret scanning via Gitleaks and TruffleHog. Gitleaks is soft-fail (SARIF to code scanning is the gate); TruffleHog runs in verified-only mode and hard-fails when it confirms a live secret. Both tools install as checksum-verified release binaries — no third-party action; no allow-list entry required.

Predicate type (Gitleaks SARIF): https://attested-delivery.github.io/attestations/secrets/v1

NameTypeRequiredDefaultDescription
directorystringno.Directory to scan
gitleaks-versionstringno8.30.1Pinned Gitleaks version (no v prefix)
trufflehog-versionstringno3.95.6Pinned TruffleHog version (no v prefix)
fail-on-verifiedbooleannotrueFail the job if TruffleHog confirms a verified live secret
NameValue
sarif-artifactsecrets-sarif
sarif-filenamegitleaks.sarif
permissions:
contents: read
security-events: write
actions: read

None — both tools are checksum-verified release binaries; GitHub-created actions only.

jobs:
secrets:
permissions:
contents: read
security-events: write
actions: read
uses: attested-delivery/.github/.github/workflows/reusable-secrets.yml@<sha>
with:
directory: .

Declarative-constituent integrity gate. Reviews the marketplace catalog (marketplace.json) and plugin manifests (plugin.json) for structural invariants: every external plugin source is pinned to a 40-char SHA, the marketplace name is not Anthropic-reserved, and required fields are present. Soft-fail; implemented as pure stdlib Python — no install, no third-party action, no allow-list entry required.

Predicate type: https://attested-delivery.github.io/attestations/manifest/v1

NameTypeRequiredDefaultDescription
directorystringno.Repo root to review
NameValue
sarif-artifactmanifest-sarif
sarif-filenamemanifest-review.sarif
permissions:
contents: read
security-events: write
actions: read

None — pure stdlib Python; GitHub-created actions only.

jobs:
manifest-review:
permissions:
contents: read
security-events: write
actions: read
uses: attested-delivery/.github/.github/workflows/reusable-manifest-review.yml@<sha>
with:
directory: .

DAST via OWASP ZAP full scan (spider + active scan) against a running target. The JSON report is uploaded as the dast-report artifact for the seam. Caller must stand up the target before invoking.

Predicate type: https://attested-delivery.github.io/attestations/dast/v1

NameTypeRequiredDefaultDescription
targetstringyesURL of the running target to scan
fail-actionbooleannotrueFail the job when ZAP reports alerts
cmd-optionsstringno-aAdditional ZAP command-line options
NameValue
report-artifactdast-report
report-filenamereport_json.json
permissions:
contents: read

zaproxy/action-full-scan.

jobs:
gate-dast:
permissions:
contents: read
uses: attested-delivery/.github/.github/workflows/reusable-zap.yml@<sha>
with:
target: https://staging.example.com

Load and performance gate via Grafana k6. The gate is k6’s thresholds: a threshold breach causes k6 to exit 99 (ThresholdsHaveFailed), failing the job. When attest: true, the JSON summary is signed as a custom performance attestation bound to the subject.

Predicate type (when attest: true): https://attested-delivery.github.io/attestations/k6-load/v1

NameTypeRequiredDefaultDescription
script-pathstringyesPath to the k6 test script
attestbooleannofalseSign the k6 summary as a custom performance attestation
subject-namestringno''Subject name for the attestation (required when attest: true)
subject-digeststringno''Subject digest for the attestation (required when attest: true)
permissions:
id-token: write
attestations: write
contents: read

id-token: write and attestations: write are only consumed when attest: true.

grafana/setup-k6-action, grafana/run-k6-action.

jobs:
load:
permissions:
id-token: write
attestations: write
contents: read
uses: attested-delivery/.github/.github/workflows/reusable-k6.yml@<sha>
with:
script-path: tests/load.js
attest: true
subject-name: my-app
subject-digest: ${{ needs.build.outputs.digest }}

OpenVEX vulnerability disposition. Normalizes an OpenVEX document with vexctl merge and signs it as an attestation bound to the artifact digest. Enables deploy gates to enforce “no undispositioned high/critical” rather than “zero findings”. Self-signs — verify with --signer-workflow .../reusable-vex.yml, not the seam.

Predicate type (self-signed): https://openvex.dev/ns/v0.2.0

NameTypeRequiredDefaultDescription
subject-namestringyesSubject the OpenVEX statement is bound to
subject-digeststringyesSubject digest (sha256:...)
vex-pathstringno.vex/openvex.jsonPath to the OpenVEX document in the repository
vexctl-versionstringnov0.4.1vexctl module version to install
permissions:
id-token: write
attestations: write
contents: read

None beyond GitHub-created actions/setup-go, actions/attest, and actions/checkout.

jobs:
vex:
needs: [build]
permissions:
id-token: write
attestations: write
contents: read
uses: attested-delivery/.github/.github/workflows/reusable-vex.yml@<sha>
with:
subject-name: ghcr.io/attested-delivery/app
subject-digest: ${{ needs.build.outputs.digest }}
vex-path: .vex/openvex.json

Discussion

Comments are powered by GitHub Discussions. Sign in with GitHub to ask a question or share how this applies in your org.