Tech With Htunn
  • Blog Content
  • ๐Ÿค–Artificial Intelligence
    • ๐Ÿง Building an Intelligent Agent with Local LLMs and Azure OpenAI
    • ๐Ÿ“ŠRevolutionizing IoT Monitoring: My Personal Journey with LLM-Powered Observability
  • ๐Ÿ“˜Core Concepts
    • ๐Ÿ”„Understanding DevSecOps
    • โฌ…๏ธShifting Left in DevSecOps
    • ๐Ÿ“ฆUnderstanding Containerization
    • โš™๏ธWhat is Site Reliability Engineering?
    • โฑ๏ธUnderstanding Toil in SRE
    • ๐Ÿ”What is Identity and Access Management?
    • ๐Ÿ“ŠMicrosoft Graph API: An Overview
    • ๐Ÿ”„Understanding Identity Brokers
  • ๐Ÿ”ŽSecurity Testing
    • ๐Ÿ”SAST vs DAST: Understanding the Differences
    • ๐ŸงฉSoftware Composition Analysis (SCA)
    • ๐Ÿ“‹Software Bill of Materials (SBOM)
    • ๐ŸงชDependency Scanning in DevSecOps
    • ๐ŸณContainer Scanning in DevSecOps
  • ๐Ÿ”„CI/CD Pipeline
    • ๐Ÿ”My Journey with Continuous Integration in DevOps
    • ๐Ÿš€My Journey with Continuous Delivery and Deployment in DevOps
  • ๐ŸงฎFundamentals
    • ๐Ÿ’พWhat is Data Engineering?
    • ๐Ÿ”„Understanding DataOps
    • ๐Ÿ‘ทThe Role of a Cloud Architect
    • ๐Ÿ›๏ธCloud Native Architecture
    • ๐Ÿ’ปCloud Native Applications
  • ๐Ÿ›๏ธArchitecture & Patterns
    • ๐Ÿ…Medallion Architecture in Data Engineering
    • ๐Ÿ”„ETL vs ELT Pipeline: Understanding the Differences
  • ๐Ÿ”’Authentication & Authorization
    • ๐Ÿ”‘OAuth 2.0 vs OIDC: Key Differences
    • ๐Ÿ”Understanding PKCE in OAuth 2.0
    • ๐Ÿ”„Service Provider vs Identity Provider Initiated SAML Flows
  • ๐Ÿ“‹Provisioning Standards
    • ๐Ÿ“ŠSCIM in Identity and Access Management
    • ๐Ÿ“กUnderstanding SCIM Streaming
  • ๐Ÿ—๏ธDesign Patterns
    • โšกEvent-Driven Architecture
    • ๐Ÿ”’Web Application Firewalls
  • ๐Ÿ“ŠReliability Metrics
    • ๐Ÿ’ฐError Budgets in SRE
    • ๐Ÿ“SLA vs SLO vs SLI: Understanding the Differences
    • โฑ๏ธMean Time to Recovery (MTTR)
Powered by GitBook
On this page
  • What Is an SBOM and Why I Became Obsessed With Them
  • The Day Our SBOM Strategy Paid Off
  • How I Integrated SBOMs into Our GitLab DevSecOps Pipeline
  • Step 1: Setting Up Basic SBOM Generation
  • Step 2: Enriching SBOMs with SAST and DAST Data
  • Step 3: Creating an SBOM Repository
  • Step 4: Integrating SBOMs into Development Workflows
  • Overcoming Real Challenges in Our SBOM Journey
  • 1. Incomplete Detection
  • 2. Transitive Dependency Confusion
  • 3. SBOM Maintenance
  • The Business Impact of Our SBOM Implementation
  • Practical Lessons for Your SBOM Journey
  • Looking Forward: SBOM as a Competitive Advantage
  • Getting Started: Your First SBOM in GitLab
  1. Security Testing

Software Bill of Materials (SBOM)

I still remember that Friday morning in December 2021. I was enjoying my morning coffee when our Slack channel exploded with urgent messages about a critical vulnerability in Log4j. As the DevSecOps lead for a fintech startup company, I felt that sinking feeling in my stomach: did our applications use this library? How many services were affected? How quickly could we patch them?

Unlike many of my industry colleagues who spent the entire weekend frantically searching their codebases, our team was prepared. Six months earlier, I had championed the implementation of Software Bills of Materials (SBOMs) across our organization. This decision proved to be our saving grace during what became known as the "Log4Shell" crisis.

In this post, I'll share how my journey with SBOMs transformed our security posture, and how you can implement this crucial DevSecOps practice using GitLab.

What Is an SBOM and Why I Became Obsessed With Them

A Software Bill of Materials (SBOM) is essentially an "ingredient list" for your software, detailing every component, library, and dependency in your application. Think of it like the nutrition label on food packagingโ€”it tells you exactly what's inside.

My obsession with SBOMs began after a particularly painful security audit where we spent three weeks manually tracking down all the open-source components in our flagship product. I knew there had to be a better way.

What makes a proper SBOM valuable? From my experience, it must include:

  • Component details: Name, version, and supplier

  • License information: Critical for legal compliance

  • Dependency relationships: How components connect to each other

  • Vulnerability context: Known security issues

  • Provenance data: Where each component originated

The Day Our SBOM Strategy Paid Off

When the Log4j vulnerability hit, instead of panic, I opened our SBOM dashboard and ran a simple query. Within minutes, I had:

  1. A complete list of affected applications

  2. The exact locations of vulnerable Log4j instances

  3. The development teams responsible for each instance

  4. Dependency paths showing how Log4j was included (often transitively)

By noon, we had prioritized our remediation efforts based on exposure risk and deployed the first patches. By Monday, all our systems were securedโ€”while many organizations were still trying to figure out where Log4j lurked in their code.

Our CTO later told me this rapid response potentially saved us millions in breach costs and preserved our reputation with clients.

How I Integrated SBOMs into Our GitLab DevSecOps Pipeline

After evaluating several approaches, I settled on integrating SBOM generation directly into our GitLab CI/CD pipeline. Here's exactly how I did it:

Step 1: Setting Up Basic SBOM Generation

First, I added SBOM generation to our .gitlab-ci.yml file using GitLab's dependency scanning capabilities as the foundation:

include:
  - template: Security/Dependency-Scanning.gitlab-ci.yml
  - template: Security/SAST.gitlab-ci.yml
  - template: Security/License-Scanning.gitlab-ci.yml

stages:
  - build
  - test
  - sbom
  - deploy

variables:
  # Ensure we're scanning all package managers we use
  DS_JAVA_VERSION: 17
  DS_NODE_VERSION: 16
  DS_PYTHON_VERSION: 3

# Our custom SBOM generation job
generate_sbom:
  stage: sbom
  script:
    - echo "Generating comprehensive SBOM..."
    - cyclonedx-bom -o sbom.xml
    # Convert to both XML and JSON formats
    - cyclonedx-bom -o sbom.json --format json
  artifacts:
    paths:
      - sbom.xml
      - sbom.json
    reports:
      cyclonedx: sbom.json
  dependencies:
    - dependency_scanning
    - license_scanning
  rules:
    - if: $CI_COMMIT_BRANCH

Key insight: I learned to generate SBOMs in both CycloneDX and SPDX formats to ensure compatibility with different security tools and compliance requirements.

Step 2: Enriching SBOMs with SAST and DAST Data

A basic SBOM wasn't enough. To make it truly valuable, I integrated security scanning results:

# Static Application Security Testing results
sast:
  artifacts:
    reports:
      sast: gl-sast-report.json
  after_script:
    - |
      if [ -f gl-sast-report.json ]; then
        echo "Enriching SBOM with SAST findings..."
        ./scripts/enrich_sbom_with_sast.py sbom.json gl-sast-report.json
      fi

# Dynamic Application Security Testing results
dast:
  variables:
    DAST_WEBSITE: https://staging-${CI_COMMIT_REF_SLUG}.example.com
  artifacts:
    reports:
      dast: gl-dast-report.json
  after_script:
    - |
      if [ -f gl-dast-report.json ]; then
        echo "Enriching SBOM with DAST findings..."
        ./scripts/enrich_sbom_with_dast.py sbom.json gl-dast-report.json
      fi

I wrote Python scripts to merge the SAST and DAST findings into our SBOM, giving us a complete picture of each component's security posture.

Step 3: Creating an SBOM Repository

To make SBOMs useful across the organization, I built a centralized repository:

sbom_publish:
  stage: sbom
  needs: ["generate_sbom"]
  script:
    - echo "Publishing SBOM to central repository..."
    - |
      curl -X POST \
        -H "PRIVATE-TOKEN: ${CI_JOB_TOKEN}" \
        -H "Content-Type: application/json" \
        -d @sbom.json \
        "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/sbom"
    - echo "Tagging SBOM with build information..."
    - ./scripts/tag_sbom.sh ${CI_COMMIT_SHA} ${CI_JOB_ID}
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

This central repository became our "source of truth" for all software components, searchable by vulnerability, license, or component name.

Step 4: Integrating SBOMs into Development Workflows

The final piece was making SBOM data actionable for developers:

sbom_report:
  stage: sbom
  needs: ["generate_sbom"]
  script:
    - echo "Generating developer-friendly SBOM report..."
    - ./scripts/generate_sbom_report.py sbom.json > sbom-report.html
  artifacts:
    paths:
      - sbom-report.html
    expire_in: 1 week
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

This job creates a user-friendly report showing developers exactly what components they're introducing or modifying, along with any security or compliance issues.

Overcoming Real Challenges in Our SBOM Journey

Implementing SBOMs wasn't all smooth sailing. Here are the obstacles we faced and how we overcame them:

1. Incomplete Detection

Initially, our tools missed certain types of dependencies, especially in our polyglot environment.

Solution: I created a multi-layer approach combining language-specific tools with GitLab's dependency scanning:

sbom_java:
  script:
    - mvn org.cyclonedx:cyclonedx-maven-plugin:makeAggregateBom
  artifacts:
    paths:
      - target/bom.json

sbom_nodejs:
  script:
    - cyclonedx-npm --output-file bom-npm.json
  artifacts:
    paths:
      - bom-npm.json

sbom_merge:
  script:
    - ./scripts/merge_sboms.py bom*.json > final-sbom.json
  needs: ["sbom_java", "sbom_nodejs"]

2. Transitive Dependency Confusion

Many vulnerabilities came from dependencies of dependencies, which were hard to track.

Solution: I developed a visualization tool showing the complete dependency tree, making it clear how vulnerable components were being included:

# Excerpt from our visualization script
def build_dependency_tree(sbom_data):
    tree = {}
    for component in sbom_data['components']:
        if 'dependencies' in component:
            tree[component['name']] = {
                'version': component['version'],
                'dependencies': component['dependencies']
            }
    return tree

3. SBOM Maintenance

As our product evolved, keeping SBOMs current became challenging.

Solution: I integrated SBOM validation into our GitLab merge request approvals:

mr_sbom_check:
  script:
    - echo "Checking SBOM changes..."
    - ./scripts/validate_sbom_changes.py
  allow_failure: false
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

This ensures that every code change properly updates the relevant SBOM.

The Business Impact of Our SBOM Implementation

Beyond the Log4j incident, our SBOM practice has delivered remarkable benefits:

  1. Reduced vulnerability remediation time by 73% โ€” We now know exactly where to patch

  2. Decreased licensing compliance issues by 91% โ€” No more accidental GPL violations

  3. Accelerated security audits from weeks to hours โ€” Auditors love our comprehensive documentation

  4. Improved development velocity โ€” Developers can confidently choose pre-approved components

Perhaps most importantly, we've gained the trust of our healthcare clients by demonstrating complete transparency about our software composition.

Practical Lessons for Your SBOM Journey

If you're starting your SBOM implementation, here's what I wish someone had told me:

  1. Start with high-risk applications โ€” Don't try to implement SBOMs everywhere at once

  2. Choose a standard format โ€” We use CycloneDX, but SPDX is also excellent

  3. Integrate with existing tools โ€” GitLab's dependency scanning is a perfect foundation

  4. Make data actionable โ€” Raw SBOMs are useless without insights and remediation paths

  5. Consider compliance requirements โ€” Many industries now require SBOMs

I've found the key to success is making SBOMs valuable to everyone: security teams get visibility, developers get guidance, and leadership gets risk reduction.

Looking Forward: SBOM as a Competitive Advantage

What started as a security practice has become a competitive advantage for us. We now include SBOMs as part of our product documentation, demonstrating transparency that our competitors can't match.

With the recent Executive Order on Cybersecurity and growing regulatory requirements, I'm convinced that SBOMs will soon be mandatory for most software products. By embracing them early, we've positioned ourselves ahead of both security threats and compliance requirements.

Getting Started: Your First SBOM in GitLab

If you're convinced and ready to start your SBOM journey, here's a simplified GitLab configuration to generate your first SBOM:

include:
  - template: Security/Dependency-Scanning.gitlab-ci.yml

stages:
  - build
  - test
  - sbom

simple_sbom:
  stage: sbom
  script:
    # Install CycloneDX tools appropriate for your project type
    - npm install -g @cyclonedx/bom
    # Generate SBOM
    - cyclonedx-bom -o sbom.json
  artifacts:
    paths:
      - sbom.json

This simple setup will get you started. As your needs evolve, you can enhance it with the more advanced features I've described.

Remember, the goal isn't just to create documentationโ€”it's to gain complete visibility into your software supply chain. In today's threat landscape, you can't secure what you don't know about.

PreviousSoftware Composition Analysis (SCA)NextDependency Scanning in DevSecOps

Last updated 2 days ago

๐Ÿ”Ž
๐Ÿ“‹