7 Proven Software Supply Chain Security Tactics
Engineering leaders: if software supply chain security is the mandate, this is your copy-paste plan. Below you’ll wire SBOM, VEX, and SLSA into CI so every build ships with signed build provenance, developer-owned triage, and deploy fail-gates that block exploitable risk—without slowing velocity.
You’ll get:
- Auto-SBOM per build, attached to the artifact.
- VEX that separates exploitable vulnerabilities from noise.
- SLSA provenance to prove what built what, when.
- Fail-gates + exception workflows that keep velocity high.

If you manage Android fleets, don’t miss our step-by-step guide to Android patch automation to ship the November 2025 update in 48 hours with staged rollouts, MDM gates, and device-posture telemetry.
keep learning on our Blog → https://www.cybersrely.com/blog/.
TL;DR: Software Supply Chain Security checklist
- Generate an SBOM on every build (CycloneDX or SPDX).
- Emit a VEX per release to mark exploitable vs not_affected.
- Produce SLSA provenance and sign both artifact & attestations.
- Gate deploys on signature + provenance + “no exploitable criticals.”
- Allow time-boxed exceptions with expiration and compensating controls.
GitHub Actions for software supply chain security (SBOM → VEX → SLSA)
1) Build + SBOM (CycloneDX or SPDX)
# .github/workflows/supply-chain.yml
name: supply-chain-security
on: [push]
permissions:
contents: read
id-token: write # for keyless signing
packages: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 1 }
- name: Build (Node example)
run: |
set -euo pipefail
npm ci
npm run build
sbom:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4
# CycloneDX for Node (swap for your stack)
- name: Install CycloneDX
run: npm i -g @cyclonedx/cyclonedx-npm
- name: Generate SBOM (CycloneDX JSON)
run: cyclonedx-npm --output-file sbom.cdx.json --spec-version 1.5
- uses: actions/upload-artifact@v4
with:
name: sbom
path: sbom.cdx.json
Python example (per-service SBOM):
pip install cyclonedx-bom
cyclonedx-py --format json --outfile sbom.cdx.json
Java/Maven example (module SBOM):
<!-- pom.xml -->
<plugin>
<groupId>org.cyclonedx</groupId>
<artifactId>cyclonedx-maven-plugin</artifactId>
<version>2.8.0</version>
<executions>
<execution>
<phase>package</phase>
<goals><goal>makeAggregateBom</goal></goals>
<configuration><schemaVersion>1.5</schemaVersion></configuration>
</execution>
</executions>
</plugin>
2) Scan + produce VEX (downgrade the noise)
scan-and-vex:
runs-on: ubuntu-latest
needs: sbom
steps:
- uses: actions/download-artifact@v4
with: { name: sbom }
# Use a maintained scanner Action to avoid curl scripts
- name: Scan SBOM for known vulns
uses: anchore/scan-action@v3
with:
sbom: 'sbom.cdx.json'
fail-build: false
id: scan
- name: Generate OpenVEX from scan output (simple policy)
run: |
echo '${{ steps.scan.outputs.scan-results }}' > grype.json
jq -n --argfile g grype.json '
{
"@context":"https://openvex.dev/ns/v0.2.0",
"statements": (
$g.matches
| group_by(.vulnerability.id)
| map({
vulnerability: (.[0].vulnerability.id),
products: [ { "@id": "pkg:app/${{ github.repository }}@${{ github.sha }}" } ],
status: (
if any(.artifact.locations[]?.path; test("dev|test|examples")) then "not_affected"
else "affected" end
),
justification: "inlineMitigationsAlreadyExist"
})
)
}' > vex.openvex.json
- uses: actions/upload-artifact@v4
with: { name: vex, path: vex.openvex.json }
As your policy matures, enrich the VEX generator with runtime context, feature flags, OS packages, and compensating controls so your VEX reflects exploitability in your environment.
3) Sign artifact + attach SLSA provenance (keyless)
sign-and-provenance:
runs-on: ubuntu-latest
needs: build
env:
IMAGE: ghcr.io/${{ github.repository }}/app:${{ github.sha }}
steps:
- uses: actions/checkout@v4
- name: Build container
run: docker build -t "$IMAGE" .
- name: Push to GHCR
run: |
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $GITHUB_ACTOR --password-stdin
docker push "$IMAGE"
- name: Install cosign (action)
uses: sigstore/cosign-installer@v3
- name: Keyless sign
run: cosign sign "$IMAGE" --yes
- name: Create SLSA provenance predicate (minimal)
run: |
cat > provenance.json <<'JSON'
{
"_type": "https://in-toto.io/Statement/v0.1",
"subject": [{"name": "IMAGE_PLACEHOLDER"}],
"predicateType": "https://slsa.dev/provenance/v1",
"predicate": {
"builder": { "id": "github-actions" },
"buildType": "container",
"invocation": {
"parameters": { "sha": "${{ github.sha }}", "ref": "${{ github.ref_name }}" }
},
"metadata": { "buildStartedOn": "${{ github.run_started_at }}" }
}
}
JSON
sed -i "s/IMAGE_PLACEHOLDER/${IMAGE//\//\\/}/" provenance.json
- name: Attach provenance attestation
run: cosign attest --type slsaprovenance --predicate provenance.json "$IMAGE" --yes
- name: Attach SBOM and VEX as attestations
run: |
cosign attest --type cyclonedx --predicate sbom.cdx.json "$IMAGE" --yes
cosign attest --type openvex --predicate vex.openvex.json "$IMAGE" --yes
4) Gate deploys: signatures + provenance + exploitable-critical=0
# .github/workflows/deploy.yml
name: deploy
on: { workflow_dispatch: {} }
jobs:
verify-and-deploy:
runs-on: ubuntu-latest
env:
IMAGE: ghcr.io/${{ github.repository }}/app:${{ github.sha }}
steps:
- uses: sigstore/cosign-installer@v3
- name: Verify signature & provenance
run: |
cosign verify "$IMAGE" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity-regexp "https://github.com/${{ github.repository }}.+"
cosign verify-attestation "$IMAGE" --type slsaprovenance
- name: Pull SBOM & VEX attestations and enforce policy
run: |
cosign verify-attestation "$IMAGE" --type cyclonedx --output-json > sbom_att.json
cosign verify-attestation "$IMAGE" --type openvex --output-json > vex_att.json
# Block if any statement remains affected at Critical severity (toy logic; adapt!)
if jq -e '
.payload | @base64d | fromjson | .predicate.statements[]
| select(.status=="affected")
' vex_att.json; then
echo "Exploitable issues remain — blocking deploy"; exit 1
fi
- name: Deploy
run: ./scripts/deploy.sh "$IMAGE"
Bonus: add a tiny OPA/Rego policy for declarative gates
# policy/vex.rego
package policy.vex
deny[msg] {
some s
s := input.vex.statements[_]
s.status == "affected"
msg := sprintf("Exploitable vuln blocked: %v", [s.vulnerability])
}
Free Website Vulnerability Scanner (landing)

GitLab CI: replicate software supply chain security controls
# .gitlab-ci.yml
stages: [build, sbom, scan, attest, deploy]
variables:
IMAGE: $CI_REGISTRY_IMAGE/app:$CI_COMMIT_SHA
build:
stage: build
image: docker:24
services: [docker:24-dind]
script:
- docker build -t "$IMAGE" .
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
- docker push "$IMAGE"
sbom:
stage: sbom
image: node:20
script:
- npm i -g @cyclonedx/cyclonedx-npm
- cyclonedx-npm --output-file sbom.cdx.json --spec-version 1.5
artifacts: { paths: [sbom.cdx.json] }
scan:
stage: scan
image: alpine:3.20
script:
- apk add --no-cache jq
- echo "Run your preferred SBOM scanner here; export JSON to grype.json"
- echo '{"matches":[]}' > grype.json || true
artifacts: { paths: [grype.json] }
attest:
stage: attest
image: alpine:3.20
script:
- apk add --no-cache cosign jq
- cosign sign "$IMAGE" --yes
- cat > provenance.json <<'JSON'
{ "_type":"https://in-toto.io/Statement/v0.1",
"subject":[{"name":"IMAGE_PLACEHOLDER"}],
"predicateType":"https://slsa.dev/provenance/v1",
"predicate":{"builder":{"id":"gitlab-ci"},"buildType":"container",
"invocation":{"parameters":{"sha":"$CI_COMMIT_SHA","pipeline":"$CI_PIPELINE_ID"}}}}
JSON
- sed -i "s/IMAGE_PLACEHOLDER/${IMAGE//\//\\/}/" provenance.json
- cosign attest --type slsaprovenance --predicate provenance.json "$IMAGE" --yes
deploy:
stage: deploy
rules: [ { if: '$MANUAL_DEPLOY == "true"', when: manual } ]
image: alpine:3.20
script:
- apk add --no-cache cosign jq
- cosign verify "$IMAGE"
- cosign verify-attestation "$IMAGE" --type slsaprovenance
- ./deploy.sh "$IMAGE"
Time-boxed exceptions (keep velocity high)
Create a VEX override file checked into the repo; merge it before attesting.
// exceptions/vex-overrides.json
{
"@context": "https://openvex.dev/ns/v0.2.0",
"statements": [{
"vulnerability": "CVE-2025-12345",
"products": [{ "@id": "pkg:app/myapp@${GIT_SHA}" }],
"status": "under_investigation",
"justification": "compensatingControls",
"timestamp": "2025-11-04T12:00:00Z",
"expires": "2025-12-04T12:00:00Z",
"impact_statement": "Feature X disabled; WAF rule in place; monitored."
}]
}
Merge step:
jq -s '
reduce .[] as $v ({"@context":"https://openvex.dev/ns/v0.2.0","statements":[]};
.statements += ($v.statements // [])
)
' vex.openvex.json exceptions/vex-overrides.json > vex.merged.json
Operational tips for software supply chain security
- One artifact, many attestations. Attach SBOM, VEX, SLSA to the digest, not the tag.
- Evidence bucket. Archive SBOM, VEX, provenance, and the release decision JSON in immutable storage.
- Guardrails, not gates. Start with warnings; flip to blocking once exceptions and ownership are clear.
- Shift left on policy. Keep OPA/Rego and VEX mapping in-repo so engineers can iterate via PRs.
Sample report snippet by the tool to check Website Vulnerability

Related services & how we help next
- Supply Chain Risk Assessment — plan the rollout, pick formats (CycloneDX/SPDX), define policy, and map to software supply chain security outcomes:
https://www.pentesttesting.com/risk-assessment-services/ - Hands-on Remediation — pair with your team to fix exploitable issues and close the loop:
https://www.pentesttesting.com/remediation-services/ - Keep up with new posts on our Blog: https://www.cybersrely.com/blog/
Recent on the Cyber Rely blog
- 7 Proven Defenses for the Pixnapping Android Exploit (threat response for mobile teams).
- Remote Code Execution (RCE) in React.js – Top 5 Examples & Prevention Tips.
- Cross-Site Scripting (XSS) in RESTful APIs — Prevention & Protection.
- 10 Best Practices to Fix Weak SSL/TLS in TypeScript-Based ERPs.
- Mastering CSRF in TypeScript-Based ERP.
- Prevent Remote Code Execution in RESTful APIs — 4 Best Tips.
- Prevent Sensitive Data Exposure in React.js — 7 Best Ways.
Move from talk to proof
Get the SBOM/VEX CI Starter Pack and book a Supply Chain Risk Assessment & Remediation Workshop.
- Risk Assessment: https://www.pentesttesting.com/risk-assessment-services/
- Remediation: https://www.pentesttesting.com/remediation-services/
- Quick external snapshot: https://free.pentesttesting.com/
Optional JSON-LD
<script type="application/ld+json">
{
"@context":"https://schema.org",
"@type":"Article",
"headline":"7 Proven Software Supply Chain Security Tactics",
"keywords":"software supply chain security, SBOM, VEX, SLSA, build provenance, CI/CD security",
"mainEntityOfPage":{"@type":"WebPage","@id":"https://cybersrely.com/software-supply-chain-security-sbom-vex-slsa"}
}
</script>
🔐 Frequently Asked Questions (FAQs)
Find answers to commonly asked questions about Software Supply Chain Security Tactics.