Dependency Scanning and SCA: The Complete Guide to Securing Your Supply Chain

Written by the Rafter Team

Dependency scanning is the automated process of analyzing every third-party library in your application for known vulnerabilities, license violations, and supply chain risks. Software Composition Analysis (SCA) tools perform this analysis by mapping your dependency tree against vulnerability databases like the National Vulnerability Database (NVD) and the GitHub Advisory Database, flagging components with known CVEs, restrictive licenses, or signs of tampering. With modern applications averaging 80% open source code by volume, SCA is not optional security tooling. It is the only way to know whether the libraries you depend on are safe to ship.
The scale of the problem is staggering. A typical Node.js project pulls in hundreds of transitive dependencies. A Java Spring Boot application can exceed a thousand. Every one of those packages is a potential entry point for an attacker. The Log4Shell vulnerability (CVE-2021-44228) demonstrated what happens when a single widely-used library contains a critical flaw. Organizations that lacked dependency scanning scrambled for days to determine whether they were even affected. Those with SCA tools had answers in minutes.
Your code is the minority of your application. Research consistently shows that 70-90% of a modern application's codebase comes from open source dependencies. If you are only scanning the code you write, you are ignoring the vast majority of your attack surface.
Scan your dependencies with Rafter — connect your repo and get a full dependency vulnerability report in under two minutes.
What Is Software Composition Analysis (SCA)?
Software Composition Analysis is a category of security tooling that identifies open source and third-party components in your codebase, catalogs them into a software bill of materials (SBOM), and continuously monitors those components for security vulnerabilities and license compliance issues.
SCA answers three questions that no other security tool can:
- What third-party code are you running? Most developers can name their direct dependencies. Almost none can list the full transitive dependency tree.
- Are any of those components vulnerable? SCA tools cross-reference your dependency versions against CVE databases updated in real time.
- Are your licenses compatible? A GPL-licensed transitive dependency buried six levels deep can force disclosure of your proprietary source code. SCA tools surface these conflicts before your legal team finds them in an audit.
Unlike SAST, which analyzes the code you write, SCA analyzes the code you import. These are fundamentally different risk domains, and they require fundamentally different tools.
SCA vs SAST vs DAST
Understanding where SCA fits in your security stack requires understanding what each tool type covers.
| Tool Type | What It Analyzes | What It Finds | Blind Spots |
|---|---|---|---|
| SCA | Third-party dependencies | Known CVEs, license violations, malicious packages | Zero-day vulnerabilities in dependencies |
| SAST | Your source code | Injection flaws, hardcoded secrets, insecure patterns | Runtime behavior, dependency vulnerabilities |
| DAST | Running application | Auth bypass, misconfig, reflected XSS | Source-level detail, dependency risk |
SCA does not replace SAST or DAST. It covers a different layer entirely. A SQL injection in your code is a SAST finding. A SQL injection in a library you import is an SCA finding. Both are exploitable. Both need detection. You need all three.
The strongest security posture comes from running SCA alongside static analysis in your CI pipeline, with DAST against staging or production environments.
How Dependency Scanning Works
SCA tools follow a well-defined pipeline to identify, catalog, and assess your dependencies. Understanding this pipeline helps you evaluate tools and interpret their results.
Step 1: Manifest and Lockfile Parsing
Every package manager uses manifest files to declare dependencies and lockfiles to pin exact versions. SCA tools start by parsing these files.
{
"name": "my-application",
"version": "1.0.0",
"dependencies": {
"express": "^4.18.2",
"lodash": "^4.17.21",
"jsonwebtoken": "^9.0.0"
},
"devDependencies": {
"jest": "^29.7.0"
}
}
The manifest declares your direct dependencies. But the version range ^4.18.2 could resolve to any compatible version. The lockfile (package-lock.json, yarn.lock, pnpm-lock.yaml) records the exact versions installed, including every transitive dependency.
SCA tools parse both. The lockfile provides the precise versions for vulnerability matching. The manifest provides context about whether a dependency is direct or transitive, production or dev-only.
Step 2: Transitive Dependency Resolution
This is where the real complexity lives. Your package.json might list 10 direct dependencies. Your node_modules folder contains 800.
SCA tools reconstruct the full dependency tree — every package, every version, every relationship. This matters because transitive dependencies are where most vulnerabilities hide. You never chose to install them. You may not know they exist. But they run in your production environment with full access to your application context.
Consider a real scenario: you install express. Express depends on qs for query string parsing. An older version of qs has a prototype pollution vulnerability (CVE-2022-24999). You never imported qs. You never configured it. But your application is vulnerable because Express pulled it in.
Step 3: Vulnerability Database Matching
With the full dependency tree mapped, SCA tools match each component and version against vulnerability databases:
- NVD (National Vulnerability Database): The U.S. government's comprehensive CVE database
- GitHub Advisory Database: Community-curated advisories with package-manager-specific metadata
- OSV (Open Source Vulnerabilities): Google's distributed vulnerability database spanning multiple ecosystems
- Vendor-specific databases: Snyk, Sonatype, and other commercial SCA vendors maintain proprietary vulnerability intelligence
Each vulnerability includes a severity score (CVSS), affected version ranges, fixed versions (when available), and exploit metadata. Advanced SCA tools also perform reachability analysis — determining whether your code actually calls the vulnerable function in the library, not just whether the library is present.
Step 4: License Analysis
SCA tools extract license declarations from each package and flag conflicts. Common issues include:
- Copyleft contamination: A GPL-licensed dependency in a proprietary application may require you to open-source your code
- License incompatibility: Combining packages with mutually exclusive licenses (e.g., GPLv2 and Apache 2.0 in certain configurations)
- Missing licenses: Packages with no declared license default to full copyright — you have no legal right to use them
Step 5: Reporting and Prioritization
Raw vulnerability counts are not useful. An application with 200 flagged CVEs needs triage. Modern SCA tools prioritize findings based on:
- CVSS score: How severe is the vulnerability?
- Exploitability: Is there a known exploit in the wild?
- Reachability: Does your code actually invoke the vulnerable code path?
- Fix availability: Is there a patched version you can upgrade to?
- Environment: Is this a production dependency or a dev-only tool?
A critical-severity, exploitable, reachable vulnerability in a production dependency with a fix available demands immediate action. A low-severity issue in a dev-only dependency with no known exploit can wait.
What SCA Tools Catch
Dependency scanning covers a broader set of risks than most developers realize. Here is what modern SCA tools detect.
Known CVEs in Open Source Libraries
This is the core SCA use case. When a researcher discovers a vulnerability in an open source library and a CVE is assigned, SCA tools flag every project using affected versions. This includes:
- Remote code execution vulnerabilities like Log4Shell
- Prototype pollution in JavaScript libraries
- Deserialization flaws in Java libraries
- Path traversal in file-handling packages
- Denial of service vulnerabilities in parsers and validators
License Compliance Violations
Enterprise SCA tools maintain license databases and policy engines. You define which licenses are acceptable for your organization, and the tool flags violations automatically. This prevents legal exposure from accidentally shipping copyleft code in a proprietary product.
Outdated Dependencies
Not every outdated dependency has a CVE. But outdated dependencies are a leading indicator of future vulnerabilities. A package that hasn't been updated in three years is more likely to contain undiscovered flaws, and when a CVE does drop, the upgrade path is longer and riskier.
Malicious Packages
The newest and fastest-growing SCA detection category. Malicious packages are planted in public registries through:
- Typosquatting: Publishing
lodasshorexpresssand hoping developers mistype - Dependency confusion: Publishing a public package with the same name as an internal package, exploiting package managers that check public registries first
- Account takeover: Compromising a legitimate maintainer's credentials and pushing a backdoored update
- Star-jacking: Cloning a popular repo, adding malware, and publishing under a similar name
Advanced SCA tools analyze package behavior — network calls, file system access, obfuscated code, post-install scripts — to detect malicious intent even before a CVE is assigned.
Supply Chain Attacks: The Threat SCA Was Built For
Supply chain attacks target the software development and delivery pipeline itself, rather than the final application. They are increasing in frequency and sophistication.
Real-World Supply Chain Attacks
event-stream (2018): A maintainer handed control of a popular npm package to a new contributor. The new maintainer added a dependency that contained obfuscated code targeting a specific Bitcoin wallet application. The package had 1.5 million weekly downloads.
ua-parser-js (2021): An attacker compromised the npm account of the maintainer of ua-parser-js (7 million weekly downloads) and published versions containing cryptomining and credential-stealing malware.
colors and faker (2022): The original maintainer of these widely-used npm packages deliberately introduced an infinite loop and corrupted output, breaking thousands of applications that depended on them.
xz Utils (2024): A multi-year social engineering campaign where an attacker gained commit access to the xz compression library and inserted a backdoor targeting SSH authentication. The attack was discovered by accident just before it reached stable Linux distributions.
These attacks share a common pattern: they exploit trust in the dependency chain. Your code is secure. The library you chose is secure. But something three levels deep in the transitive dependency tree has been compromised.
SCA tools are your primary defense against these attacks. They maintain databases of known-malicious packages, monitor for suspicious package behaviors, and alert when dependencies change in unexpected ways.
The AI-Generated Code Problem
AI coding assistants introduce a specific and underappreciated supply chain risk. When you ask an LLM to generate code, it often suggests dependencies based on its training data. Those suggestions may reference:
- Outdated versions: The model's training data has a cutoff. It may suggest
lodash@4.17.15when4.17.21patches a prototype pollution vulnerability. - Deprecated packages: The model may suggest
request(deprecated since 2020) instead of modern alternatives likeundiciornode-fetch. - Non-existent packages: LLMs hallucinate. They sometimes suggest package names that do not exist. An attacker who registers those hallucinated names can execute a supply chain attack against anyone who blindly installs the AI's suggestion.
This last vector — dependency hallucination — is new and growing. Researchers have documented cases where popular LLMs consistently suggest the same non-existent package names, creating predictable targets for attackers.
If your team uses AI to generate code, dependency scanning is not just recommended. It is mandatory. Every AI-generated dependency should be verified against the actual package registry and scanned for vulnerabilities before installation.
AI-suggested dependencies are unvetted by default. An LLM has no mechanism to check whether a package is maintained, secure, or even real. Treat every AI-generated import and require statement as untrusted input that needs validation through your SCA pipeline.
The SCA Tool Landscape
The dependency scanning market ranges from free, open-source tools to enterprise platforms with six-figure price tags. Here is how the major options compare.
Snyk
Snyk is the most developer-focused commercial SCA platform. It integrates with GitHub, GitLab, Bitbucket, and most CI systems. Its vulnerability database is curated by a dedicated research team, and it provides automated fix PRs that bump vulnerable dependencies to patched versions.
Strengths: Developer experience, automated fix PRs, broad language support, container scanning. Weaknesses: Free tier is limited, pricing scales with project count, can generate alert fatigue on large monorepos.
GitHub Dependabot
Dependabot is built into GitHub and free for all repositories. It monitors your dependency manifests, creates pull requests when vulnerabilities are discovered, and can also open PRs for routine version updates.
Strengths: Zero setup for GitHub users, free, well-integrated with GitHub Security Advisories. Weaknesses: GitHub-only, limited policy controls, no reachability analysis, no license compliance.
Renovate
Renovate is an open-source dependency update tool that runs as a bot on your repositories. While not a pure SCA tool, it keeps dependencies current, which is the most effective way to reduce your vulnerability surface area over time.
Strengths: Highly configurable, supports every major package manager, can be self-hosted, grouping and scheduling options. Weaknesses: Not a vulnerability scanner — it updates dependencies but does not perform CVE matching or license analysis on its own.
OWASP Dependency-Check
OWASP Dependency-Check is a free, open-source SCA tool that identifies known vulnerabilities in project dependencies. It supports Java, .NET, Python, Ruby, Node.js, and several other ecosystems.
Strengths: Free, open source, integrates with Maven/Gradle/Jenkins, maps directly to NVD data. Weaknesses: High false positive rate, slower database updates than commercial tools, limited support for newer ecosystems.
Rafter
Rafter combines SCA with SAST in a single platform designed for AI-generated code. It scans your dependencies alongside your source code, providing a unified view of both first-party and third-party risk. This is particularly valuable for teams using AI coding assistants, where the boundary between "code you wrote" and "code you imported" is increasingly blurred.
Strengths: Unified SAST + SCA, optimized for AI-generated code, fast GitHub integration, actionable prioritization. Weaknesses: Newer platform, still expanding language coverage.
Try Rafter's dependency scanning — connect a repo and see your full dependency risk profile in minutes.
Integrating SCA Into Your CI/CD Pipeline
Dependency scanning delivers the most value when it runs automatically on every pull request and merge to main. Here is a reference pipeline configuration.
name: Security Scan
on:
pull_request:
branches: [main]
push:
branches: [main]
schedule:
- cron: '0 6 * * 1' # Weekly Monday scan for new CVEs
jobs:
dependency-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: npm ci
- name: Run SCA scan
run: npx rafter scan --sca --fail-on critical
- name: Upload SBOM
if: github.ref == 'refs/heads/main'
run: npx rafter sbom --format spdx --output sbom.json
- name: Upload scan results
uses: actions/upload-artifact@v4
with:
name: security-results
path: |
sbom.json
rafter-report.json
Key design decisions in this pipeline:
- Fail on critical: The pipeline blocks merges when critical-severity vulnerabilities are found in dependencies. This prevents known-bad libraries from reaching production.
- Weekly scheduled scan: New CVEs are published daily. A dependency that was safe on Monday may have a critical CVE by Friday. Scheduled scans catch these retroactively.
- SBOM generation: A Software Bill of Materials is increasingly required by regulation (U.S. Executive Order 14028) and by enterprise customers. Generating it in CI ensures it stays current.
Setting Policies That Work
Aggressive SCA policies (block on any vulnerability) create developer friction and get disabled. Lax policies (alert only) get ignored. Find the middle ground:
- Block on critical and high severity in production dependencies with known exploits
- Warn on medium severity and dev-dependency issues
- Track but don't block low-severity findings and informational license notices
- Auto-merge patch updates from Dependabot or Renovate for non-breaking version bumps
- Review major version bumps manually since they may include breaking changes
Building a Dependency Management Strategy
Dependency scanning is a tool. Dependency management is a strategy. The tool tells you what is wrong. The strategy determines how you respond.
Establish a Dependency Governance Policy
Define clear rules for adding new dependencies:
- Evaluation criteria: Maintenance activity, download counts, known vulnerabilities, license compatibility, and bus factor (how many maintainers does the package have?)
- Approval process: Who can add a new direct dependency? For critical applications, this should require a brief review.
- Banned packages: Maintain a list of packages your organization will not use, either for security reasons or because a preferred alternative exists.
Keep Dependencies Current
The single most effective dependency security practice is keeping packages up to date. Most CVEs are fixed quickly by maintainers. If you are running the latest version, the window of vulnerability is minimal.
Renovate or Dependabot should run continuously, creating update PRs that your CI pipeline validates. For most packages, automated merge of patch-level updates is safe and dramatically reduces your vulnerability backlog.
Monitor Continuously, Not Just at Build Time
New CVEs are published against existing package versions every day. A clean SCA scan today does not guarantee a clean state tomorrow. Your SCA tool should:
- Run on every PR and merge
- Run on a daily or weekly schedule against your main branch
- Send alerts when new CVEs affect your deployed dependencies
- Integrate with your incident response workflow for critical findings
Generate and Maintain SBOMs
A Software Bill of Materials is a machine-readable inventory of every component in your application. It serves two purposes:
- Incident response: When the next Log4Shell drops, you can query your SBOM to determine exposure in seconds rather than hours.
- Compliance: Government contracts, regulated industries, and enterprise customers increasingly require SBOMs as part of procurement.
Generate SBOMs in your CI pipeline and store them alongside your releases.
Pin Dependency Versions
Use lockfiles religiously. Never deploy from a fresh npm install that resolves version ranges at install time. Your lockfile ensures that the exact versions you tested are the exact versions you deploy.
For critical applications, consider vendoring dependencies — checking them directly into your repository or a private registry — so that even a compromised public registry cannot inject malicious code.
Common SCA Mistakes to Avoid
Scanning only direct dependencies. If your SCA tool does not resolve transitive dependencies, it misses the majority of your attack surface. Verify that your tool parses lockfiles, not just manifests.
Ignoring dev dependencies. While dev dependencies do not ship to production, they run in your CI environment. A compromised dev dependency can steal secrets from your build pipeline, modify build outputs, or exfiltrate source code.
Treating all CVEs equally. A CVSS 9.8 with a public exploit in a production dependency is not the same as a CVSS 4.0 with no known exploit in a testing utility. Prioritize ruthlessly or your team will develop alert fatigue and start ignoring SCA results entirely.
Running SCA only in CI. Developers should see dependency vulnerability information in their IDE or during local development. Catching a vulnerable dependency before it reaches a PR saves review cycles and pipeline time.
Not tracking your SBOM. Without a current bill of materials, you cannot respond quickly to zero-day disclosures. When a new critical CVE is announced, you need to know within minutes whether any of your applications are affected.
Getting Started With Dependency Scanning
If you are not running SCA today, start with these steps:
- Enable Dependabot alerts on every GitHub repository. This is free, takes 30 seconds, and provides baseline CVE monitoring.
- Add lockfile generation to any project that does not already have one. Without a lockfile, SCA tools cannot determine exact versions.
- Run a baseline scan to understand your current vulnerability posture. Expect a large initial backlog — this is normal.
- Triage the backlog starting with critical-severity, exploitable vulnerabilities in production dependencies.
- Integrate SCA into CI so new vulnerabilities cannot be introduced without review.
- Add scheduled scans to catch new CVEs published against your existing dependencies.
The goal is not zero vulnerabilities. The goal is continuous awareness and systematic reduction of risk.
Start your first dependency scan with Rafter — free for open source projects.