When security teams talk about "scanning" code in CI/CD, they usually mean one of two very different things: scanning the code you wrote (SAST) or scanning the open-source code you imported (SCA). Both are called "security scanners." Both produce findings with severities and CVE-like identifiers. But they catch almost completely different vulnerability classes, and understanding that distinction determines whether you actually close your real risk gaps or just feel like you have.
What SAST scans
Static Application Security Testing (SAST) reads your source code — the JavaScript, Python, Java, Go, Ruby files that your team writes — and looks for security flaws in the code itself. SQL injection in a database query. A hardcoded AWS key in a config file. An XSS vector in a template. A call to MD5 where bcrypt should be. An HTTP endpoint that passes user input to a shell command.
SAST doesn't know about or care about which npm packages you installed. It's analyzing your code logic. A SAST tool will flag this:
const result = db.query(`SELECT * FROM users WHERE id = ${req.params.id}`);
...because the user-controlled value req.params.id flows directly into a SQL query without parameterization. It doesn't matter which database library you're using or whether that library has any CVEs. The bug is in your code.
What SCA scans
Software Composition Analysis (SCA) reads your dependency manifest — package.json, requirements.txt, pom.xml, go.mod — and checks every package (direct and transitive) against a vulnerability database like OSV. If you're running lodash@4.17.4, which has a known prototype pollution CVE, SCA flags it.
SCA doesn't analyze your code at all. It's checking the versions of the packages you depend on against a list of known-vulnerable versions. A perfect SAST run with zero findings can coexist with fifty SCA findings in your dependencies — and vice versa.
The blind spots in each
What SAST can't see:
- Vulnerabilities introduced by the open-source packages you import
- Supply-chain attacks with no CVE (typosquatting, dependency confusion)
- Runtime configuration mistakes in cloud infrastructure
- Bugs that only manifest under specific execution conditions
What SCA can't see:
- Security bugs in the code your team writes
- Hardcoded credentials in your own source files
- Weak cryptographic choices in your own logic
- Framework misconfigurations (CSRF disabled, DEBUG mode on, CORS wildcard)
The blind spots are almost perfectly complementary. An attacker probing your application has two main paths: exploit a bug in your code (SAST territory) or exploit a bug in a library you imported (SCA territory). Both scanners, covering both paths.
A concrete example: two reports, two attack surfaces
Imagine a Node.js API with these two problems:
Problem A (SAST territory): In controllers/user.js, you build a MongoDB query with string interpolation from req.query.username. This is a NoSQL injection vulnerability. It's in your code. No CVE exists for it. SCA will never find it.
Problem B (SCA territory): You depend on jsonwebtoken@8.5.1, which has a known algorithm confusion vulnerability (CVE-2022-23529). Your code calls jwt.verify() correctly. SAST may not flag it because the call looks correct in isolation — the vulnerability is in the library's internal implementation.
These are two real attack vectors. One scanner catches Problem A; the other catches Problem B. Running only SCA leaves NoSQL injection open. Running only SAST leaves the JWT library vulnerability open.
The combined CI gate
The most effective CI configuration runs both in parallel:
# GitHub Actions — combined SCA + SAST gate
- uses: Rushabh5000/dep-warden/cli@main
with:
file: package-lock.json # SCA: dependency scan
sast-dir: ./src # SAST: static analysis
fail-on: high
sast-fail-on: high
This single step:
- Parses
package-lock.json, resolves the full transitive dependency tree, checks OSV/KEV/EPSS for vulnerabilities and typosquats - Walks
./src, detects languages, runs pattern + taint analysis across all source files against 300+ security rules - Fails the build if either scan produces a HIGH or CRITICAL finding
Two scan types, one gate, no account required.
Prioritization across both
When findings come from both SAST and SCA, the combined priority order:
- SCA: KEV-listed + direct dependency + fix available — attackers are actively using this, you can fix it now
- SAST: HIGH-confidence injection/RCE finding — user input confirmed flowing to a dangerous sink
- SCA: HIGH CVSS + EPSS > 0.10 + fix available — elevated exploitation probability
- SAST: hardcoded credential — immediate exposure risk if it reaches a repo
- Everything else — triage by severity and confidence, don't block releases on MEDIUM/LOW
What DepWarden gives you
DepWarden combines both scanners in one tool, free and without an account:
- SCA across 11 package ecosystems (npm, PyPI, Maven, Gradle, Go, Cargo, Composer, RubyGems, NuGet, Dart, Swift) with OSV/KEV/EPSS enrichment and exploitability-first prioritization
- SAST across 15 languages and IaC formats, with 300+ security rules covering injection, XSS, secrets, weak crypto, framework-specific misconfigurations, and more
- A single GitHub Action that gates pull requests with both scanners in one step
The only scanner you need in CI to cover the two main attack paths against your application.
See also: what is SAST?, CVSS, EPSS and KEV guide, free Snyk alternative.
Top comments (0)