Software Composition Analysis (SCA)
What is SCA?
SCA is a method for analyzing open-source components included in software to detect known vulnerabilities (CVEs). It tracks the full dependency graph based on an SBOM and enables immediate response when new CVEs are discovered. What an SBOM is is covered in SBOM Basics.
The YAML and commands on this page are examples that show the essentials. For a complete, copy-and-run pipeline (including policy files and a sample app), see the Best Practice repository.
SBOM Generation — syft
Basic Usage
# CycloneDX JSON generation (recommended)
syft . -o cyclonedx-json=sbom.cdx.json
# Generate SPDX JSON
syft . -o spdx-json=sbom.spdx.json
# Analyze a container image
syft nginx:latest -o cyclonedx-json=sbom.cdx.json
Format Selection
| Format | Steward | Recommended Use |
|---|---|---|
| CycloneDX JSON | OWASP | Security and vulnerability management (grype integration) |
| SPDX JSON | Linux Foundation | Supply chain sharing and regulatory response |
For security pipeline-centric workflows, CycloneDX JSON is recommended.
cdxgen
An alternative generator, from the CycloneDX project itself. Where syft reads what is on disk, cdxgen resolves through each language's own package manager, so it can recover dependencies a file-based scan does not see — which matters when a lockfile is absent or the tree is only fixed at build time. It covers more than 30 ecosystems and emits CycloneDX directly.
# CycloneDX JSON for the current project
npx @cyclonedx/cdxgen@latest -o sbom.cdx.json
TRUSCA uses cdxgen as its generator. Which one to choose comes down to whether your build resolves dependencies at install time (syft is enough) or at build time (cdxgen recovers what syft loses).
Vulnerability Scanning — grype
Full GitHub Actions Workflow
# .github/workflows/sca.yml
name: SCA — SBOM & Vulnerability Scan
on:
pull_request:
branches: [main, develop]
jobs:
sca:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Generate SBOM
uses: anchore/sbom-action@v0
with:
format: cyclonedx-json
output-file: sbom.cdx.json
- name: Scan vulnerabilities
uses: anchore/scan-action@v7
with:
sbom: sbom.cdx.json
fail-build: true
severity-cutoff: high
config: .grype.yaml
- name: Upload SBOM artifact
uses: actions/upload-artifact@v7
with:
name: sbom-${{ github.sha }}
path: sbom.cdx.json
retention-days: 90
GitLab CI
# .gitlab-ci.yml (sca job section)
sca:
stage: test
image: ubuntu:22.04
script:
# The base ubuntu image does not include curl
- apt-get update -qq && apt-get install -y -qq curl ca-certificates
- curl -sSfL https://get.anchore.io/syft
| sh -s -- -b /usr/local/bin
- curl -sSfL https://get.anchore.io/grype
| sh -s -- -b /usr/local/bin
- syft . -o cyclonedx-json=sbom.cdx.json
- grype sbom:sbom.cdx.json --fail-on high --config .grype.yaml
artifacts:
paths:
- sbom.cdx.json
expire_in: 90 days
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
sbom format not recognizedsyft 1.51 and newer emit CycloneDX 1.7, which only grype 0.118 and newer can read.
Upgrade both tools together, or generate at the older version with syft ... -o cyclonedx-json@1.6.
How this differs from the cicd-quick workflow
AI Coding — Quick CI/CD in 30 minutes carries a workflow of the same shape. If you already applied that one, adding the three items below turns it into what this page describes.
| Item | Quick CI/CD | This page |
|---|---|---|
| Artifact retention | Default (may be under 90 days) | retention-days: 90 and expire_in 90d |
| Scan policy file | None | .grype.yaml for exception handling |
| Prohibited license check | Shell script grepping the SBOM | None (licenses move to a policy gate) |
Quick CI/CD exists to stand up a first gate in 30 minutes; this page goes on to exception handling and evidence retention. Keep one of the two workflows, not both.
Vulnerability Policy Design
Severity-Based SLA
The table below is an example of a hardened, organization-level SLA tuned for CI gates. For the KWG baseline (Critical 1 week, High 4 weeks) and the canonical response deadlines, see Vulnerability response deadlines and VEX.
| Severity | CVSS Range | Hardened SLA Example | Build Block |
|---|---|---|---|
| Critical | 9.0–10.0 | 24 hours | Block |
| High | 7.0–8.9 | 7 days | Block |
| Medium | 4.0–6.9 | 30 days | Warning only |
| Low | 0.1–3.9 | Next release | Ignore |
At initial adoption, it is recommended to block only Critical issues, then expand to High after the team is accustomed.
grype Policy File
For audit response, exceptions without evidence can become a compliance risk.
# .grype.yaml
fail-on-severity: high
ignore:
# not used in actual code paths — security team approved 2024-01-15
- vulnerability: CVE-2023-XXXXX
reason: 'confirmed function not used'
# test-only package
- package:
name: some-test-lib
type: npm
Trivy
An alternative scanner, from Aqua Security. It ships a single database that merges NVD, OSV, GHSA, EPSS and KEV, so exploit probability and known-exploited status arrive with the finding rather than from a second lookup. It also scans container images and IaC, not only SBOM files.
# Scan an SBOM you already have
trivy sbom sbom.cdx.json
# Or scan the project directly
trivy fs --scanners vuln,license .
TRUSCA uses Trivy as its matching engine, which is why its findings carry EPSS and KEV alongside CVSS.
Developer workstations belong in scanning scope
Everything above targeted repositories and container images. There is one more path code arrives through: the extensions a developer installs in an IDE. Extensions run with developer privileges and reach source and credentials, yet they never appear in package.json or a lockfile, so the SCA results above never show them.
- GlassWorm spread through the Open VSX marketplace in 2025-10 with 35,800 installs and returned in a second wave in 2025-11. In 2026-03 a variant delivered through transitive dependencies affected 72 extensions, including ones impersonating Claude Code and Codex.
- MaliciousCorgi posed as AI extensions on the VS Code marketplace and affected roughly 1.5 million developers in 2026-01.
- Fifteen malicious AI plugins were confirmed on the JetBrains marketplace in 2026-06.
Three controls go together in practice: enforce an extension allowlist through organization policy, re-check the installed list on a schedule, and verify the publisher and linked repository before installing. The same controls extended to MCP servers and agent skills are in the tool and extension supply chain section of Agent and MCP Tool Governance.
The publish path and the install path are attack surfaces too
The scans above inspect packages that have already arrived. Attacks also happen on either side of that: the publish path, where a package is uploaded to a registry, and the install path, where a downloaded package runs scripts during installation.
Publishing: trusted publishing instead of long-lived tokens
If a maintainer's npm token leaks, malicious code ships as a new version of a legitimate package. Many of the npm supply chain attacks since the second half of 2025 took that route. npm has since tightened its token policy and retired classic tokens; the official documentation now states that only granular access tokens are supported (as of 2025-11).
The alternative is trusted publishing. The CI workflow proves its identity to the registry over
OIDC and publishes with a short-lived credential issued on the spot, so no long-lived token has to
sit in repository secrets. Published packages also carry a provenance attestation recording which
workflow produced them, generated automatically without the --provenance flag. It currently works
on the cloud runners of GitHub Actions, GitLab CI/CD and CircleCI; self-hosted runners are not
supported yet. PyPI and RubyGems offer the same mechanism.
# .github/workflows/publish.yml - npm trusted publishing
jobs:
publish:
runs-on: ubuntu-latest
permissions:
id-token: write # required to mint the OIDC token
contents: read
steps:
- uses: actions/checkout@v7
- run: npm ci --ignore-scripts
- run: npm publish # published without NODE_AUTH_TOKEN
A provenance attestation only guarantees that the build came out of the declared pipeline. If the pipeline itself is compromised, a malicious build ships with the attestation still valid. Mini Shai-Hulud in 2026-05 is the case in point: 84 malicious packages were published carrying valid SLSA Build Level 3 attestations.
Installing: install hooks are arbitrary code execution
An npm package automatically runs its preinstall, install and postinstall scripts during
installation. The Shai-Hulud lineage (2025-09 initial, 2025-11 2.0, 2026-05 Mini, 2026-08
CHAINDROP) and the postmark-mcp incident all used those hooks to get execution. A single
npm install is someone else's code running on your machine.
- In CI, install with
npm ci --ignore-scriptsand run scripts separately only for the packages whose build genuinely needs them. - pnpm already blocks them by default. List only the packages you reviewed and approved under
allowBuilds(onlyBuiltDependenciesbefore pnpm 11). - If you run an internal ingest gate, flag packages that carry install hooks for review. For how to build that gate, see section 3-1 of Open Source Process: From Use to Distribution.
MCP servers and agent skills installed by coding agents travel the same install path. The same controls extended to those tools are in the tool and extension supply chain section of Agent and MCP Tool Governance.
Using VEX
What is VEX (Vulnerability Exploitability eXchange)? It is a machine-readable document that specifies whether a particular CVE is actually exploitable in a given product. It formally expresses cases like "the CVE exists, but the affected code path is not used," reducing unnecessary alerts across downstream supply chains.
Practical use: Four formats are actually in use, CycloneDX VEX, OpenVEX, CSAF, and SPDX 3.0, and none has converged as the single standard. If a customer has not specified a format, starting with the same CycloneDX vulnerabilities field as your existing SBOM is the easiest to wire into your tooling. For the concepts, including the four status values, Vulnerability response deadlines and VEX is the canonical reference.
SBOM Retention Policy
Storage location: Store as CI/CD artifacts and connect to release tags to track SBOMs by version. Use GitHub Actions upload-artifact and GitLab artifacts.paths.
Retention period: ISO/IEC 18974 requires retention for the life of the program. In practice, permanent retention per release version is recommended.
When to update: Regenerate whenever dependencies change. Automatic generation at the PR level keeps it always up to date.
SBOM Analyzer
Upload SBOM files generated by syft, trivy, or cdxgen to automatically analyze vulnerabilities and generate response guidance.
Preview with a sample first (no API key required)
The same demo is available from the 5-minute quick start. Try it below, then run a real analysis on your own SBOM.
Run a real analysis on your own SBOM
It calls the Anthropic API directly from your browser. Enter your own Anthropic API key to use it right away. Your key and inputs are sent only from your browser to Anthropic (they never pass through a trustedoss server). Usage is billed to your own Anthropic account.
In Practice
TRUSCA's sca-self.yml generates a CycloneDX SBOM with cdxgen and then scans it with Trivy, on a daily schedule. Both tools are installed at pinned versions with checksum verification.
The reason for a scheduled run alongside the PR check is that vulnerabilities are disclosed after a release ships. That thread continues in Continuous Monitoring.
Self-Study
The analyzer above is available directly in your browser.
If you need deeper analysis and automatic .grype.yaml policy file generation,
use the agent below.
Prerequisite: Clone the Trusted OSS repository
cd agents/en/sbom-vuln-analyst
claude
The agent automatically performs the following:
- Auto-detects CycloneDX / SPDX / grype results
- Classifies by severity and suggests fixed versions
- Generates
.grype.yamlexception handling examples - Provides CI/CD pipeline integration guidance
Next Steps
- Prevent secret leakage: Secret Detection
- Container image vulnerabilities: Container Security
- Continuous post-deployment monitoring: Monitoring & Auto-Remediation
- ISO/IEC 18974 alignment: ISO Standard Mapping
The analyzer above is for one-off checks. If your whole team needs a continuously running, self-hosted SCA, move on to TRUSCA — an Apache-2.0 tool that manages vulnerabilities (CVEs), license compliance, and SBOMs in one UI.
- Try it yourself: TRUSCA repository (Docker Compose or Helm deployment)
- It is a path to a continuously operated SCA where budget, staffing, or an air-gapped network constrain the options.
The TRUSCA portal links a hosted demo instance you can open. The demo is for looking around, so run it in your own environment with the guide above for real use.