<?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: Александр Тихонов</title>
    <description>The latest articles on DEV Community by Александр Тихонов (@__1b223f7).</description>
    <link>https://dev.to/__1b223f7</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%2F4093593%2F7d0b14a8-99b4-4958-b533-af520e6005f2.png</url>
      <title>DEV Community: Александр Тихонов</title>
      <link>https://dev.to/__1b223f7</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/__1b223f7"/>
    <language>en</language>
    <item>
      <title>An AI pentest agent that structurally can't hallucinate a vulnerability — and runs offline</title>
      <dc:creator>Александр Тихонов</dc:creator>
      <pubDate>Tue, 25 Aug 2026 07:14:59 +0000</pubDate>
      <link>https://dev.to/__1b223f7/an-ai-pentest-agent-that-structurally-cant-hallucinate-a-vulnerability-and-runs-offline-25mk</link>
      <guid>https://dev.to/__1b223f7/an-ai-pentest-agent-that-structurally-cant-hallucinate-a-vulnerability-and-runs-offline-25mk</guid>
      <description>&lt;p&gt;If you point any LLM at a target and ask it to "write a security report," it will confidently invent findings that aren't there: an imagined TLS weakness, a "likely" SQL injection, a secret leak that never happened. For a security tool, &lt;strong&gt;a hallucinated finding is the worst possible output&lt;/strong&gt; — you can't hand a client a report built on fiction.&lt;/p&gt;

&lt;p&gt;There's a second problem, and it's a hard blocker for a lot of real work: &lt;strong&gt;client data can't go to someone else's cloud.&lt;/strong&gt; NDAs, air-gapped environments, regulated data, or plain lack of trust. "Just use ChatGPT" isn't an option.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;Nexus&lt;/strong&gt;, an autonomous red+blue agent that addresses both. Here's how.&lt;/p&gt;

&lt;h2&gt;
  
  
  The idea: an evidence gate
&lt;/h2&gt;

&lt;p&gt;An LLM is great at some things and terrible at others, so the two jobs are split:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The model TRIES&lt;/strong&gt; — it decides what to test and sends the payloads. This is where LLMs are strong.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic code writes the report&lt;/strong&gt; (&lt;code&gt;findings.py&lt;/code&gt;), and a finding only counts &lt;strong&gt;if the live target's response proves it&lt;/strong&gt;: an XSS marker came back unescaped; &lt;code&gt;../../etc/passwd&lt;/code&gt; returned content containing &lt;code&gt;root:x:&lt;/code&gt;; a quote triggered a SQL error; the server handed over a token on &lt;code&gt;' OR 1=1--&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing in the final report comes from the model's prose. Every finding is read from the &lt;strong&gt;transcript&lt;/strong&gt; — the actual response bytes — not from what the model "wrote." Hallucinating a finding isn't forbidden; it's structurally &lt;strong&gt;impossible&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ nexus --target demo.testfire.net --authorized --rules-accepted
  -&amp;gt; /search.jsp?query=&amp;lt;script&amp;gt;alert(1)&amp;lt;/script&amp;gt;
     [+] reflected UNESCAPED — XSS confirmed
  -&amp;gt; /index.jsp?content=../../../../etc/passwd
     [-] no root:x: in response — not confirmed, dropped
[gate]  writing report from EVIDENCE, not from prose
  [x] "weak TLS 1.0 cipher"    no evidence · DROPPED
  [+] HIGH    Reflected XSS
[done]  findings: 2 · hallucinated: 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model suspected path traversal and weak TLS — the gate &lt;strong&gt;dropped everything the target didn't confirm.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Offline: an stdlib core, data stays with you
&lt;/h2&gt;

&lt;p&gt;The core is pure Python stdlib, zero dependencies, and runs in an air-gapped box. The "brain" is pluggable: a cloud model (if allowed), a local Ollama model, or a &lt;strong&gt;small fine-tuned model&lt;/strong&gt; that runs fully offline. The point: for confidential work where the cloud is off the table, you still get a working AI pentester, and &lt;strong&gt;the client's data never leaves the machine.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Isn't a small offline model just a toy?
&lt;/h2&gt;

&lt;p&gt;A generic 1.5B is nearly useless for a real assessment: on a held-out benchmark it latches onto two passive findings and &lt;strong&gt;exploits nothing&lt;/strong&gt; — 35%. I fine-tuned the same 1.5B (on teacher-distilled trajectories, scored by the same evidence gate where you can't fake a finding): &lt;strong&gt;95%&lt;/strong&gt; held-out, &lt;strong&gt;71%&lt;/strong&gt; on an OOD target it had never seen, &lt;code&gt;fp=0&lt;/code&gt;. An offline brain that does the work instead of imitating it. Numbers are reproducible (&lt;code&gt;lab/ood_eval.py&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  What you get
&lt;/h2&gt;

&lt;p&gt;Not a scanner dump — a &lt;strong&gt;client-ready report&lt;/strong&gt;: CVSS 3.1 (computed from the formula, not guessed), attack chains, CWE/OWASP/PCI mapping, a remediation plan with concrete fixes, retest deltas between runs, and a co-pilot you can ask about findings — it answers &lt;strong&gt;only from what was proven&lt;/strong&gt; (ask about an XSS that doesn't exist and it says "no evidence" instead of inventing one). Red (audit) and blue (defending your own host) are one discipline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ethics
&lt;/h2&gt;

&lt;p&gt;Authorized scope only, declared up front. Scope is an allowlist in code, checked on every request and every redirect (SSRF guard). External targets require a second confirmation. No destructive or DoS actions. This is a tool for &lt;strong&gt;your own&lt;/strong&gt; infrastructure and for engagements with written permission.&lt;/p&gt;

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

&lt;p&gt;Early release, source-available (BUSL-1.1).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;nexus-sec
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Code: &lt;a href="https://github.com/alerta200/alerta" rel="noopener noreferrer"&gt;https://github.com/alerta200/alerta&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm most curious where the evidence-gated approach itself breaks. The obvious trade-off is false negatives — a detector this strict will miss real bugs. If you find a case, send it.&lt;/p&gt;

</description>
      <category>security</category>
      <category>ai</category>
      <category>llm</category>
      <category>python</category>
    </item>
  </channel>
</rss>
