VVAPT Insights
Integrations

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:

  1. 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.
  2. Saved it as a secret named VAPT_INSIGHTS_API_KEY in your GitHub repository configurations.

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:

InputRequiredDefaultDescription
api-keyYes—VAPT Insights API key stored in GitHub Actions secrets.
artifact-nameYes—Artifact name displayed in VAPT Insights.
scan-pathNo.Repository folder to scan.
artifact-versionNoShort commit SHAVersion 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-service

Scan 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.json

3. 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.json

Replace 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:

  1. Go to your VAPT Insights Dashboard.
  2. Select your project and navigate to SBOM Reports.
  3. You should see a new scan report matching the timestamp and commit hash of your pipeline run.

On this page