<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Satyendra Vemulapalli</title>
    <description>The latest articles on Forem by Satyendra Vemulapalli (@sathyendrav).</description>
    <link>https://forem.com/sathyendrav</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1337792%2Fc12cffa3-528e-493b-a00d-e85f1d70b3d7.jpg</url>
      <title>Forem: Satyendra Vemulapalli</title>
      <link>https://forem.com/sathyendrav</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/sathyendrav"/>
    <language>en</language>
    <item>
      <title>I Built a Zero-Dependency Supply-Chain Security Scanner for Node.js — 18 Checks, One Command</title>
      <dc:creator>Satyendra Vemulapalli</dc:creator>
      <pubDate>Thu, 02 Apr 2026 11:50:47 +0000</pubDate>
      <link>https://forem.com/sathyendrav/i-built-a-zero-dependency-supply-chain-security-scanner-for-nodejs-18-checks-one-command-39b9</link>
      <guid>https://forem.com/sathyendrav/i-built-a-zero-dependency-supply-chain-security-scanner-for-nodejs-18-checks-one-command-39b9</guid>
      <description>&lt;h2&gt;
  
  
  The npm install trust problem
&lt;/h2&gt;

&lt;p&gt;When you run &lt;code&gt;npm install&lt;/code&gt;, you're trusting hundreds of strangers to not run malicious code on your machine. And that trust has been broken — repeatedly.&lt;/p&gt;

&lt;p&gt;Packages like &lt;strong&gt;event-stream&lt;/strong&gt;, &lt;strong&gt;ua-parser-js&lt;/strong&gt;, and &lt;strong&gt;coa&lt;/strong&gt; were hijacked to steal credentials, install backdoors, and exfiltrate data through &lt;code&gt;postinstall&lt;/code&gt; scripts. By the time &lt;code&gt;npm install&lt;/code&gt; finishes, the damage is already done.&lt;/p&gt;

&lt;p&gt;The traditional answer? &lt;code&gt;npm audit&lt;/code&gt;. But that only catches &lt;strong&gt;known CVEs&lt;/strong&gt;. It completely misses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Typosquatted packages hiding in your lockfile&lt;/li&gt;
&lt;li&gt;Dropper packages that &lt;code&gt;curl | sh&lt;/code&gt; in &lt;code&gt;postinstall&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Tampered &lt;code&gt;package.json&lt;/code&gt; files swapped after install&lt;/li&gt;
&lt;li&gt;C2 domains hardcoded in dependencies&lt;/li&gt;
&lt;li&gt;Stolen npm tokens used to publish without CI/CD provenance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I needed something better. So I built it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Meet &lt;code&gt;sec-check&lt;/code&gt; — one command, 18 security checks, zero dependencies
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @sathyendra/security-checker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the entire setup. No config files, no API keys, no build step. It scans your project and tells you what's wrong:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;──────────────────────────────────────────────────────────────────────
  @sathyendra/security-checker — Diagnostic Report
──────────────────────────────────────────────────────────────────────
  🚨 CRITICAL: plain-crypto-js detected in node_modules       [FIXABLE]
  🚨 LOCKFILE: flatmap-stream found in dependency tree         [FIXABLE]
  🚨 DROPPER: suspicious-pkg has postinstall with curl | sh   [MANUAL]
  ⚠️  PROVENANCE: "axios@1.7.0" — Manual Publish Detected      [MANUAL]
  ⚠️  OUTDATED: lodash@3.10.1 — 2 major versions behind        [MANUAL]
──────────────────────────────────────────────────────────────────────
  5 threat(s) found | 2 fixable | 3 require manual review
  Run with --fix to auto-remediate fixable threats.
──────────────────────────────────────────────────────────────────────
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why zero dependencies?
&lt;/h3&gt;

&lt;p&gt;A security tool that pulls in 200 transitive dependencies is an oxymoron. Every dependency is attack surface. &lt;code&gt;sec-check&lt;/code&gt; uses &lt;strong&gt;only Node.js built-ins&lt;/strong&gt; (&lt;code&gt;fs&lt;/code&gt;, &lt;code&gt;path&lt;/code&gt;, &lt;code&gt;crypto&lt;/code&gt;, &lt;code&gt;child_process&lt;/code&gt;, &lt;code&gt;os&lt;/code&gt;, &lt;code&gt;https&lt;/code&gt;) — nothing from npm. The tool that checks your supply chain has no supply chain of its own.&lt;/p&gt;




&lt;h2&gt;
  
  
  What does it actually check?
&lt;/h2&gt;

&lt;p&gt;Here's the full list of 18 detection modules:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;What it catches&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Malicious packages&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Known bad packages (e.g. &lt;code&gt;plain-crypto-js&lt;/code&gt;) in &lt;code&gt;node_modules&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;npm audit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High/critical CVEs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Deep lockfile audit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Malicious packages buried in the full dependency tree&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Dropper detection&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Packages with &lt;code&gt;postinstall&lt;/code&gt; scripts but no real code — the "install-and-run" pattern&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Integrity checksums&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Post-install tampering (hash mismatch vs lockfile and registry)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Decoy swap detection&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;package.md&lt;/code&gt;, &lt;code&gt;.bak&lt;/code&gt; artifacts — the exact trick used in the Axios attack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;TeamPCP / WAVESHAPER&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;RAT artifacts, persistence mechanisms across Windows/macOS/Linux&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;C2 domains&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Known command-and-control domains in your hosts file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Cross-ecosystem (PyPI)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Malicious PyPI packages from the same campaigns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Python stager detection&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Suspicious &lt;code&gt;.py&lt;/code&gt; files with backdoor patterns in Node.js projects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Malicious .pth files&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Python's "importless execution" technique in site-packages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Provenance verification&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Popular packages published without CI/CD provenance (stolen token indicator)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Shadow execution&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;LD_PRELOAD&lt;/code&gt;, &lt;code&gt;DYLD_INSERT_LIBRARIES&lt;/code&gt;, &lt;code&gt;NODE_OPTIONS --require&lt;/code&gt; hijacking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Outdated dependencies&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Major version drift = no security patches&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Registry configuration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dependency Confusion via non-official or HTTP registries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Lifecycle script injection&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;`curl&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Dependency script sandboxing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Same analysis on every dependency's lifecycle scripts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Secrets detection&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;{% raw %}&lt;code&gt;.env&lt;/code&gt; files, hardcoded &lt;code&gt;NPM_TOKEN&lt;/code&gt;, AWS keys, GitHub tokens, PEM keys&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Plus bonus checks: &lt;strong&gt;npm doctor&lt;/strong&gt;, &lt;strong&gt;lockfile enforcement&lt;/strong&gt;, &lt;strong&gt;SSRF/C2 blocklist scan&lt;/strong&gt;, &lt;strong&gt;environment variable audit&lt;/strong&gt;, and &lt;strong&gt;Lockfile Sentinel&lt;/strong&gt; (hash comparison against known-compromised database).&lt;/p&gt;




&lt;h2&gt;
  
  
  The killer feature: Zero Trust Shield
&lt;/h2&gt;

&lt;p&gt;Instead of the traditional "install and hope" workflow, Shield gives you defense-in-depth:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sec-check &lt;span class="nt"&gt;--shield&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ▸ Stage 1: Pre-flight — scan lockfile &amp;amp; config BEFORE downloading anything
  ▸ Stage 2: Isolated Install — npm install --ignore-scripts (no code execution)
  ▸ Stage 3: Post-vetting — full integrity &amp;amp; security scan on downloaded files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the workflow that would have caught every major npm supply-chain attack. The malicious &lt;code&gt;postinstall&lt;/code&gt; never runs because Stage 2 uses &lt;code&gt;--ignore-scripts&lt;/code&gt;, and Stage 3 catches any artifacts before you run your code.&lt;/p&gt;




&lt;h2&gt;
  
  
  OWASP Top 10 mapping
&lt;/h2&gt;

&lt;p&gt;Three Shield features map directly to OWASP risk categories, so you can reference them in compliance conversations:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;OWASP Risk&lt;/th&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;A03: Injection&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Script Blocker&lt;/td&gt;
&lt;td&gt;Flags dangerous commands in lifecycle hooks before execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;A05: Misconfiguration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Registry Guard&lt;/td&gt;
&lt;td&gt;Rejects non-official or HTTP registries across &lt;code&gt;.npmrc&lt;/code&gt;, env, and lockfile&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;A08: Integrity Failures&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lockfile Sentinel&lt;/td&gt;
&lt;td&gt;Compares lockfile hashes against known-compromised database&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  CI/CD integration in 30 seconds
&lt;/h2&gt;

&lt;p&gt;Add one line to your GitHub Actions workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Security scan&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npx @sathyendra/security-checker&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exit code &lt;code&gt;1&lt;/code&gt; = threats found = pipeline fails. That's it.&lt;/p&gt;

&lt;p&gt;For structured output (dashboards, artifact collection):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sec-check &lt;span class="nt"&gt;--json&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; scan-results.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For compliance artifacts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sec-check &lt;span class="nt"&gt;--vex-out&lt;/span&gt;   &lt;span class="c"&gt;# CycloneDX VEX document&lt;/span&gt;
sec-check &lt;span class="nt"&gt;--sbom&lt;/span&gt;      &lt;span class="c"&gt;# CycloneDX SBOM&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Auto-fix what can be fixed
&lt;/h2&gt;

&lt;p&gt;Not into manual cleanup? The &lt;code&gt;--fix&lt;/code&gt; flag handles the boring stuff:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sec-check &lt;span class="nt"&gt;--fix&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Threat&lt;/th&gt;
&lt;th&gt;What &lt;code&gt;--fix&lt;/code&gt; does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Malicious packages&lt;/td&gt;
&lt;td&gt;&lt;code&gt;npm uninstall &amp;lt;package&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Audit vulnerabilities&lt;/td&gt;
&lt;td&gt;&lt;code&gt;npm audit fix&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Integrity mismatches&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;npm ci&lt;/code&gt; (clean reinstall)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Swap artifacts&lt;/td&gt;
&lt;td&gt;Deletes the artifact file&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Threats that need human judgment (provenance issues, C2 indicators, system artifacts) stay as &lt;code&gt;[MANUAL]&lt;/code&gt; — the tool never makes destructive decisions for you.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick start
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# One-shot scan (no install needed)&lt;/span&gt;
npx @sathyendra/security-checker

&lt;span class="c"&gt;# Install as dev dependency&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @sathyendra/security-checker

&lt;span class="c"&gt;# Auto-fix fixable threats&lt;/span&gt;
sec-check &lt;span class="nt"&gt;--fix&lt;/span&gt;

&lt;span class="c"&gt;# Protect every future install&lt;/span&gt;
sec-check &lt;span class="nt"&gt;--init&lt;/span&gt;

&lt;span class="c"&gt;# Full Zero Trust workflow&lt;/span&gt;
sec-check &lt;span class="nt"&gt;--shield&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Try it now
&lt;/h2&gt;

&lt;p&gt;The best way to evaluate it is to point it at your own project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;your-project
npx @sathyendra/security-checker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it finds something, that's a good thing — you just caught it before an attacker exploited it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Links:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📦 &lt;a href="https://www.npmjs.com/package/@sathyendra/security-checker" rel="noopener noreferrer"&gt;npm: @sathyendra/security-checker&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🔗 &lt;a href="https://github.com/sathyendrav/security-checker" rel="noopener noreferrer"&gt;GitHub: sathyendrav/security-checker&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📄 &lt;a href="https://github.com/sathyendrav/security-checker#readme" rel="noopener noreferrer"&gt;Full README with all 18 checks explained&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;If this is useful, a ⭐ on GitHub or an &lt;code&gt;npm i&lt;/code&gt; helps more than you'd think. Questions, feature requests, or "it flagged something weird" — open an issue, I read all of them.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>npm</category>
      <category>opensource</category>
      <category>security</category>
    </item>
  </channel>
</rss>
