<?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>DEV Community: jomynn</title>
    <description>The latest articles on DEV Community by jomynn (@jomynn).</description>
    <link>https://dev.to/jomynn</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1281364%2F43541c24-85d1-4bb3-8236-e7ef7b1821b7.png</url>
      <title>DEV Community: jomynn</title>
      <link>https://dev.to/jomynn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jomynn"/>
    <language>en</language>
    <item>
      <title>Manually Proving and Documenting an IDOR (CWE-639) — A Full Walkthrough</title>
      <dc:creator>jomynn</dc:creator>
      <pubDate>Mon, 24 Aug 2026 13:01:03 +0000</pubDate>
      <link>https://dev.to/jomynn/manually-proving-and-documenting-an-idor-cwe-639-a-full-walkthrough-m7m</link>
      <guid>https://dev.to/jomynn/manually-proving-and-documenting-an-idor-cwe-639-a-full-walkthrough-m7m</guid>
      <description>&lt;p&gt;Most IDOR write-ups stop at "change the ID in the URL and you get someone else's data."&lt;br&gt;
That's the easy part. The part that actually matters — proving it rigorously, ruling out&lt;br&gt;
the boring explanation, and turning it into a report someone can act on — usually gets&lt;br&gt;
skipped.&lt;/p&gt;

&lt;p&gt;I recorded a full walkthrough doing exactly that, end to end, against a deliberately&lt;br&gt;
vulnerable local training target.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/8RlBRBQBUAw"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  The bug
&lt;/h2&gt;

&lt;p&gt;A simple invoice endpoint, &lt;code&gt;GET /invoices/:id&lt;/code&gt;. It checks that &lt;em&gt;someone&lt;/em&gt; is logged in&lt;br&gt;
(401 if not), but never checks that the logged-in identity actually &lt;em&gt;owns&lt;/em&gt; the invoice&lt;br&gt;
it's returning:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
js
`invoices.find(inv =&amp;gt; inv.id === Number(req.params.id))
// no invoice.owner === session.user check`


Log in as any user, change the number in the URL, read anyone's invoice. Classic
CWE-639 — Authorization Bypass Through User-Controlled Key, and it maps directly to:

OWASP A01:2021 — Broken Access Control
API1:2023 — Broken Object Level Authorization (BOLA)

**What the walkthrough actually covers**
The video isn't just "look, it's broken" — it's the full evidence chain a real assessment
needs:

Timestamp   Phase
0:00    Capture two separate identities (alice, bob)
1:26:19 Prove cross-owner access live, in-browser
2:06:26 Pull raw request/response evidence from the network tab
2:52:04 Run a negative control — unauthenticated request, confirm 401
4:08:06 Confirm independently with an automated IDOR probe
6:12:03 Create a structured finding (CWE/OWASP/API mapping + evidence)
8:12:07 Structure the evidence for review
10:29:00    Export a report
The negative control is the step people skip most often, and it's the one that separates
"broken access control" from "there's just no auth at all" — an important distinction if
you're writing this up for a real triager.

**Why the control matters**
Without it, you've only shown that an authenticated user can read someone else's data —
you haven't ruled out the (much less interesting) possibility that the endpoint has no
auth check whatsoever. Hitting the same endpoint with zero session and getting a clean
401 proves the app does enforce authentication — it just never enforces ownership.
That's the difference between a one-line "missing auth" bug and a systemic
authorization-model gap.

**Fix**
Load the object, then check ownership before returning it:

`const invoice = invoices.find(inv =&amp;gt; inv.id === Number(req.params.id));
if (!invoice || invoice.owner !== session.user) {
  return res.status(404).end(); // or 403 — avoid leaking existence via 401 vs 403
}`

Every object access needs to be authorized, not just authenticated — that's the whole bug
in one sentence.

Try it yourself → https://github.com/sendwavehub/scan-target-demo-apps
Windows Store https://apps.microsoft.com/detail/9pj0j7bk1m27?hl=en-US
Web Site https://Sendwavehub.tech/en/apps/ai-security-studio-4 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>api</category>
      <category>cybersecurity</category>
      <category>security</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Building an Offline AI Security Scanner That Doesn't Hallucinate Findings</title>
      <dc:creator>jomynn</dc:creator>
      <pubDate>Sat, 22 Aug 2026 06:47:26 +0000</pubDate>
      <link>https://dev.to/jomynn/building-an-offline-ai-security-scanner-that-doesnt-hallucinate-findings-3oab</link>
      <guid>https://dev.to/jomynn/building-an-offline-ai-security-scanner-that-doesnt-hallucinate-findings-3oab</guid>
      <description>&lt;p&gt;How AiSec Studio pipes every scan through parser → rule engine → knowledge graph before a local LLM ever sees it — and why that order matters. 60-second Auto Scan demo included.&lt;/p&gt;

&lt;p&gt;Most "AI-powered" security scanners work the same way under the hood: grab the target's code or HTTP responses, stuff them into an LLM prompt, and ask it to find vulnerabilities. It demos well. It also hallucinates constantly — the model pattern-matches on plausible-looking code and reports things that were never exploitable, or never there at all.&lt;/p&gt;

&lt;p&gt;I've been building &lt;strong&gt;AiSec Studio&lt;/strong&gt;, an offline AI security research platform, around the opposite assumption: &lt;strong&gt;the LLM should never be the thing that discovers a vulnerability.&lt;/strong&gt; It should only reason over what a deterministic system already found.&lt;/p&gt;

&lt;p&gt;Here's a 60-second walkthrough of the Auto Scan lane — target URL in, reviewed report out — followed by how the pipeline behind it is actually built.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/xux8-H7e2_0"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  The pipeline
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Parser → Rule Engine → Knowledge Retrieval → Summarization → LLM → Reasoning → Finding → Report
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every stage exists to keep the model away from raw, untrusted input and away from the job of &lt;em&gt;deciding&lt;/em&gt; something is a vulnerability.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Parse before you analyze
&lt;/h3&gt;

&lt;p&gt;Before any AI touches a target, the code goes through &lt;strong&gt;Roslyn&lt;/strong&gt; (for .NET) or &lt;strong&gt;Tree-sitter&lt;/strong&gt; (everything else) to extract:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AST&lt;/li&gt;
&lt;li&gt;Call graph / dependency graph&lt;/li&gt;
&lt;li&gt;Controllers, services, routes&lt;/li&gt;
&lt;li&gt;Authentication and authorization wiring&lt;/li&gt;
&lt;li&gt;Configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the same reason a compiler front-end exists before an optimizer runs — you don't want probabilistic reasoning operating on unstructured text when a deterministic parser can hand you a structured graph instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Rule engine does the actual discovering
&lt;/h3&gt;

&lt;p&gt;Vulnerability &lt;em&gt;discovery&lt;/em&gt; is a deterministic-rules job, not an LLM job:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Secret detection&lt;/li&gt;
&lt;li&gt;JWT validation (including algorithm-confusion, CWE-347)&lt;/li&gt;
&lt;li&gt;Header / cookie / CSP / CORS analysis&lt;/li&gt;
&lt;li&gt;SQL and XSS pattern detection&lt;/li&gt;
&lt;li&gt;Dependency and configuration analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this requires a model. It requires correct rules, and it's auditable — you can point at exactly which regex or AST pattern fired for a given finding.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Everything lands in a per-engagement Knowledge Graph
&lt;/h3&gt;

&lt;p&gt;Pages, APIs, JS bundles, auth flows, technologies, and findings all get cross-linked by canonical route into one persistent graph per engagement. This is what lets risk &lt;em&gt;propagate&lt;/em&gt; — a leaked JWT secret on one endpoint and an IDOR on a related endpoint aren't two isolated findings, they're connected nodes with compounding risk.&lt;/p&gt;

&lt;p&gt;It also means re-scanning is incremental: unchanged parts of the graph don't get re-analyzed.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. The LLM only reasons over structured summaries — never raw input
&lt;/h3&gt;

&lt;p&gt;This is the boundary that matters most. The local LLM (Qwen2.5-Coder or DeepSeek-Coder, served through Ollama or llama.cpp — no cloud API, ever, at any point) is only handed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Structured summaries from the rule engine + knowledge graph&lt;/li&gt;
&lt;li&gt;Never raw HTTP responses&lt;/li&gt;
&lt;li&gt;Never raw bundles&lt;/li&gt;
&lt;li&gt;Never raw source dumped wholesale&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Its job is explanation and correlation: &lt;em&gt;why&lt;/em&gt; does this finding matter, &lt;em&gt;what's&lt;/em&gt; the business impact, &lt;em&gt;which&lt;/em&gt; of these twelve findings should a human look at first, &lt;em&gt;how&lt;/em&gt; should the final report read. It doesn't get to originate a finding out of nothing, because it never sees anything a finding could be originated from.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Confidence tiers instead of confident-sounding guesses
&lt;/h3&gt;

&lt;p&gt;Every finding is tagged:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Confirmed&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Likely&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Possible&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hypothesis&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the evidence doesn't support any of those, the system returns &lt;strong&gt;"Needs Manual Verification"&lt;/strong&gt; instead of inventing a conclusion. A finding without evidence, reasoning, a confidence score, a risk level, and a suggested fix isn't a finding — it's a guess wearing a report template.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the demo actually shows
&lt;/h2&gt;

&lt;p&gt;Mapped to the pipeline above, the video is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Auto Scan panel&lt;/strong&gt; — set the target URL&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scan Anonymously&lt;/strong&gt; — passive discovery only, rule-engine + parser stage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scan All&lt;/strong&gt; — runs discovery → analysis → active testing end to end&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Investigate → Finding Report&lt;/strong&gt; — step through findings one by one, each with its evidence and confidence tier attached&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Report → Markdown&lt;/strong&gt; — export the write-up&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open Report&lt;/strong&gt; — hand it straight to the OS's default viewer&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Nothing in that flow leaves the machine. No target data, no code, no findings go to a cloud API at any point — that's a hard architectural constraint, not a configuration toggle.&lt;/p&gt;

&lt;p&gt;Try it yourself: &lt;a href="https://github.com/sendwavehub/scan-target-demo-apps" rel="noopener noreferrer"&gt;https://github.com/sendwavehub/scan-target-demo-apps&lt;/a&gt;&lt;br&gt;
Free download: &lt;a href="https://apps.microsoft.com/store/detail/9PJ0J7BK1M27?cid=DevShareMCLPCB" rel="noopener noreferrer"&gt;https://apps.microsoft.com/store/detail/9PJ0J7BK1M27?cid=DevShareMCLPCB&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Web download:&lt;br&gt;
&lt;a href="https://sendwavehub.tech/th/apps/ai-security-studio-4" rel="noopener noreferrer"&gt;https://sendwavehub.tech/th/apps/ai-security-studio-4&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>cybersecurity</category>
      <category>llm</category>
      <category>security</category>
    </item>
    <item>
      <title>We caught a SQL injection with an offline AI security scanner — here's the exact query it found</title>
      <dc:creator>jomynn</dc:creator>
      <pubDate>Thu, 20 Aug 2026 13:57:45 +0000</pubDate>
      <link>https://dev.to/jomynn/we-caught-a-sql-injection-with-an-offline-ai-security-scanner-heres-the-exact-query-it-found-4187</link>
      <guid>https://dev.to/jomynn/we-caught-a-sql-injection-with-an-offline-ai-security-scanner-heres-the-exact-query-it-found-4187</guid>
      <description>&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/GknBmsqaFk4"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  The bug
&lt;/h2&gt;

&lt;p&gt;Here's a login endpoint from a small Express demo app&lt;br&gt;
(&lt;a href="https://github.com/sendwavehub/scan-target-demo-apps" rel="noopener noreferrer"&gt;&lt;code&gt;scan-target-demo-apps/apps/01-sql-injection&lt;/code&gt;&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`SELECT id, username, email, is_admin FROM users
                  WHERE username = '&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;' AND password = '&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;'`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You've seen this shape before. &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; go straight into the SQL string — no&lt;br&gt;
parameter binding, no escaping. Submit &lt;code&gt;admin' --&lt;/code&gt; as the username and anything as the password,&lt;br&gt;
and the query becomes:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;is_admin&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'admin'&lt;/span&gt; &lt;span class="c1"&gt;-- ' AND password = 'anything'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;--&lt;/code&gt; comments out the rest of the line. The password check never runs. &lt;code&gt;{"ok": true}&lt;/code&gt;, logged in&lt;br&gt;
as &lt;code&gt;admin&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Classic CWE-89, OWASP A03:2021. Nothing novel here — the interesting part is what caught it.&lt;/p&gt;
&lt;h2&gt;
  
  
  What actually caught it
&lt;/h2&gt;

&lt;p&gt;We ran this target through &lt;strong&gt;AI Security Studio&lt;/strong&gt;, an offline security research platform we've&lt;br&gt;
been building. No cloud calls, no code leaves the machine — everything you're about to read&lt;br&gt;
happened on a laptop with no network access to anywhere but &lt;code&gt;localhost:3001&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The important design decision: &lt;strong&gt;the LLM never sees raw source code or raw HTTP traffic.&lt;/strong&gt;&lt;br&gt;
The pipeline looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Parser → Rule Engine → Knowledge Retrieval → Summarization → LLM → Reasoning → Finding → Report
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A deterministic parser and rule engine do the actual &lt;em&gt;finding&lt;/em&gt;. The local LLM only explains&lt;br&gt;
&lt;em&gt;already-discovered&lt;/em&gt; evidence — it's not asked to eyeball a codebase and guess where the bugs&lt;br&gt;
might be. If the evidence isn't there, the platform is built to say "Needs Manual Verification"&lt;br&gt;
instead of inventing a conclusion.&lt;/p&gt;

&lt;p&gt;For this run, that meant:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Point the scanner at &lt;code&gt;http://localhost:3001&lt;/code&gt; as scope.&lt;/li&gt;
&lt;li&gt;Let it run a real passive crawl — no exploitation, just discovery.&lt;/li&gt;
&lt;li&gt;Run a source scan against the target's own directory.&lt;/li&gt;
&lt;li&gt;The rule engine flags the string-concatenated query pattern in &lt;code&gt;server.js:56&lt;/code&gt; and the missing
auth check on the state-changing &lt;code&gt;POST /login&lt;/code&gt; route.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The generated report includes the actual vulnerable line as evidence, not a generic "possible SQL&lt;br&gt;
injection" label:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Source&lt;/span&gt; &lt;span class="nx"&gt;preview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`SELECT id, username, email, is_admin FROM users WHERE username = '&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;' AND password = '&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;'`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Risk: High. Root cause: CWE-89 (and a separate CWE-306 finding for the missing authorization&lt;br&gt;
check). Suggested fix: parameterized queries. Confidence explicitly marked — some findings from&lt;br&gt;
this pass are "Confirmed," others are flagged "Needs Manual Verification" rather than asserted,&lt;br&gt;
because header/config-level evidence alone doesn't prove exploitability the way a manual&lt;br&gt;
Active Test / Repeater run does.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why "offline" is the actual point
&lt;/h2&gt;

&lt;p&gt;It's easy to gloss over "runs locally" as a checkbox feature. In practice it means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can point it at unreleased/internal code without a vendor's cloud pipeline ever touching it.&lt;/li&gt;
&lt;li&gt;The rule engine — not the LLM — does secret detection, JWT/header/cookie analysis, and pattern
matching, so results are reproducible and don't drift between runs.&lt;/li&gt;
&lt;li&gt;The LLM's job shrinks to something it's actually reliable at: turning structured findings into a
clear explanation, not hunting for vulnerabilities in raw text.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Try it yourself
&lt;/h2&gt;

&lt;p&gt;The demo app is intentionally vulnerable and open source — safe to point any scanner at, including&lt;br&gt;
this one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Demo target: &lt;a href="https://github.com/sendwavehub/scan-target-demo-apps" rel="noopener noreferrer"&gt;https://github.com/sendwavehub/scan-target-demo-apps&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;AI Security Studio: &lt;a href="https://apps.microsoft.com/store/detail/9PJ0J7BK1M27?cid=DevShareMCLPCB" rel="noopener noreferrer"&gt;https://apps.microsoft.com/store/detail/9PJ0J7BK1M27?cid=DevShareMCLPCB&lt;/a&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://sendwavehub.tech/th/apps/ai-security-studio-4" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsendwavehub.tech%2Fog-default-blog.png" height="auto" class="m-0"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://sendwavehub.tech/th/apps/ai-security-studio-4" rel="noopener noreferrer" class="c-link"&gt;
            SendWaveHub — Hire AI Employees for Your Business Email
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            AI Employees that read, process, and respond to your business email. AI Accountant live now — email marketing, eSign, PDF tools, and automation included. Free plan.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsendwavehub.tech%2Fsendwave-icon.svg"&gt;
          sendwavehub.tech
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Built for security researchers, pentesters, and AppSec teams doing work they're authorized to do.&lt;/p&gt;

&lt;p&gt;Next up in this series: stored XSS — one comment field, every visitor who loads the page.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>javascript</category>
      <category>security</category>
      <category>sql</category>
    </item>
    <item>
      <title>We Built a Security Scanner That Automates Itself — and Never Touches the Cloud</title>
      <dc:creator>jomynn</dc:creator>
      <pubDate>Tue, 18 Aug 2026 07:51:55 +0000</pubDate>
      <link>https://dev.to/jomynn/we-built-a-security-scanner-that-automates-itself-and-never-touches-the-cloud-48h6</link>
      <guid>https://dev.to/jomynn/we-built-a-security-scanner-that-automates-itself-and-never-touches-the-cloud-48h6</guid>
      <description>&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/0Dyc07P3AuI"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;How AI Security Studio's ASS Script engine lets you record, replay, and narrate a full offline security scan — deterministic analysis first, local LLM reasoning second.&lt;br&gt;
Most "AI-powered" security tools have the same dependency: your code has to leave your machine to get an answer. That's a non-starter for a lot of security research — client engagements under NDA, regulated codebases, or just not wanting proprietary source sitting in someone else's inference logs.&lt;/p&gt;

&lt;p&gt;AI Security Studio is built the other way: &lt;strong&gt;everything runs locally.&lt;/strong&gt; Local LLM (Ollama / llama.cpp / LM Studio), no external API calls, no telemetry. This post walks through one specific piece of it — the automation engine we call &lt;strong&gt;ASS Script&lt;/strong&gt; — and the small offline pipeline I built on top of it to generate narrated, subtitled walkthrough videos without touching a cloud TTS API either.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deterministic first, LLM second
&lt;/h2&gt;

&lt;p&gt;Before any AI touches a finding, it goes through:&lt;/p&gt;

&lt;p&gt;Parser → Rule Engine → Knowledge Retrieval → Summarization → LLM → Reasoning → Finding → Report&lt;/p&gt;

&lt;p&gt;Static parsing (Roslyn / Tree-sitter) and a deterministic rule engine — secret detection, header analysis, JWT validation, SQLi/XSS pattern matching — do the actual discovery. The LLM never sees raw source. It only reasons over structured summaries the rule engine already produced: explaining &lt;em&gt;why&lt;/em&gt; something is a bug, correlating findings, drafting the writeup. If the evidence isn't solid, the system is designed to say "needs manual verification" rather than invent a conclusion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Record once, replay forever
&lt;/h2&gt;

&lt;p&gt;ASS Script (AI Security Studio Automation Script) is an iMacro-style record/play/edit engine built on the same node-graph designer used elsewhere in the app. Scripts are plain YAML — readable and diffable, not an opaque macro blob:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
yaml
nodes:
  - id: "n5"
    kind: "GuiInteract"
    title: "Click Find bugs on this URL"
    notes: "Imports the URL as a one-host scope. Scope import only — sends no network traffic by itself."
    parameters:
      control: "ScanUrlButton"
      action: "click"
  - id: "n9"
    kind: "GuiInteract"
    title: "Click Scan All"
    notes: "Kicks off the panel's real passive sweep — genuinely live crawl traffic, same as a human operator would trigger."
    parameters:
      control: "ScanAllButton"
      action: "click"
  - id: "n14"
    kind: "RunScan"
    title: "Live source scan"
    notes: "Runs the real ScanService against the target's own source directory — footage shows a real scan, not a mockup."
    parameters:
      path: "/path/to/target/source"
Each node is a real GUI action or a real scan/analyzer call — no simulated steps. You record a workflow once, then replay it identically from the GUI or the CLI (workflow run some-script.adrflow.yaml).

The fun side quest: offline narration for the demo videos
We wanted walkthrough videos with voiceover and subtitles, but the "generate subtitles" step usually means uploading video/audio to a cloud transcription or TTS API — which would be a little embarrassing for a project whose whole pitch is "nothing leaves your machine."

So the pipeline is: write the shot list as a markdown table (beat / timecode / on-screen action / caption / VO line), then run it through a small Python script that:

Parses the table into timed cues
Synthesizes each VO line with macOS's built-in say (fully offline TTS)
Measures each clip's real duration with ffprobe
Concatenates them into one narration track with ffmpeg
Emits a .srt timed to the actual synthesized audio, not a guess
Flags any beat where the narration runs longer than the video's planned window, so you know exactly where to hold a shot longer
The output is a narration.wav + captions.srt pair generated entirely from tools already on the machine — no API keys, no cloud dependency, same philosophy as the scanner itself.

Why this matters beyond the demo video
The pattern generalizes: treat the LLM/AI step as optional and swappable, put the deterministic and local-first parts first. It's true for the security pipeline (rule engine before LLM) and it turned out to be just as true for the tooling around the project (offline TTS before cloud TTS). If your architecture assumes "AI" every time it actually means "network call," that's worth questioning.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>security</category>
      <category>ai</category>
      <category>automation</category>
      <category>opensource</category>
    </item>
    <item>
      <title>🛡️ NPM Safety Guard — All 23 Security Layers Explained</title>
      <dc:creator>jomynn</dc:creator>
      <pubDate>Mon, 29 Jun 2026 06:20:23 +0000</pubDate>
      <link>https://dev.to/jomynn/npm-safety-guard-all-23-security-layers-explained-1l0</link>
      <guid>https://dev.to/jomynn/npm-safety-guard-all-23-security-layers-explained-1l0</guid>
      <description>&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/wd6ZNTIoYKE"&gt;
  &lt;/iframe&gt;
&lt;br&gt;
Every npm project is one malicious package away from a supply-chain breach. NPM Safety Guard catches threats that npm audit completely misses — from DPRK backdoors and typosquatted packages, to exposed API keys and AI credential theft hidden inside your node_modules.&lt;/p&gt;

&lt;p&gt;This video walks through all 23 detection layers, one by one, showing exactly what each layer catches and how it protects your project in real time.&lt;br&gt;
🛡️ Intro&lt;br&gt;
NPM Safety Guard is the most comprehensive npm security scanner for developers. It ships as a VS Code extension (also works in Cursor and Windsurf) and a JetBrains plugin (WebStorm, IntelliJ IDEA, and all IntelliJ-based IDEs). It runs silently in the background and alerts you to supply-chain threats, malware, CVEs, and credential leaks — before they can cause damage.&lt;/p&gt;

&lt;p&gt;Layer 1 — Known Malicious Packages&lt;br&gt;
Checks every package in your package.json against a bundled database of documented supply-chain attacks, including DPRK/Lazarus Group backdoors, the infamous event-stream compromise, and dozens of other confirmed malicious packages. The database is also synced against a live remote feed so newly discovered threats are caught even before you update the extension.&lt;/p&gt;

&lt;p&gt;Layer 2 — CVE Vulnerabilities&lt;br&gt;
Queries the Google OSV.dev API for known CVEs across all your direct dependencies. No API key needed — it is completely free. Results are cached for 24 hours to minimize network calls. CVSS scores are mapped to severity levels (Critical, High, Medium, Low) so you always know exactly how serious each vulnerability is and which version fixes it.&lt;/p&gt;

&lt;p&gt;Layer 3 — Install Script Hooks&lt;br&gt;
Flags packages that declare preinstall, postinstall, install, or prepare npm scripts. These hooks run automatically during npm install — before any of your own code executes — making them the number one real-world vector for supply-chain malware delivery. Legitimate packages that genuinely need install scripts (like node-gyp and imagemin) are automatically whitelisted.&lt;/p&gt;

&lt;p&gt;Layer 4 — Deep Tarball AST Scan&lt;br&gt;
Downloads the actual npm tarball for flagged packages and scans every JavaScript and TypeScript file inside it for 14 malware patterns: eval() with encoded payloads, new Function(), vm.runInNewContext(), child_process spawning, dynamic require() calls, Base64-decoded payloads, zero-width and Zalgo character obfuscation, network exfiltration patterns, self-publication via npm publish, and more. This catches threats that registry metadata alone cannot reveal.&lt;/p&gt;

&lt;p&gt;Layer 5 — Typosquatting Detection&lt;br&gt;
Detects three classes of package name attacks entirely offline with no network calls. First, classic typosquatting — misspelled names like recat instead of react — using Damerau-Levenshtein edit distance checked against 250+ top npm packages. Second, homoglyph attacks where Unicode look-alike characters (Cyrillic, Greek) replace Latin letters, making reаct look identical to react on screen. Third, AI hallucination squatting — package names that AI coding assistants commonly invent but that do not actually exist on npm, leaving a gap for attackers to register.&lt;/p&gt;

&lt;p&gt;Layer 6 — Dependency Confusion&lt;br&gt;
Identifies internal or private package names that have been planted on the public npm registry. Attackers register a name like @yourcompany/internal-utils on public npm with an inflated version number (e.g., 99.0.0). Because npm resolves the highest semver by default, the malicious public package silently wins over your private registry. This layer detects freshly published packages with inflated versions and near-zero download counts under scopes that should be private.&lt;/p&gt;

&lt;p&gt;Layer 7 — Registry Risk Heuristics&lt;br&gt;
Scores each package against a set of behavioral signals pulled from the npm registry. The risk score combines: package age (newly published packages score much higher), number of maintainers, weekly download velocity relative to package age, whether the publisher account matches the listed maintainers (a key account-takeover signal), whether the GitHub organization matches the npm publisher, and whether the unpacked package size is suspiciously large. A single flagged signal is informational; multiple signals together produce a High or Critical rating.&lt;/p&gt;

&lt;p&gt;Layer 8 — Lockfile Full-Tree Scan&lt;br&gt;
Expands the complete dependency tree from your lockfile and checks every transitive package — not just the ones listed in your package.json. Supports npm lockfile versions 1, 2, and 3, yarn.lock v1, pnpm-lock.yaml versions 5 through 9, and Bun lockfiles. It also validates that every resolved URL points to the standard npm registry, flagging packages silently pulled from alternative or attacker-controlled registries. The 2018 event-stream attack only worked because the malicious payload was three levels deep in the dependency tree — exactly what this layer is designed to catch.&lt;/p&gt;

&lt;p&gt;Layer 9 — Overrides / Resolutions CVE Poisoning&lt;br&gt;
Checks the overrides field (npm) and resolutions field (yarn) in your package.json. These fields are commonly used to force a safe version of a transitive dependency — but they can also accidentally or maliciously pin a vulnerable version that overrides a safe one. Every version pinned in these fields is checked against OSV.dev for known CVEs, exactly like direct dependencies.&lt;/p&gt;

&lt;p&gt;Layer 10 — Deprecated Packages&lt;br&gt;
Queries the npm registry for the official deprecation flag on each of your packages. Deprecated packages receive no further security patches — any vulnerability discovered after deprecation will remain permanently unpatched. The alert shows the deprecation message left by the maintainer and, where available, the recommended migration path or alternative package.&lt;/p&gt;

&lt;p&gt;Layer 11 — License Compliance&lt;br&gt;
Checks the SPDX license identifier of each package against a configurable deny-list. The default deny-list covers licenses that are incompatible with closed-source commercial software: GPL-2.0, GPL-3.0, AGPL-3.0, and SSPL-1.0. AGPL-3.0 in particular requires you to open-source your entire application if you distribute it or run it as a network service. The deny-list is fully customizable per team via a .nsgrc.json file in the project root.&lt;/p&gt;

&lt;p&gt;Layer 12 — Unmaintained Packages&lt;br&gt;
Flags packages that have not received a new publish in longer than a configurable threshold, defaulting to 12 months. Unmaintained packages are a common entry point for supply-chain attacks: threat actors acquire abandoned maintainer accounts through credential stuffing or social engineering, then push malicious updates to packages that still have millions of weekly downloads from years-old package.json files that nobody has touched. The age threshold is fully configurable via npmSafetyGuard.unmaintained.months.&lt;/p&gt;

&lt;p&gt;Layer 13 — Phantom Dependencies&lt;br&gt;
Scans your entire workspace source code — all .ts, .js, .tsx, and .jsx files — for import and require() statements referencing packages that are not declared in your package.json. These are called phantom dependencies. They appear to work locally because npm hoists packages into a flat node_modules structure, so a package required by one of your declared dependencies is incidentally available to your code. They break silently in CI pipelines, Docker builds, or whenever the transitive provider is updated or removed.&lt;/p&gt;

&lt;p&gt;Layer 14 — OSSF Scorecard&lt;br&gt;
Queries the Open Source Security Foundation Scorecard API for each package's GitHub repository and retrieves a security hygiene score from 0 to 10. The score is based on 18 automated checks including: whether branch protection is enforced, whether pull request reviews are required before merging, whether CI tests run on every commit, whether releases are cryptographically signed, and whether known vulnerabilities are tracked and patched. A low score means the project has weak practices and would be easy for an attacker to compromise. The API is free, requires no key, and results are cached for 24 hours.&lt;/p&gt;

&lt;p&gt;Layer 15 — Socket.dev Supply Chain Score&lt;br&gt;
Integrates with the Socket.dev API to retrieve deep behavioral supply-chain intelligence for each package. Socket analyzes packages at the AST level before you install them, flagging unexpected environment variable reads, network calls, shell spawning, obfuscated code, and author-change signals that indicate a possible account takeover. Requires a Socket.dev API key. Results are cached for 6 hours.&lt;/p&gt;

&lt;p&gt;Layer 16 — ReversingLabs Spectra Assure&lt;br&gt;
An optional premium integration with ReversingLabs, the same binary analysis platform used by enterprise security teams and government agencies. It provides malware classification, tampering detection (identifying when a published package has been modified after upload — a definitive sign of supply-chain compromise), CVE enumeration with fix availability, and C2 callback detection. A free community tier is available for individual developers.&lt;/p&gt;

&lt;p&gt;Layer 17 — npm Provenance Attestations&lt;br&gt;
Checks whether each package has a Sigstore-signed provenance attestation, a feature introduced in npm 9.5 in 2023. A provenance attestation cryptographically links the published package to the exact GitHub repository, commit SHA, and CI workflow run that built it. Without an attestation, there is no proof that the published tarball matches what was in the source code — it could have been built locally, tampered with, or published from a compromised machine.&lt;/p&gt;

&lt;p&gt;Layer 18 — Package Upgrade Diff Scanner&lt;br&gt;
When you bump a package version, this layer downloads both the old tarball and the new tarball, runs the full 14-pattern AST scan on each, and reports only the patterns that are newly present in the upgraded version. Patterns that existed in both versions are intentionally suppressed to eliminate noise. This means you see exactly what new capabilities or risks were introduced in the upgrade — eval() that was not there before, a new child_process call, an unexpected HTTP request — and nothing else.&lt;/p&gt;

&lt;p&gt;Layer 19 — Supply Chain Graph&lt;br&gt;
Renders an interactive force-directed graph of your entire dependency tree inside a VS Code webview. Every node is color-coded by its highest severity finding: red for Critical, orange for High, yellow for Medium, green for clean. Edges connecting risky packages are highlighted. You can pan, zoom, drag nodes, and search. A statistics overlay shows the total package count and a breakdown by risk level. The graph is truncated at 500 nodes, prioritizing the riskiest packages first.&lt;/p&gt;

&lt;p&gt;Layer 20 — MCP Server Config Scanner&lt;br&gt;
Scans Model Context Protocol configuration files across your workspace and home directory — including .cursor/mcp.json, .vscode/mcp.json, and ~/.claude/claude_desktop_config.json — for malicious or typosquatted MCP server packages. MCP servers run as persistent background processes inside AI coding sessions like Cursor and Claude Code. A malicious MCP server can intercept every AI query, read your entire codebase, and exfiltrate any API keys passed to it through the env configuration block.&lt;/p&gt;

&lt;p&gt;Layer 21 — AI Config Guard&lt;br&gt;
Scans up to three levels deep inside your node_modules directory for packages that contain code designed to target AI developer tool credentials. Using approximately 20 attack signatures, it detects attempts to read Claude Code settings, Cursor configuration, GitHub Copilot tokens, and 1Password CLI credentials, followed by exfiltration patterns like unexpected network calls carrying the stolen data. This layer addresses an emerging class of supply-chain attack specifically targeting the AI-assisted development workflow.&lt;/p&gt;

&lt;p&gt;Layer 22 — Exposed Secrets Scanner&lt;br&gt;
Scans your workspace files for accidentally exposed secrets in .env*, .npmrc, *.pem, *.key, credentials.json, and secrets.json files. Detects over a dozen secret types: AWS access keys, Stripe live keys, GitHub Personal Access Tokens, Slack tokens, Google API keys, SendGrid keys, npm auth tokens, private keys in PEM format, and generic API_KEY, SECRET, TOKEN, and PASSWORD patterns. Severity is escalated to Critical if the file is not listed in .gitignore, because the secret will be committed to your repository on the next git commit. Files like .env.example and .env.sample are never scanned.&lt;/p&gt;

&lt;p&gt;Layer 23 — Native Binary Detection&lt;br&gt;
Detects precompiled .node binary files inside npm package tarballs. Native Node.js Addons are compiled C or C++ shared libraries that are loaded directly into the Node.js process. They are completely opaque to JavaScript static analysis tools — none of the 14 AST scan patterns in Layer 4, none of the other JS-based layers, can inspect what a .node binary actually does at runtime. Many legitimate packages use native bindings for performance (image processing, database drivers, cryptography), so findings are flagged as High rather than Critical, with guidance to audit the source code on GitHub and consider whether a pure-JavaScript alternative exists.&lt;/p&gt;

&lt;p&gt;⭐ Outro&lt;br&gt;
NPM Safety Guard covers the entire threat surface of the npm ecosystem — from known malware databases and CVEs, through behavioral heuristics and tarball analysis, all the way to AI credential targeting and exposed secrets. Most layers require no API keys and work completely offline. Install it once and your entire team is protected on every project, in every file, on every save.&lt;/p&gt;

&lt;p&gt;Available free on the VS Code Marketplace (ext install jomynn.npm-safety-guard) and the JetBrains Marketplace. Open source under the MIT license. Built by SendWaveHub.&lt;/p&gt;

&lt;p&gt;🔧 INSTALL&lt;/p&gt;

&lt;p&gt;VS Code / Cursor / Windsufl:&lt;br&gt;
Search "NPM Safety Guard" in the Extensions panel, or run:&lt;br&gt;
ext install jomynn.npm-safety-guard&lt;/p&gt;

&lt;p&gt;JetBrains (WebStorm, IntelliJ IDEA, Rider…):&lt;br&gt;
Settings → Plugins → Marketplace → search "NPM Safety Guard"&lt;/p&gt;

&lt;p&gt;🔗 LINKS&lt;/p&gt;

&lt;p&gt;VS Code Marketplace → &lt;a href="https://marketplace.visualstudio.com/items?itemName=jomynn.npm-safety-guard" rel="noopener noreferrer"&gt;https://marketplace.visualstudio.com/items?itemName=jomynn.npm-safety-guard&lt;/a&gt;&lt;br&gt;
JetBrains Marketplace → &lt;a href="https://plugins.jetbrains.com/plugin/com.sendwavehub.npmsafetyguard" rel="noopener noreferrer"&gt;https://plugins.jetbrains.com/plugin/com.sendwavehub.npmsafetyguard&lt;/a&gt;&lt;br&gt;
GitHub (open source, MIT) → &lt;a href="https://github.com/jomynn/npm-safety-guard" rel="noopener noreferrer"&gt;https://github.com/jomynn/npm-safety-guard&lt;/a&gt;&lt;br&gt;
SendWaveHub → &lt;a href="https://sendwavehub.tech" rel="noopener noreferrer"&gt;https://sendwavehub.tech&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;💛 SUPPORT THE PROJECT&lt;/p&gt;

&lt;p&gt;⭐ Star the repo on GitHub — it helps more developers discover it&lt;br&gt;
☕ Ko-fi one-off tip → &lt;a href="https://ko-fi.com/sendwavehubtech" rel="noopener noreferrer"&gt;https://ko-fi.com/sendwavehubtech&lt;/a&gt;&lt;br&gt;
💖 GitHub Sponsors (recurring) → &lt;a href="https://github.com/sponsors/jomynn" rel="noopener noreferrer"&gt;https://github.com/sponsors/jomynn&lt;/a&gt;&lt;br&gt;
🏢 Corporate sponsorship → &lt;a href="https://sendwavehub.tech/contact" rel="noopener noreferrer"&gt;https://sendwavehub.tech/contact&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>security</category>
      <category>tooling</category>
    </item>
    <item>
      <title>I built a free IDE extension to catch malicious npm packages before they wreck your project</title>
      <dc:creator>jomynn</dc:creator>
      <pubDate>Thu, 18 Jun 2026 10:16:30 +0000</pubDate>
      <link>https://dev.to/jomynn/i-built-a-free-ide-extension-to-catch-malicious-npm-packages-before-they-wreck-your-project-24oe</link>
      <guid>https://dev.to/jomynn/i-built-a-free-ide-extension-to-catch-malicious-npm-packages-before-they-wreck-your-project-24oe</guid>
      <description>&lt;p&gt;Supply-chain attacks via npm are up year-over-year — packages like &lt;code&gt;event-stream&lt;/code&gt;, &lt;br&gt;
the Lazarus group drops, and AI-hallucinated typosquats keep landing in real codebases. &lt;br&gt;
I got tired of finding out &lt;em&gt;after&lt;/em&gt; the fact, so I built &lt;strong&gt;NPM Safety Guard&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;It scans your &lt;code&gt;package.json&lt;/code&gt; and lockfiles right inside your editor — no separate CLI step.&lt;/p&gt;

&lt;p&gt;Here's what it currently catches across &lt;strong&gt;22 detection layers&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Known malicious packages&lt;/strong&gt; — DPRK RAT drops, Lazarus-linked packages, event-stream clones&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CVEs&lt;/strong&gt; — via OSV.dev, cached locally (free, no API key needed)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Typosquatting &amp;amp; homoglyph attacks&lt;/strong&gt; — catches &lt;code&gt;lodahs&lt;/code&gt;, &lt;code&gt;reàct&lt;/code&gt;, and AI-hallucinated package names&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install script hooks&lt;/strong&gt; — flags &lt;code&gt;preinstall&lt;/code&gt;/&lt;code&gt;postinstall&lt;/code&gt; before you run them&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deep tarball AST scan&lt;/strong&gt; — detects obfuscation, &lt;code&gt;eval&lt;/code&gt;, and payload patterns in the actual source&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependency confusion&lt;/strong&gt; — scoped packages planted on public npm to hijack private installs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exposed secrets&lt;/strong&gt; — API keys, tokens, private keys accidentally left in &lt;code&gt;.env&lt;/code&gt;, &lt;code&gt;.npmrc&lt;/code&gt;, &lt;code&gt;.pem&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP server config scanner&lt;/strong&gt; — catches typosquatted or malicious MCP transport configs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supply chain graph&lt;/strong&gt; — interactive force-directed graph with risk overlay from your lockfile&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OSSF Scorecard + Socket.dev score&lt;/strong&gt; — security hygiene at a glance&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where to get it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VS Code / Cursor / Windsurf →&lt;/strong&gt; &lt;a href="https://marketplace.visualstudio.com/items?itemName=jomynn.npm-safety-guard" rel="noopener noreferrer"&gt;VS Code Marketplace&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VS Codium / open-source IDEs →&lt;/strong&gt; &lt;a href="https://open-vsx.org/extension/jomynn/npm-safety-guard" rel="noopener noreferrer"&gt;Open VSX Registry&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WebStorm / IntelliJ IDEA / all JetBrains IDEs →&lt;/strong&gt; &lt;a href="https://plugins.jetbrains.com/plugin/com.sendwavehub.npmsafetyguard" rel="noopener noreferrer"&gt;JetBrains Marketplace&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All free. No account required for the core layers. MIT licensed on the VS Code side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Under the hood
&lt;/h2&gt;

&lt;p&gt;The VS Code extension is TypeScript. The JetBrains plugin is Kotlin. They share the same &lt;br&gt;
detection signatures bundled at build time — no cloud dependency for the core scan.&lt;/p&gt;

&lt;p&gt;CVE lookups hit OSV.dev with a 24-hour local cache so you're not waiting on a network &lt;br&gt;
call every keystroke.&lt;/p&gt;




&lt;p&gt;Have you been burned by a supply-chain attack before? Or do you have a detection layer &lt;br&gt;
you wish existed? Drop it in the comments — I'm actively adding new signatures.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>security</category>
      <category>showdev</category>
    </item>
    <item>
      <title>How We Catch the Axios DPRK RAT — Directly in Your IDE</title>
      <dc:creator>jomynn</dc:creator>
      <pubDate>Fri, 22 May 2026 02:26:06 +0000</pubDate>
      <link>https://dev.to/jomynn/how-we-catch-the-axios-dprk-rat-directly-in-your-ide-449</link>
      <guid>https://dev.to/jomynn/how-we-catch-the-axios-dprk-rat-directly-in-your-ide-449</guid>
      <description>&lt;p&gt;&lt;em&gt;Published by SendWaveHub · NPM Safety Guard v1.12.0&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Attack
&lt;/h2&gt;

&lt;p&gt;In April 2025, security researchers discovered that &lt;strong&gt;axios 1.14.1&lt;/strong&gt; — a package with &lt;strong&gt;hundreds of millions of downloads&lt;/strong&gt; — had been briefly replaced on npm with a version containing a Remote Access Trojan (RAT) attributed to DPRK-linked threat actors (the Lazarus Group).&lt;/p&gt;

&lt;p&gt;The malicious version was live for a short window. Developers who ran &lt;code&gt;npm install&lt;/code&gt; during that window pulled down a backdoor that connected to attacker-controlled infrastructure.&lt;/p&gt;

&lt;p&gt;This isn't an edge case. It's the same pattern used in the &lt;strong&gt;event-stream&lt;/strong&gt; attack (2018), &lt;strong&gt;ua-parser-js&lt;/strong&gt; (2021), and dozens of others. Supply chain attacks now account for a significant share of real-world breaches — and they bypass most traditional security tools because &lt;strong&gt;the package itself is the attack vector&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem with Existing Tooling
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;npm audit&lt;/code&gt; only catches &lt;strong&gt;known CVEs&lt;/strong&gt; — it doesn't flag malicious payloads injected into legitimate packages. By the time a CVE is filed, the damage may already be done.&lt;/p&gt;

&lt;p&gt;OSV.dev, Snyk, and similar tools are excellent at CVE tracking, but they rely on a package being reported and catalogued. A supply chain attack that's live for 48 hours may never make it into those databases in time to protect you.&lt;/p&gt;




&lt;h2&gt;
  
  
  What NPM Safety Guard Does Differently
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=Sendwavehubtech.npm-safety-guard" rel="noopener noreferrer"&gt;NPM Safety Guard&lt;/a&gt; is a free VS Code extension that runs &lt;strong&gt;13 detection layers&lt;/strong&gt; directly in your editor, before &lt;code&gt;npm install&lt;/code&gt; even runs.&lt;/p&gt;

&lt;p&gt;For the Axios DPRK RAT specifically, it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Matches against a curated malicious-package database&lt;/strong&gt; — the bundled DB includes &lt;code&gt;axios@1.14.1&lt;/code&gt;, flagged as CRITICAL with the exact version and attack description&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pulls a live remote feed&lt;/strong&gt; — updated independently of extension releases, so new attacks light up within hours of discovery&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Checks OSV.dev in real time&lt;/strong&gt; — CVEs filed against your installed versions are flagged inline&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audits install hooks&lt;/strong&gt; — &lt;code&gt;preinstall&lt;/code&gt;/&lt;code&gt;postinstall&lt;/code&gt;/&lt;code&gt;prepare&lt;/code&gt; scripts are flagged before they run, since they're the #1 supply-chain execution vector&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here's what it looks like when &lt;code&gt;axios@1.14.1&lt;/code&gt; appears in your &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🔴 CRITICAL — DPRK RAT (Lazarus Group) — axios@1.14.1
This version was replaced with a Remote Access Trojan.
Safe version: 1.7.9
npm install axios@1.7.9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The warning appears inline, in the Problems panel, and in a full Security Report — all before you've run a single &lt;code&gt;npm&lt;/code&gt; command.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Other 12 Detection Layers
&lt;/h2&gt;

&lt;p&gt;Catching known-malicious packages is the floor, not the ceiling. NPM Safety Guard also detects:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&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;&lt;strong&gt;Typosquatting&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;lодash&lt;/code&gt; (Cyrillic о), &lt;code&gt;expres&lt;/code&gt; — packages designed to look like legitimate ones&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dependency confusion&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Scoped packages (&lt;code&gt;@company/pkg&lt;/code&gt;) that have been planted on public npm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Overrides/resolutions poisoning&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Teams pin versions to fix a transitive CVE, accidentally pinning to a vulnerable version&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Phantom dependencies&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Packages your code imports but aren't in &lt;code&gt;package.json&lt;/code&gt; — fail silently in clean installs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Unmaintained packages&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Last release &amp;gt;24 months ago → accumulating unpatched CVEs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deprecated packages&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;npm-deprecated packages with auto-upgrade suggestions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Install script audit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Every &lt;code&gt;preinstall&lt;/code&gt;/&lt;code&gt;postinstall&lt;/code&gt; hook flagged with package context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OSSF Scorecard&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Security hygiene scores from the OpenSSF for each dependency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Socket.dev integration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Supply chain risk scores (requires token)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;License compliance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GPL/AGPL in commercial projects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ReversingLabs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Real-time CVE + malware detection (requires free token)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Lockfile scan&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full resolved dependency tree, not just direct deps&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Install It Free
&lt;/h2&gt;

&lt;p&gt;The extension is free, open source (MIT), and available on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=Sendwavehubtech.npm-safety-guard" rel="noopener noreferrer"&gt;VS Code Marketplace&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://open-vsx.org/" rel="noopener noreferrer"&gt;Open VSX&lt;/a&gt; (for VSCodium users)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ext &lt;span class="nb"&gt;install &lt;/span&gt;Sendwavehubtech.npm-safety-guard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No API key required for the core features. The malware DB and OSV.dev integration work out of the box.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Matters Now
&lt;/h2&gt;

&lt;p&gt;The Axios attack was caught relatively quickly — but only because it targeted a high-profile package with many eyes on it. The next attack will target a smaller package, with fewer watchers, and stay live longer.&lt;/p&gt;

&lt;p&gt;Your best defense is catching the package &lt;strong&gt;before it's installed&lt;/strong&gt; — at the point where you're editing &lt;code&gt;package.json&lt;/code&gt; in your editor.&lt;/p&gt;

&lt;p&gt;That's exactly what NPM Safety Guard is built for.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built by &lt;a href="https://sendwavehub.tech" rel="noopener noreferrer"&gt;SendWaveHub&lt;/a&gt;. If this saves your project, consider &lt;a href="https://github.com/sponsors/jomynn" rel="noopener noreferrer"&gt;sponsoring the work&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;code&gt;security&lt;/code&gt; &lt;code&gt;npm&lt;/code&gt; &lt;code&gt;javascript&lt;/code&gt; &lt;code&gt;devsecops&lt;/code&gt; &lt;code&gt;supplychain&lt;/code&gt;&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>javascript</category>
      <category>npm</category>
      <category>security</category>
    </item>
  </channel>
</rss>
