# SAST vs SCA: why your CI pipeline needs both

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:

```javascript
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.

## Running both together

The most effective setup runs SCA and SAST on the same codebase in one pass: upload a manifest alongside a source zip in the browser, or connect a GitHub, GitLab, Bitbucket or Azure DevOps repo branch directly and DepWarden runs both.

That single scan:

- Parses `package-lock.json`, resolves the full transitive dependency tree, checks OSV/KEV/EPSS for vulnerabilities and typosquats
- Walks the source tree, detects languages, runs pattern + taint analysis against 300+ security rules
- Ranks findings from both by severity so nothing gets buried

Two scan types, one report, no account required.

## Prioritization across both

When findings come from both SAST and SCA, the combined priority order:

1. **SCA: KEV-listed + direct dependency + fix available** — attackers are actively using this, you can fix it now
2. **SAST: HIGH-confidence injection/RCE finding** — user input confirmed flowing to a dangerous sink
3. **SCA: HIGH CVSS + EPSS > 0.10 + fix available** — elevated exploitation probability
4. **SAST: hardcoded credential** — immediate exposure risk if it reaches a repo
5. **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?](https://depwarden.in/blog/what-is-sast), [CVSS, EPSS and KEV guide](https://depwarden.in/blog/cvss-epss-kev-guide), [free Snyk alternative](https://depwarden.in/vs/snyk).

