Skip to content

feat(security): add comprehensive SBOM generation and integration#11

Merged
arunsanna merged 3 commits intomainfrom
feat/sbom-generation
Aug 27, 2025
Merged

feat(security): add comprehensive SBOM generation and integration#11
arunsanna merged 3 commits intomainfrom
feat/sbom-generation

Conversation

@arunsanna
Copy link
Contributor

Summary

  • Added comprehensive Software Bill of Materials (SBOM) generation workflow
  • Integrated SBOM generation into existing container and dependency security workflows
  • Updated security report to aggregate and analyze SBOM data

Changes

New Workflow: security-sbom.yml

  • sbom-source: Generates SBOMs for source code using Syft and cdxgen
  • sbom-containers: Creates SBOMs for Docker containers in multiple formats
  • sbom-vulnerability-scan: Scans all SBOMs with Grype for vulnerabilities
  • sbom-attestation: Creates SBOM attestation for main branch commits
  • sbom-publish: Publishes SBOMs as release assets

Updated Workflows

  • security-containers.yml: Added Syft SBOM generation alongside container scanning
  • security-dependencies.yml: Integrated CycloneDX SBOM generation for npm dependencies
  • security-report.yml: Added SBOM analysis section and supply chain tracking

SBOM Formats Supported

  • SPDX 2.3 JSON
  • CycloneDX 1.5 JSON/XML
  • Syft native JSON
  • NPM dependency trees
  • License compliance tracking

Testing

All workflows include:

  • Error handling with continue-on-error: true
  • Multiple format generation
  • Vulnerability correlation
  • Artifact uploads for all SBOMs

Benefits

  • Complete software supply chain transparency
  • Multi-format SBOM support for different tools
  • Automated vulnerability scanning of all components
  • License compliance tracking
  • Release asset publishing for SBOMs

- Add dedicated security-sbom.yml workflow for multi-format SBOM generation
- Generate SBOMs in SPDX, CycloneDX, and Syft formats
- Integrate Syft SBOM generation into container security workflow
- Add CycloneDX SBOM generation to dependency workflow
- Include SBOM vulnerability scanning with Grype
- Add license compliance tracking
- Update security report to aggregate SBOM data
- Support SBOM attestation for main branch pushes
- Publish SBOMs as release assets
Copilot AI review requested due to automatic review settings August 26, 2025 22:30
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds comprehensive Software Bill of Materials (SBOM) generation and vulnerability scanning capabilities to the security workflow infrastructure. The implementation creates a dedicated SBOM workflow while integrating SBOM generation into existing container and dependency security workflows.

  • Implements comprehensive SBOM generation using multiple tools (Syft, cdxgen, CycloneDX) with support for various formats (SPDX, CycloneDX, Syft native)
  • Integrates vulnerability scanning of SBOMs using Grype and adds SBOM attestation for supply chain security
  • Updates existing security workflows to include SBOM generation and enhances security reporting with supply chain tracking

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
.github/workflows/security-sbom.yml New comprehensive SBOM workflow with source code, container, and vulnerability scanning jobs
.github/workflows/security-report.yml Added SBOM analysis section to aggregate and display supply chain information
.github/workflows/security-dependencies.yml Integrated CycloneDX SBOM generation for npm dependencies
.github/workflows/security-containers.yml Added Syft SBOM generation alongside existing container scanning

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +324 to +336
find . -name "vuln-*.json" | while read vuln_file; do
if [ -f "$vuln_file" ]; then
CRITICAL=$(jq '[.matches[] | select(.vulnerability.severity == "Critical")] | length' $vuln_file 2>/dev/null || echo "0")
HIGH=$(jq '[.matches[] | select(.vulnerability.severity == "High")] | length' $vuln_file 2>/dev/null || echo "0")
MEDIUM=$(jq '[.matches[] | select(.vulnerability.severity == "Medium")] | length' $vuln_file 2>/dev/null || echo "0")
LOW=$(jq '[.matches[] | select(.vulnerability.severity == "Low")] | length' $vuln_file 2>/dev/null || echo "0")

TOTAL_CRITICAL=$((TOTAL_CRITICAL + CRITICAL))
TOTAL_HIGH=$((TOTAL_HIGH + HIGH))
TOTAL_MEDIUM=$((TOTAL_MEDIUM + MEDIUM))
TOTAL_LOW=$((TOTAL_LOW + LOW))
fi
done
Copy link

Copilot AI Aug 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variables TOTAL_CRITICAL, TOTAL_HIGH, TOTAL_MEDIUM, and TOTAL_LOW are modified inside a subshell created by the pipe to while read. These changes won't persist outside the loop, so the totals will always remain 0. Use process substitution instead: while read vuln_file; do ... done < <(find . -name \"vuln-*.json\")

Suggested change
find . -name "vuln-*.json" | while read vuln_file; do
if [ -f "$vuln_file" ]; then
CRITICAL=$(jq '[.matches[] | select(.vulnerability.severity == "Critical")] | length' $vuln_file 2>/dev/null || echo "0")
HIGH=$(jq '[.matches[] | select(.vulnerability.severity == "High")] | length' $vuln_file 2>/dev/null || echo "0")
MEDIUM=$(jq '[.matches[] | select(.vulnerability.severity == "Medium")] | length' $vuln_file 2>/dev/null || echo "0")
LOW=$(jq '[.matches[] | select(.vulnerability.severity == "Low")] | length' $vuln_file 2>/dev/null || echo "0")
TOTAL_CRITICAL=$((TOTAL_CRITICAL + CRITICAL))
TOTAL_HIGH=$((TOTAL_HIGH + HIGH))
TOTAL_MEDIUM=$((TOTAL_MEDIUM + MEDIUM))
TOTAL_LOW=$((TOTAL_LOW + LOW))
fi
done
done < <(find . -name "vuln-*.json")

Copilot uses AI. Check for mistakes.
Comment on lines +208 to +215
echo "Build failed, creating minimal image..."
cat > Dockerfile.minimal << EOF
FROM node:18-alpine
WORKDIR /app
COPY ${{ matrix.service }}/package*.json ./
RUN npm ci --only=production || npm install --production || echo "Install failed"
EOF
docker build -t connectkit-${{ matrix.service }}:sbom -f Dockerfile.minimal .
Copy link

Copilot AI Aug 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fallback Docker build strategy assumes a specific project structure and Node.js setup that may not match the actual project. Consider validating the existence of package.json files before attempting the fallback build, or make the fallback more generic to handle different project types.

Suggested change
echo "Build failed, creating minimal image..."
cat > Dockerfile.minimal << EOF
FROM node:18-alpine
WORKDIR /app
COPY ${{ matrix.service }}/package*.json ./
RUN npm ci --only=production || npm install --production || echo "Install failed"
EOF
docker build -t connectkit-${{ matrix.service }}:sbom -f Dockerfile.minimal .
echo "Build failed, checking for Node.js project files..."
if ls ${{ matrix.service }}/package*.json 1> /dev/null 2>&1; then
echo "Node.js project detected, creating minimal Node.js image..."
cat > Dockerfile.minimal << EOF
FROM node:18-alpine
WORKDIR /app
COPY ${{ matrix.service }}/package*.json ./
RUN npm ci --only=production || npm install --production || echo "Install failed"
EOF
docker build -t connectkit-${{ matrix.service }}:sbom -f Dockerfile.minimal .
else
echo "No package.json found, creating generic minimal image..."
cat > Dockerfile.minimal << EOF
FROM alpine:3.18
WORKDIR /app
COPY ${{ matrix.service }} .
EOF
docker build -t connectkit-${{ matrix.service }}:sbom -f Dockerfile.minimal .
fi

Copilot uses AI. Check for mistakes.
Comment on lines +215 to +218
TOTAL_COMPONENTS=$((TOTAL_COMPONENTS + COMPONENTS))
fi
done

Copy link

Copilot AI Aug 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the previous vulnerability counting issue, the TOTAL_COMPONENTS variable is being modified inside a subshell created by the for loop with glob expansion. The changes won't persist outside the loop. Use an array or process substitution approach to properly accumulate the component counts.

Suggested change
TOTAL_COMPONENTS=$((TOTAL_COMPONENTS + COMPONENTS))
fi
done
COMPONENT_COUNTS+=("$COMPONENTS")
fi
done
TOTAL_COMPONENTS=0
for count in "${COMPONENT_COUNTS[@]}"; do
TOTAL_COMPONENTS=$((TOTAL_COMPONENTS + count))
done

Copilot uses AI. Check for mistakes.
- Add Node.js version check before cdxgen installation
- Skip cdxgen on Node 18, use alternative CycloneDX npm tool
- Ensure workflow continues even if cdxgen is incompatible
- Add fallback for environments with Node.js < 20
- Remove archived/accessibility.yml (now active)
- Remove archived/ci.yml (replaced with separate workflows)
- Remove archived/compliance-federal.yml (not needed)
- Remove archived/nightly.yml (not needed)
- Remove archived/performance.yml (not needed)
- Remove archived/security.yml (replaced with multiple security workflows)
- Clean up repository by removing unused workflow files
@arunsanna arunsanna merged commit c4b359c into main Aug 27, 2025
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant