SBOM

SBOM API Integration Patterns for Development Teams

SBOMs locked in files are static inventory. SBOMs exposed through APIs become live infrastructure. Here's how to build the integration layer.

Bob
Platform Engineer
5 min read

An SBOM sitting in an S3 bucket is a compliance artifact. An SBOM exposed through APIs -- queryable, searchable, correlated with vulnerability data in real time -- is operational infrastructure. The difference between the two is integration.

Most SBOM tooling focuses on generation. This guide focuses on what comes after: the API patterns that turn SBOMs from static documents into live components of your security workflow.

Core API Patterns

Pattern 1: Upload and Ingest

The foundational pattern. Every SBOM needs to get from the build pipeline into a central store.

# Simple upload endpoint
curl -X POST https://sbom-api.internal/v1/sboms \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -F "project=myapp" \
  -F "version=1.2.3" \
  -F "environment=production" \
  -F "commit_sha=abc123" \
  -F "file=@sbom.cdx.json"

The API should:

  • Validate the SBOM format and schema
  • Extract and index component data for search
  • Trigger asynchronous vulnerability matching
  • Return immediately with a reference ID
{
  "id": "sbom-uuid-here",
  "status": "processing",
  "project": "myapp",
  "version": "1.2.3",
  "component_count": 342,
  "vulnerability_scan": "pending",
  "url": "/v1/sboms/sbom-uuid-here"
}

Pattern 2: Component Search

The most valuable query pattern during incident response: "which of our projects use this component?"

# Find all projects affected by a vulnerable component
curl "https://sbom-api.internal/v1/components/search?name=log4j-core&version_lt=2.17.1"

Response:

{
  "results": [
    {
      "project": "order-service",
      "version": "3.4.1",
      "component_version": "2.14.0",
      "environment": "production",
      "deployed": true
    },
    {
      "project": "notification-service",
      "version": "2.1.0",
      "component_version": "2.16.0",
      "environment": "staging",
      "deployed": false
    }
  ],
  "total": 2
}

This query needs to be fast. When Log4Shell hits, "we'll get back to you in an hour" isn't acceptable.

Pattern 3: Vulnerability Correlation

Match SBOM components against vulnerability databases and return the results through the API:

# Get vulnerabilities for a specific SBOM
curl "https://sbom-api.internal/v1/sboms/sbom-uuid-here/vulnerabilities"
{
  "sbom_id": "sbom-uuid-here",
  "project": "myapp",
  "version": "1.2.3",
  "vulnerabilities": [
    {
      "id": "CVE-2023-44487",
      "severity": "high",
      "cvss": 7.5,
      "affected_component": {
        "name": "nghttp2",
        "version": "1.51.0",
        "purl": "pkg:apk/alpine/nghttp2@1.51.0"
      },
      "fixed_version": "1.57.0",
      "status": "open"
    }
  ],
  "summary": {
    "critical": 0,
    "high": 3,
    "medium": 12,
    "low": 8
  }
}

Pattern 4: Policy Enforcement

Expose policy checks as an API that CI/CD pipelines call before deployment:

# Check if an SBOM passes policy
curl -X POST "https://sbom-api.internal/v1/policy/evaluate" \
  -H "Content-Type: application/json" \
  -d '{
    "sbom_id": "sbom-uuid-here",
    "policy": "production-deployment"
  }'
{
  "result": "fail",
  "violations": [
    {
      "rule": "no-critical-cves",
      "message": "Component nghttp2@1.51.0 has 1 critical CVE",
      "severity": "critical"
    },
    {
      "rule": "no-copyleft-licenses",
      "message": "Component readline@8.2 uses GPL-3.0",
      "severity": "warning"
    }
  ]
}

The CI/CD pipeline uses the response to gate deployments:

- name: Check SBOM Policy
  run: |
    RESULT=$(curl -s -X POST https://sbom-api.internal/v1/policy/evaluate \
      -H "Authorization: Bearer $TOKEN" \
      -d '{"sbom_id": "'$SBOM_ID'", "policy": "production-deployment"}')
    
    if [ "$(echo $RESULT | jq -r '.result')" = "fail" ]; then
      echo "Policy check failed:"
      echo $RESULT | jq '.violations[]'
      exit 1
    fi

Webhook Integrations

Push-based notifications complement pull-based APIs:

New Vulnerability Discovered

When a new CVE is published that affects a component in your SBOMs:

{
  "event": "vulnerability.discovered",
  "timestamp": "2024-01-25T14:30:00Z",
  "vulnerability": {
    "id": "CVE-2024-XXXX",
    "severity": "critical",
    "cvss": 9.8
  },
  "affected_projects": [
    {
      "project": "myapp",
      "version": "1.2.3",
      "component": "libexpat@2.5.0",
      "environment": "production"
    }
  ]
}

Route this webhook to:

  • Slack/Teams for immediate team notification
  • Jira/Linear to create a remediation ticket automatically
  • PagerDuty for critical-severity vulnerabilities in production

SBOM Drift Detected

When a new SBOM differs significantly from the previous version:

{
  "event": "sbom.drift",
  "timestamp": "2024-01-25T15:00:00Z",
  "project": "myapp",
  "previous_version": "1.2.2",
  "current_version": "1.2.3",
  "changes": {
    "added": 5,
    "removed": 2,
    "updated": 8,
    "notable": [
      {
        "component": "openssl",
        "from": "3.0.8",
        "to": "3.1.4",
        "reason": "security update"
      }
    ]
  }
}

CI/CD Integration Examples

GitHub Actions

name: SBOM Pipeline
on:
  push:
    branches: [main]

jobs:
  sbom:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Build
        run: docker build -t myapp:${{ github.sha }} .

      - name: Generate SBOM
        run: |
          syft myapp:${{ github.sha }} -o cyclonedx-json > sbom.json

      - name: Upload SBOM
        id: upload
        run: |
          RESPONSE=$(curl -s -X POST https://sbom-api.example.com/v1/sboms \
            -H "Authorization: Bearer ${{ secrets.SBOM_TOKEN }}" \
            -F "project=myapp" \
            -F "version=${{ github.sha }}" \
            -F "file=@sbom.json")
          echo "sbom_id=$(echo $RESPONSE | jq -r '.id')" >> $GITHUB_OUTPUT

      - name: Policy Check
        run: |
          RESULT=$(curl -s -X POST https://sbom-api.example.com/v1/policy/evaluate \
            -H "Authorization: Bearer ${{ secrets.SBOM_TOKEN }}" \
            -d '{"sbom_id": "${{ steps.upload.outputs.sbom_id }}", "policy": "default"}')
          
          if [ "$(echo $RESULT | jq -r '.result')" = "fail" ]; then
            echo "::error::SBOM policy check failed"
            echo $RESULT | jq '.violations[]'
            exit 1
          fi

Jenkins

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                sh 'docker build -t myapp:${BUILD_NUMBER} .'
            }
        }
        stage('SBOM') {
            steps {
                sh 'syft myapp:${BUILD_NUMBER} -o cyclonedx-json > sbom.json'
                
                script {
                    def response = sh(
                        script: """curl -s -X POST https://sbom-api.internal/v1/sboms \
                            -H "Authorization: Bearer ${SBOM_TOKEN}" \
                            -F "project=myapp" \
                            -F "version=${BUILD_NUMBER}" \
                            -F "file=@sbom.json" """,
                        returnStdout: true
                    )
                    def sbomId = readJSON(text: response).id
                    env.SBOM_ID = sbomId
                }
            }
        }
        stage('Policy Gate') {
            steps {
                script {
                    def result = sh(
                        script: """curl -s -X POST https://sbom-api.internal/v1/policy/evaluate \
                            -d '{"sbom_id": "${SBOM_ID}", "policy": "production"}' """,
                        returnStdout: true
                    )
                    if (readJSON(text: result).result == 'fail') {
                        error("SBOM policy check failed")
                    }
                }
            }
        }
    }
}

Aggregation and Reporting APIs

Beyond individual SBOM operations, aggregation endpoints drive executive reporting:

# Organization-wide vulnerability summary
curl "https://sbom-api.internal/v1/reports/vulnerability-summary"

# Response
{
  "total_projects": 85,
  "total_components": 12450,
  "unique_components": 3200,
  "vulnerabilities": {
    "critical": 12,
    "high": 45,
    "medium": 230,
    "low": 510
  },
  "mean_time_to_remediate_days": 14.5,
  "oldest_unpatched_critical": "2023-11-15"
}

How Safeguard.sh Helps

Safeguard exposes all of these patterns through its API and CI/CD integrations out of the box. Upload SBOMs from any pipeline, query components across your entire portfolio, get real-time vulnerability correlation, and enforce policies before deployment -- all through documented APIs and native integrations with GitHub Actions, GitLab CI, and Jenkins. Webhooks push alerts to Slack, Jira, and PagerDuty when new vulnerabilities affect your deployed software. The platform handles the infrastructure so your team focuses on remediation, not plumbing.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.