<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[DepWarden Blog]]></title><description><![CDATA[DepWarden Blog]]></description><link>https://depwarden.hashnode.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1593680282896/kNC7E8IR4.png</url><title>DepWarden Blog</title><link>https://depwarden.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Fri, 11 Sep 2026 07:25:41 GMT</lastBuildDate><atom:link href="https://depwarden.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[We checked every single-typo of the 30 most popular npm and PyPI packages. Here's what's actually registered.]]></title><description><![CDATA[Typosquatting is one of the best-documented supply-chain attack techniques — publish a package one keystroke away from something popular, wait for developers to fat-finger npm install, and you have a ]]></description><link>https://depwarden.hashnode.dev/npm-pypi-typosquatting-packages-registry-2026-report</link><guid isPermaLink="true">https://depwarden.hashnode.dev/npm-pypi-typosquatting-packages-registry-2026-report</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Rushabh Shah]]></dc:creator><pubDate>Thu, 10 Sep 2026 06:43:44 GMT</pubDate><content:encoded><![CDATA[<p>Typosquatting is one of the best-documented supply-chain attack techniques — publish a package one keystroke away from something popular, wait for developers to fat-finger <code>npm install</code>, and you have a foothold on their machine or CI pipeline with no CVE ever filed. It's been written about for years. What's less documented is a very simple question: <strong>right now, today, how many of those look-alike names are actually sitting on the registry?</strong></p>
<p>So we checked. Not a sample, not an estimate — every single-character typo (omit a letter, double a letter, swap two adjacent letters — the three classic patterns) of the 30 most popular packages on npm and the 30 most popular on PyPI, queried live against each registry's real API, then cross-referenced every hit that's actually registered against OSV.dev's public malicious-package database.</p>
<h2>The headline numbers</h2>
<ul>
<li><strong>npm: 498 candidate typo names checked across 30 popular packages. 297 (59.6%) are currently registered, real packages.</strong> Of those 297, <strong>97 (32.7%) are already documented as malicious in OSV's public database</strong> — not "suspicious," not "flagged by us," but carrying a real <code>MAL-</code> or <code>GHSA-</code> advisory ID today.</li>
<li><strong>PyPI: 582 candidate typo names checked across an equally popular 30-package set. 47 (8.1%) are registered. Zero are flagged malicious in OSV.</strong></li>
</ul>
<p>Same technique, same rigor, same day. One ecosystem where a third of the look-alikes you'd stumble into are already confirmed hostile; the other where the exposure — at least via this specific single-typo technique — is close to zero.</p>
<h2>Methodology</h2>
<p>This mirrors the exact detection method DepWarden uses in production: Damerau–Levenshtein edit-distance matching against a curated list of high-popularity package names. For this study we narrowed to the three typo patterns that account for the overwhelming majority of real-world typosquats (and match the classic examples — <code>expresss</code>, <code>epxress</code> — that show up in every writeup of this technique):</p>
<ol>
<li><strong>Omission</strong> — drop one character (<code>express</code> → <code>expres</code>)</li>
<li><strong>Duplication</strong> — double one character (<code>express</code> → <code>expresss</code>)</li>
<li><strong>Adjacent transposition</strong> — swap two neighboring characters (<code>express</code> → <code>epxress</code>)</li>
</ol>
<p>For each of the 30 most popular packages per ecosystem, every candidate generated by these three rules was checked against the real registry API (<code>registry.npmjs.org</code> for npm, <code>pypi.org/pypi/.../json</code> for PyPI) — a 200 response means it's a real, currently-published package. Every hit was then queried against <code>api.osv.dev</code> for any associated advisory. Nothing here is inferred or estimated; every count is a live HTTP response, checked on 25 August 2026.</p>
<p><strong>What this deliberately doesn't claim:</strong> a registered look-alike name is not automatically malicious. Plenty of short candidate strings (<code>vue</code> → <code>ve</code>, <code>next</code> → <code>net</code>) collide with legitimate, completely unrelated packages that just happen to be short common words — npm alone has over 3 million packages, so some collision is inevitable. That's exactly why the OSV cross-reference matters: it's the difference between "this name exists" (weak signal) and "this specific package is a documented, named threat" (real finding). The 97/47 split above is the second kind.</p>
<h2>Which popular packages attract the most confirmed-malicious squats</h2>
<table>
<thead>
<tr>
<th>Popular package</th>
<th>Confirmed-malicious typo variants found</th>
</tr>
</thead>
<tbody><tr>
<td>request</td>
<td>17</td>
</tr>
<tr>
<td>lodash</td>
<td>9</td>
</tr>
<tr>
<td>express</td>
<td>9</td>
</tr>
<tr>
<td>chalk</td>
<td>8</td>
</tr>
<tr>
<td>commander</td>
<td>8</td>
</tr>
<tr>
<td>async</td>
<td>8</td>
</tr>
<tr>
<td>react</td>
<td>7</td>
</tr>
<tr>
<td>debug</td>
<td>5</td>
</tr>
<tr>
<td>bluebird</td>
<td>5</td>
</tr>
<tr>
<td>moment</td>
<td>4</td>
</tr>
</tbody></table>
<p><code>request</code> — deprecated since 2020 but still one of the most-installed packages in npm history from years of accumulated dependents — tops the list by a wide margin. That's a pattern worth naming explicitly: <strong>an old, extremely popular, no-longer-actively-maintained package appears to be a more attractive squatting target than a young one</strong>, plausibly because the volume of developers who've typed its name from memory (and therefore mistyped it) over the package's lifetime is simply larger. We're not claiming causation from an n=30 sample, but the shape of the data points that way.</p>
<h2>The full data, and how to re-run it yourself</h2>
<p>The top-10 table above is the interesting slice, but a study you cannot check is just an assertion. So here is all of it — every candidate name, whether the registry says it is published, and every advisory id attached to it.</p>
<ul>
<li><strong><a href="https://depwarden.in/data/typosquat-study.csv">Download the dataset (CSV)</a></strong> — one row per candidate, 1,098 rows across both ecosystems.</li>
<li><strong><a href="https://depwarden.in/data/typosquat-study.json">Same data as JSON</a></strong> — includes the exact package lists used.</li>
<li><strong>Re-run it yourself:</strong> the generator is in the <a href="https://github.com/Rushabh5000/dep-warden">DepWarden repo</a> at <code>scripts/typosquat-study.mjs</code>. The package lists are hard-coded in that file on purpose, so a re-run stays comparable rather than drifting with whatever is popular this week.</li>
</ul>
<p>Re-running the whole study on <strong>5 September 2026</strong>, eleven days after the original pass, reproduced it closely: npm 483 candidates, 284 registered (58.8%), <strong>99 carrying an advisory (34.9% of registered)</strong>; PyPI 615 candidates, 52 registered (8.5%), <strong>zero carrying an advisory</strong>. The per-package ranking came back identical — <code>request</code> still first by a wide margin at 17. Counts move by a few points between runs because packages get published and unpublished and OSV adds advisories; the finding does not.</p>
<h2>The second data point: how healthy are the real packages?</h2>
<p>Alongside the typosquat check, we pulled real <a href="https://scorecard.dev">OpenSSF Scorecard</a> scores — an independent, automated 0–10 supply-chain-hygiene rating covering branch protection, CI presence, signed releases and 15 other checks — for the same 60 popular packages (59 resolved; one npm package's GitHub mapping didn't return a score).</p>
<ul>
<li><strong>npm: average score 6.24/10. 20.7% score below 5. 6.9% score below 3.</strong></li>
<li><strong>PyPI: average score 6.79/10. 10.0% score below 5. 0% score below 3.</strong></li>
</ul>
<p>Lowest-scoring packages checked: <strong>bluebird (2.0)</strong>, <strong>debug (2.6)</strong>, and <strong>request (3.4)</strong> on npm; <strong>psycopg2 (3.7)</strong>, <strong>setuptools (4.4)</strong>, and <strong>httpx (4.9)</strong> on PyPI. Worth noting: <code>bluebird</code> and <code>debug</code> — two of the lowest Scorecard scores in the whole sample — also both appear in the confirmed-malicious-squat table above. Again, not a causal claim from this sample size, but a genuinely interesting adjacency: the same handful of enormously popular, comparatively lower-maintenance-signal packages show up on both lists.</p>
<h2>What this means if you ship software</h2>
<p>The practical takeaway isn't "avoid npm" — it's that <strong>single-character typing mistakes in <code>npm install</code> carry real, non-hypothetical, currently-live risk today</strong>, at a rate (roughly 1 in 3 of the names you could plausibly typo into) that's higher than most developers would guess. PyPI's exposure, at least to this specific attack pattern, is measurably lower — worth knowing if you're weighing where a supply-chain review should focus first.</p>
<p>Three concrete things that actually help: pin exact versions in a lockfile so a one-off typo in a scratch command doesn't become a permanent dependency; use a scanner that checks for typosquat-shaped names as a distinct signal from CVE matching, since (by definition) none of these 97 malicious packages have a CVE; and treat an unfamiliar package with a name suspiciously close to something you know — one character off, one character doubled — as worth a second look before installing, especially if it has few downloads and a recent publish date.</p>
<p>DepWarden runs this same detection — Damerau-Levenshtein matching against a curated popular-package list per ecosystem — on every scan, free, no account required. Related reading: <a href="https://depwarden.in/blog/npm-typosquatting-guide">how npm typosquatting and dependency confusion attacks work</a>, <a href="https://depwarden.in/blog/detect-typosquats-in-ci">detecting typosquats in CI</a>, <a href="https://depwarden.in/blog/openssf-scorecard-explained">what the OpenSSF Scorecard actually measures</a>.</p>
]]></content:encoded></item><item><title><![CDATA[SAST vs SCA: why your CI pipeline needs both]]></title><description><![CDATA[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). Bot]]></description><link>https://depwarden.hashnode.dev/sast-vs-sca-ci-pipeline-security-testing</link><guid isPermaLink="true">https://depwarden.hashnode.dev/sast-vs-sca-ci-pipeline-security-testing</guid><category><![CDATA[SAST]]></category><category><![CDATA[Security]]></category><category><![CDATA[DevSecOps]]></category><dc:creator><![CDATA[Rushabh Shah]]></dc:creator><pubDate>Thu, 10 Sep 2026 06:43:21 GMT</pubDate><content:encoded><![CDATA[<p>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.</p>
<h2>What SAST scans</h2>
<p><strong>Static Application Security Testing (SAST)</strong> 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 <code>MD5</code> where <code>bcrypt</code> should be. An HTTP endpoint that passes user input to a shell command.</p>
<p>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:</p>
<pre><code class="language-javascript">const result = db.query(`SELECT * FROM users WHERE id = ${req.params.id}`);
</code></pre>
<p>...because the user-controlled value <code>req.params.id</code> 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.</p>
<h2>What SCA scans</h2>
<p><strong>Software Composition Analysis (SCA)</strong> reads your dependency manifest — <code>package.json</code>, <code>requirements.txt</code>, <code>pom.xml</code>, <code>go.mod</code> — and checks every package (direct and transitive) against a vulnerability database like OSV. If you're running <code>lodash@4.17.4</code>, which has a known prototype pollution CVE, SCA flags it.</p>
<p>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.</p>
<h2>The blind spots in each</h2>
<p><strong>What SAST can't see:</strong></p>
<ul>
<li>Vulnerabilities introduced by the open-source packages you import</li>
<li>Supply-chain attacks with no CVE (typosquatting, dependency confusion)</li>
<li>Runtime configuration mistakes in cloud infrastructure</li>
<li>Bugs that only manifest under specific execution conditions</li>
</ul>
<p><strong>What SCA can't see:</strong></p>
<ul>
<li>Security bugs in the code your team writes</li>
<li>Hardcoded credentials in your own source files</li>
<li>Weak cryptographic choices in your own logic</li>
<li>Framework misconfigurations (CSRF disabled, DEBUG mode on, CORS wildcard)</li>
</ul>
<p>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.</p>
<h2>A concrete example: two reports, two attack surfaces</h2>
<p>Imagine a Node.js API with these two problems:</p>
<p><strong>Problem A (SAST territory):</strong> In <code>controllers/user.js</code>, you build a MongoDB query with string interpolation from <code>req.query.username</code>. This is a NoSQL injection vulnerability. It's in your code. No CVE exists for it. SCA will never find it.</p>
<p><strong>Problem B (SCA territory):</strong> You depend on <code>jsonwebtoken@8.5.1</code>, which has a known algorithm confusion vulnerability (CVE-2022-23529). Your code calls <code>jwt.verify()</code> correctly. SAST may not flag it because the call looks correct in isolation — the vulnerability is in the library's internal implementation.</p>
<p>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.</p>
<h2>Running both together</h2>
<p>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.</p>
<p>That single scan:</p>
<ul>
<li>Parses <code>package-lock.json</code>, resolves the full transitive dependency tree, checks OSV/KEV/EPSS for vulnerabilities and typosquats</li>
<li>Walks the source tree, detects languages, runs pattern + taint analysis against 300+ security rules</li>
<li>Ranks findings from both by severity so nothing gets buried</li>
</ul>
<p>Two scan types, one report, no account required.</p>
<h2>Prioritization across both</h2>
<p>When findings come from both SAST and SCA, the combined priority order:</p>
<ol>
<li><strong>SCA: KEV-listed + direct dependency + fix available</strong> — attackers are actively using this, you can fix it now</li>
<li><strong>SAST: HIGH-confidence injection/RCE finding</strong> — user input confirmed flowing to a dangerous sink</li>
<li><strong>SCA: HIGH CVSS + EPSS &gt; 0.10 + fix available</strong> — elevated exploitation probability</li>
<li><strong>SAST: hardcoded credential</strong> — immediate exposure risk if it reaches a repo</li>
<li><strong>Everything else</strong> — triage by severity and confidence, don't block releases on MEDIUM/LOW</li>
</ol>
<h2>What DepWarden gives you</h2>
<p>DepWarden combines both scanners in one tool, free and without an account:</p>
<ul>
<li><strong>SCA</strong> across 11 package ecosystems (npm, PyPI, Maven, Gradle, Go, Cargo, Composer, RubyGems, NuGet, Dart, Swift) with OSV/KEV/EPSS enrichment and exploitability-first prioritization</li>
<li><strong>SAST</strong> across 15 languages and IaC formats, with 300+ security rules covering injection, XSS, secrets, weak crypto, framework-specific misconfigurations, and more</li>
<li>A single <strong>GitHub Action</strong> that gates pull requests with both scanners in one step</li>
</ul>
<p>The only scanner you need in CI to cover the two main attack paths against your application.</p>
<p>See also: <a href="https://depwarden.in/blog/what-is-sast">what is SAST?</a>, <a href="https://depwarden.in/blog/cvss-epss-kev-guide">CVSS, EPSS and KEV guide</a>, <a href="https://depwarden.in/vs/snyk">free Snyk alternative</a>.</p>
]]></content:encoded></item><item><title><![CDATA[How npm typosquatting and dependency confusion attacks work (and how to stop them)]]></title><description><![CDATA[In February 2021, security researcher Alex Birsan published a paper describing how he had successfully deployed malicious packages to the internal build systems of Apple, Microsoft, PayPal, Shopify, a]]></description><link>https://depwarden.hashnode.dev/npm-typosquatting-dependency-confusion-attacks-guide</link><guid isPermaLink="true">https://depwarden.hashnode.dev/npm-typosquatting-dependency-confusion-attacks-guide</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Security]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[npm]]></category><dc:creator><![CDATA[Rushabh Shah]]></dc:creator><pubDate>Mon, 07 Sep 2026 13:51:49 GMT</pubDate><content:encoded><![CDATA[<p>In February 2021, security researcher Alex Birsan published a paper describing how he had successfully deployed malicious packages to the internal build systems of Apple, Microsoft, PayPal, Shopify, and 32 other companies. He did it without hacking a single server, exploiting a single CVE, or phishing a single developer. He published packages to npm, PyPI and RubyGems with names matching internal packages those companies used — and their build systems installed his public versions automatically.</p>
<p>This is <strong>dependency confusion</strong>. It doesn't have a CVE because the vulnerability isn't in the package — it's in the resolution logic of package managers. And it's just one flavour of supply-chain attack that pure CVE-based scanners completely miss.</p>
<h2>Typosquatting: catch the typo, own the build</h2>
<p><strong>Typosquatting</strong> exploits the fact that developers type package names by hand. Publish <code>expresss</code> to npm (with three s's) and anyone who makes that common typo in <code>npm install</code> pulls down whatever you put in the package. Publish it with a convincing README, a few hundred weekly downloads from bots, and a malicious <code>postinstall</code> script, and you have a stealthy credential-stealing payload reaching developer machines and CI pipelines.</p>
<p>Real examples from npm's history:</p>
<ul>
<li><code>crossenv</code> — a typosquat of <code>cross-env</code> that stole environment variables (which often contain API keys and tokens).</li>
<li><code>getcookies</code> — embedded in a legitimate-looking utility, exfiltrated browser cookies.</li>
<li><code>loadsh</code> — typosquat of <code>lodash</code>, one of the most-downloaded npm packages.</li>
<li><code>reqeusts</code> / <code>reqests</code> — multiple typosquats of the Python <code>requests</code> library.</li>
</ul>
<p>The <code>postinstall</code> script is the key mechanism: npm runs it automatically when the package installs, before you've had a chance to read the code. A malicious <code>postinstall</code> can exfiltrate environment variables, install persistent backdoors, or modify other packages in <code>node_modules</code>.</p>
<h2>Dependency confusion: the namespace collision attack</h2>
<p>Dependency confusion exploits a different logic flaw. Many companies use a private npm registry (Artifactory, Nexus, GitHub Packages) alongside the public npm registry. When a package manager is told to look up a package, most configurations check the public registry if the private one doesn't have it — or check both and take the highest version.</p>
<p>Birsan's attack: find the name of an internal package (often visible in job postings, leaked config files, or error messages), publish a public package with the same name at a version number higher than the internal one (e.g. <code>99.0.0</code>), and wait for build systems to install the "newer" public version.</p>
<p>The fix at the package manager level is to scope all internal packages under a private namespace (<code>@company/internal-lib</code> rather than <code>internal-lib</code>) and configure the registry to only allow scoped packages from the private registry. But this requires intentional configuration that many teams never got around to.</p>
<h2>What detection looks like</h2>
<p>CVE-based scanners can't catch these attacks because there's no CVE. The signals that matter:</p>
<p><strong>Typosquat detection</strong> uses edit distance algorithms (Levenshtein, Damerau-Levenshtein) to find packages in your dependency tree whose names are suspiciously close to popular packages but aren't those packages. A package one character transposition away from <code>lodash</code>, <code>express</code> or <code>react</code> with no established publishing history is a strong signal.</p>
<p><strong>Install-script presence</strong> is a risk signal on its own. Legitimate packages rarely need to run code at install time. A package with a <code>postinstall</code> script from an unknown publisher warrants scrutiny, especially if it appeared recently in your tree.</p>
<p><strong>Maintainer and publish history</strong> signals: a package published 3 days ago with 0 dependents and a <code>postinstall</code> script that matches a popular name is almost certainly malicious or a testing mistake. Package maintainer changes on established packages — the XZ Utils backdoor mechanism — are similarly high-signal.</p>
<p><strong>Version anomalies</strong>: a version number that skips from <code>1.0.4</code> to <code>99.0.0</code> is a classic dependency confusion marker.</p>
<h2>DepWarden's approach</h2>
<p>DepWarden flags typosquats using a Damerau-Levenshtein edit-distance check against a curated list of the most popular packages in each ecosystem. A package one keystroke away from a popular one that isn't that package gets a supply-chain finding (HIGH severity) with the specific match it resembles.</p>
<p>Install-script presence, maintainer-change signals and version anomalies from the OpenSSF Scorecard and supply-chain metadata are also surfaced — the signals that have no CVE but matter enormously in the real attack landscape.</p>
<p>The important point: these attacks happen before a CVE is ever filed, if one ever is. By the time there's a CVE for <code>loadsh</code>, the attack has already run. The only defence is catching the suspicious signal upstream.</p>
<p>Curious how many of these look-alike names are actually live on the registry right now? We checked every single-character typo of the 30 most popular npm and PyPI packages against the real registries and cross-referenced the hits against OSV's malicious-package database — see <a href="https://depwarden.in/blog/npm-pypi-typosquatting-2026-report">the full data</a>.</p>
]]></content:encoded></item><item><title><![CDATA[SAST vs SCA: why your CI pipeline needs both]]></title><description><![CDATA[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). Bot]]></description><link>https://depwarden.hashnode.dev/sast-vs-sca-why-your-ci-pipeline-needs-both</link><guid isPermaLink="true">https://depwarden.hashnode.dev/sast-vs-sca-why-your-ci-pipeline-needs-both</guid><dc:creator><![CDATA[Rushabh Shah]]></dc:creator><pubDate>Mon, 29 Jun 2026 11:24:06 GMT</pubDate><content:encoded><![CDATA[<p>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.</p>
<h2>What SAST scans</h2>
<p><strong>Static Application Security Testing (SAST)</strong> 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 <code>MD5</code> where <code>bcrypt</code> should be. An HTTP endpoint that passes user input to a shell command.</p>
<p>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:</p>
<pre><code class="language-javascript">const result = db.query(`SELECT * FROM users WHERE id = ${req.params.id}`);
</code></pre>
<p>...because the user-controlled value <code>req.params.id</code> 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.</p>
<h2>What SCA scans</h2>
<p><strong>Software Composition Analysis (SCA)</strong> reads your dependency manifest — <code>package.json</code>, <code>requirements.txt</code>, <code>pom.xml</code>, <code>go.mod</code> — and checks every package (direct and transitive) against a vulnerability database like OSV. If you're running <code>lodash@4.17.4</code>, which has a known prototype pollution CVE, SCA flags it.</p>
<p>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.</p>
<h2>The blind spots in each</h2>
<p><strong>What SAST can't see:</strong></p>
<ul>
<li><p>Vulnerabilities introduced by the open-source packages you import</p>
</li>
<li><p>Supply-chain attacks with no CVE (typosquatting, dependency confusion)</p>
</li>
<li><p>Runtime configuration mistakes in cloud infrastructure</p>
</li>
<li><p>Bugs that only manifest under specific execution conditions</p>
</li>
</ul>
<p><strong>What SCA can't see:</strong></p>
<ul>
<li><p>Security bugs in the code your team writes</p>
</li>
<li><p>Hardcoded credentials in your own source files</p>
</li>
<li><p>Weak cryptographic choices in your own logic</p>
</li>
<li><p>Framework misconfigurations (CSRF disabled, DEBUG mode on, CORS wildcard)</p>
</li>
</ul>
<p>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.</p>
<h2>A concrete example: two reports, two attack surfaces</h2>
<p>Imagine a Node.js API with these two problems:</p>
<p><strong>Problem A (SAST territory):</strong> In <code>controllers/user.js</code>, you build a MongoDB query with string interpolation from <code>req.query.username</code>. This is a NoSQL injection vulnerability. It's in your code. No CVE exists for it. SCA will never find it.</p>
<p><strong>Problem B (SCA territory):</strong> You depend on <code>jsonwebtoken@8.5.1</code>, which has a known algorithm confusion vulnerability (CVE-2022-23529). Your code calls <code>jwt.verify()</code> correctly. SAST may not flag it because the call looks correct in isolation — the vulnerability is in the library's internal implementation.</p>
<p>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.</p>
<h2>The combined CI gate</h2>
<p>The most effective CI configuration runs both in parallel:</p>
<pre><code class="language-yaml"># 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
</code></pre>
<p>This single step:</p>
<ul>
<li><p>Parses <code>package-lock.json</code>, resolves the full transitive dependency tree, checks OSV/KEV/EPSS for vulnerabilities and typosquats</p>
</li>
<li><p>Walks <code>./src</code>, detects languages, runs pattern + taint analysis across all source files against 300+ security rules</p>
</li>
<li><p>Fails the build if either scan produces a HIGH or CRITICAL finding</p>
</li>
</ul>
<p>Two scan types, one gate, no account required.</p>
<h2>Prioritization across both</h2>
<p>When findings come from both SAST and SCA, the combined priority order:</p>
<ol>
<li><p><strong>SCA: KEV-listed + direct dependency + fix available</strong> — attackers are actively using this, you can fix it now</p>
</li>
<li><p><strong>SAST: HIGH-confidence injection/RCE finding</strong> — user input confirmed flowing to a dangerous sink</p>
</li>
<li><p><strong>SCA: HIGH CVSS + EPSS &gt; 0.10 + fix available</strong> — elevated exploitation probability</p>
</li>
<li><p><strong>SAST: hardcoded credential</strong> — immediate exposure risk if it reaches a repo</p>
</li>
<li><p><strong>Everything else</strong> — triage by severity and confidence, don't block releases on MEDIUM/LOW</p>
</li>
</ol>
<h2>What DepWarden gives you</h2>
<p>DepWarden combines both scanners in one tool, free and without an account:</p>
<ul>
<li><p><strong>SCA</strong> across 11 package ecosystems (npm, PyPI, Maven, Gradle, Go, Cargo, Composer, RubyGems, NuGet, Dart, Swift) with OSV/KEV/EPSS enrichment and exploitability-first prioritization</p>
</li>
<li><p><strong>SAST</strong> across 15 languages and IaC formats, with 300+ security rules covering injection, XSS, secrets, weak crypto, framework-specific misconfigurations, and more</p>
</li>
<li><p>A single <strong>GitHub Action</strong> that gates pull requests with both scanners in one step</p>
</li>
</ul>
<p>The only scanner you need in CI to cover the two main attack paths against your application.</p>
<p>See also: <a href="https://depwarden.in/blog/what-is-sast">what is SAST?</a>, <a href="https://depwarden.in/blog/cvss-epss-kev-guide">CVSS, EPSS and KEV guide</a>, <a href="https://depwarden.in/blog/free-snyk-alternative">free Snyk alternative</a>.</p>
]]></content:encoded></item></channel></rss>