CI/CD Pipeline Setup
Learn how to integrate automated Trivy SBOM vulnerability scanning into GitHub Actions.
Integrating VAPT Insights into your automated software development workflows ensures that every code commit and deploy is audited for known vulnerabilities, security misconfigurations, and compliance risks.
This guide provides platform-specific, copy-pasteable configuration files to generate a Software Bill of Materials (SBOM) using Trivy and securely ingest it into the VAPT Insights platform.
🔐 Security Best Practices
Never Hardcode Secrets
Never hardcode your VAPT API credentials directly in your repository files. Always use your platform's secure secret storage (e.g., GitHub Actions Secrets) and reference them as environment variables.
Before configuring your pipelines, ensure you have:
- Generated a secure API key from the dashboard:
- Click Account Settings (under the "Account" section) in the bottom of your VAPT Insights sidebar.
- Click the API Tokens tab on the top menu navigation bar.
- Click Generate New Token, name it (e.g.,
GitHub Actions CI/CD), and copy the secret key immediately. - Alternatively, go directly to the VAPT Insights API Settings Dashboard.
- Saved it as a secret named
VAPT_INSIGHTS_API_KEYin your GitHub repository configurations.
1. GitHub Marketplace Action (Recommended)
The official VAPT Insights Security Scan Action packages the Trivy installation, CycloneDX SBOM generation, and secure upload steps into one reusable action.
Add your API key as a repository secret named VAPT_INSIGHTS_API_KEY, then create .github/workflows/vapt-security-scan.yml:
name: VAPT Insights Security Scan
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run VAPT Insights Security Scan
uses: vaptinsights/[email protected]
with:
api-key: ${{ secrets.VAPT_INSIGHTS_API_KEY }}
scan-path: .
artifact-name: ${{ github.event.repository.name }}The Action accepts the following inputs:
| Input | Required | Default | Description |
|---|---|---|---|
api-key | Yes | — | VAPT Insights API key stored in GitHub Actions secrets. |
artifact-name | Yes | — | Artifact name displayed in VAPT Insights. |
scan-path | No | . | Repository folder to scan. |
artifact-version | No | Short commit SHA | Version displayed for the uploaded artifact. |
Pin the Action version
The example uses the exact v1.0.0 release for reproducible builds. You can use v1 after the stable major-version tag is available to receive backward-compatible updates automatically.
Scan a nested folder
Set scan-path to the application directory and include the service name in artifact-name:
- name: Scan SMS service
uses: vaptinsights/[email protected]
with:
api-key: ${{ secrets.VAPT_INSIGHTS_API_KEY }}
scan-path: services/sms-service
artifact-name: ${{ github.event.repository.name }}/sms-serviceScan multiple monorepo services
Use a matrix to scan and upload each service as a separate VAPT Insights artifact:
name: VAPT Insights Monorepo Scan
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
jobs:
security-scan:
name: Scan ${{ matrix.service.name }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
service:
- name: ui
path: ui
- name: sms-service
path: services/sms-service
- name: api-service
path: services/api-service
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Scan ${{ matrix.service.name }}
uses: vaptinsights/[email protected]
with:
api-key: ${{ secrets.VAPT_INSIGHTS_API_KEY }}
scan-path: ${{ matrix.service.path }}
artifact-name: ${{ github.event.repository.name }}/${{ matrix.service.name }}Each matrix entry runs independently. Add or remove entries under matrix.service to match the folders in your repository.
2. Manual GitHub Actions Setup
To run automated vulnerability scanning using Trivy on push events to your main branch, create a workflow file at .github/workflows/vapt-scan.yml with the following configuration:
name: VAPT Insights Security Scan
on:
push:
branches: [ main ]
workflow_dispatch:
jobs:
trivy-scan:
runs-on: ubuntu-latest
env:
VAPT_ARTIFACT_NAME: ${{ github.event.repository.name }}
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set Short SHA
run: echo "VAPT_ARTIFACT_VERSION=$(echo ${GITHUB_SHA} | cut -c1-7)" >> $GITHUB_ENV
- name: Setup Trivy
uses: aquasecurity/[email protected]
with:
cache: true
- name: Check Trivy Version
run: trivy --version
- name: Generate Inventory SBOM (CycloneDX)
run: |
trivy fs . \
--format cyclonedx \
--output sbom.json \
--scanners vuln
- name: Upload Artifacts to VAPT Insights
env:
VAPT_INSIGHTS_API_KEY: ${{ secrets.VAPT_INSIGHTS_API_KEY }}
run: |
echo "Uploading Inventory SBOM..."
curl -X POST "https://svc.vaptinsights.com/webhook/inventory-sbom" \
-H "X-API-Key: ${VAPT_INSIGHTS_API_KEY}" \
-H "X-Artifact-Name: ${VAPT_ARTIFACT_NAME}" \
-H "X-Artifact-Version: ${VAPT_ARTIFACT_VERSION}" \
-H "Content-Type: application/json" \
--data-binary @sbom.json3. Manual Monorepo and Nested Folder Setup
Use this setup when your repository contains one application inside a nested folder, or several independently deployed services:
my-repository/
├── ui/
├── sms-service/
└── api-service/The standard workflow uses trivy fs ., which scans the entire repository and uploads one combined SBOM. For service-level reports, scan each folder separately and give every service a unique artifact name.
Scan one nested application folder
If the repository contains a single application under a folder such as ui/, change the scan target and artifact name:
jobs:
trivy-scan:
runs-on: ubuntu-latest
env:
VAPT_ARTIFACT_NAME: ${{ github.event.repository.name }}/ui
VAPT_SERVICE_PATH: ui
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set Short SHA
run: echo "VAPT_ARTIFACT_VERSION=$(echo ${GITHUB_SHA} | cut -c1-7)" >> $GITHUB_ENV
- name: Setup Trivy
uses: aquasecurity/[email protected]
with:
cache: true
- name: Generate Inventory SBOM
run: |
trivy fs "${VAPT_SERVICE_PATH}" \
--format cyclonedx \
--output sbom.json \
--scanners vuln
- name: Upload Artifact to VAPT Insights
env:
VAPT_INSIGHTS_API_KEY: ${{ secrets.VAPT_INSIGHTS_API_KEY }}
run: |
curl --fail-with-body -X POST "https://svc.vaptinsights.com/webhook/inventory-sbom" \
-H "X-API-Key: ${VAPT_INSIGHTS_API_KEY}" \
-H "X-Artifact-Name: ${VAPT_ARTIFACT_NAME}" \
-H "X-Artifact-Version: ${VAPT_ARTIFACT_VERSION}" \
-H "Content-Type: application/json" \
--data-binary @sbom.jsonReplace ui with the path to your application, such as apps/web, services/payments, or backend/sms-service.
Scan multiple monorepo services
Use a matrix when several folders should appear as separate artifacts in VAPT Insights. Each matrix entry runs as an independent parallel job.
name: VAPT Insights Monorepo Security Scan
on:
push:
branches: [ main ]
workflow_dispatch:
jobs:
trivy-scan:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
service:
- name: ui
path: ui
- name: sms-service
path: sms-service
- name: api-service
path: api-service
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set Short SHA
run: echo "VAPT_ARTIFACT_VERSION=$(echo ${GITHUB_SHA} | cut -c1-7)" >> $GITHUB_ENV
- name: Setup Trivy
uses: aquasecurity/[email protected]
with:
cache: true
- name: Generate ${{ matrix.service.name }} SBOM
run: |
trivy fs "${{ matrix.service.path }}" \
--format cyclonedx \
--output "sbom-${{ matrix.service.name }}.json" \
--scanners vuln
- name: Upload ${{ matrix.service.name }} to VAPT Insights
env:
VAPT_INSIGHTS_API_KEY: ${{ secrets.VAPT_INSIGHTS_API_KEY }}
VAPT_ARTIFACT_NAME: ${{ github.event.repository.name }}/${{ matrix.service.name }}
run: |
curl --fail-with-body -X POST "https://svc.vaptinsights.com/webhook/inventory-sbom" \
-H "X-API-Key: ${VAPT_INSIGHTS_API_KEY}" \
-H "X-Artifact-Name: ${VAPT_ARTIFACT_NAME}" \
-H "X-Artifact-Version: ${VAPT_ARTIFACT_VERSION}" \
-H "Content-Type: application/json" \
--data-binary "@sbom-${{ matrix.service.name }}.json"This example creates three separate artifacts:
<repository-name>/ui<repository-name>/sms-service<repository-name>/api-service
Add or remove entries under matrix.service to match your repository. fail-fast: false ensures that a failed scan or upload for one service does not cancel the other service jobs.
Shared dependency files
Each scan is limited to its configured service folder. If dependencies are declared only in a shared root-level file, scan the repository root as one combined artifact or include the shared files in each service's build context before generating its SBOM.
🔍 Verifying the Integration
Once your pipeline runs:
- Go to your VAPT Insights Dashboard.
- Select your project and navigate to SBOM Reports.
- You should see a new scan report matching the timestamp and commit hash of your pipeline run.