<?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: YUVRAJ</title>
    <description>The latest articles on DEV Community by YUVRAJ (@malgatyuvraj).</description>
    <link>https://dev.to/malgatyuvraj</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%2F3948320%2F82b4a5b7-3679-4f22-97b2-fa461119f4f3.jpg</url>
      <title>DEV Community: YUVRAJ</title>
      <link>https://dev.to/malgatyuvraj</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/malgatyuvraj"/>
    <language>en</language>
    <item>
      <title>I built an AI IDE where the AI tries to hack its own code here's how the swarm works</title>
      <dc:creator>YUVRAJ</dc:creator>
      <pubDate>Sun, 24 May 2026 12:48:50 +0000</pubDate>
      <link>https://dev.to/malgatyuvraj/i-built-an-ai-ide-where-the-ai-tries-to-hack-its-own-code-heres-how-the-swarm-works-28a5</link>
      <guid>https://dev.to/malgatyuvraj/i-built-an-ai-ide-where-the-ai-tries-to-hack-its-own-code-heres-how-the-swarm-works-28a5</guid>
      <description>&lt;p&gt;Most AI coding tools are built to assist you.&lt;/p&gt;

&lt;p&gt;Rogue Studio is built to attack you — specifically, to attack &lt;br&gt;
the code it just wrote for you, find every vulnerability, and &lt;br&gt;
force itself to fix them before you ever see the output.&lt;/p&gt;

&lt;p&gt;Here's how I built the adversarial swarm architecture, and why &lt;br&gt;
I think this approach to AI-assisted security is underexplored.&lt;/p&gt;


&lt;h2&gt;
  
  
  Why I built this
&lt;/h2&gt;

&lt;p&gt;I kept hitting the same wall.&lt;/p&gt;

&lt;p&gt;I'm a security-focused developer. I do legitimate vulnerability &lt;br&gt;
research. I analyze contracts, decompile binaries, write PoC &lt;br&gt;
exploits against test environments I own.&lt;/p&gt;

&lt;p&gt;And every single AI coding tool I tried would either refuse, &lt;br&gt;
add a disclaimer, water down the output, or quietly route my &lt;br&gt;
code to a server I had no visibility into.&lt;/p&gt;

&lt;p&gt;I didn't want a safer AI.&lt;br&gt;
I wanted a sharper one.&lt;/p&gt;

&lt;p&gt;So I spent the last few weeks building the tool I actually &lt;br&gt;
wanted to use. I called it Rogue Studio.&lt;/p&gt;

&lt;p&gt;It's open source, self-hostable, and it does not apologize &lt;br&gt;
for what it is.&lt;/p&gt;

&lt;p&gt;→ &lt;a href="https://github.com/malgatyuvraj/Rogue-Studio" rel="noopener noreferrer"&gt;github.com/malgatyuvraj/Rogue-Studio&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  The core idea: make the AI fight itself
&lt;/h2&gt;

&lt;p&gt;Here's the problem with AI-generated code from a &lt;br&gt;
security perspective.&lt;/p&gt;

&lt;p&gt;The same model that writes your code is the one &lt;br&gt;
you're asking to review it. It has the same blind spots &lt;br&gt;
in both directions. It wrote the vulnerable pattern, &lt;br&gt;
so it's likely to miss the vulnerable pattern.&lt;/p&gt;

&lt;p&gt;The fix is obvious once you see it: use a &lt;em&gt;different&lt;/em&gt; &lt;br&gt;
agent with a &lt;em&gt;different&lt;/em&gt; system prompt — one that is &lt;br&gt;
not trying to be helpful, but trying to be destructive.&lt;/p&gt;

&lt;p&gt;That's Swarm Mode.&lt;/p&gt;

&lt;p&gt;Two agents. One goal. No guardrails.&lt;br&gt;
Blue Team → writes the code → signals &lt;br&gt;
↓&lt;br&gt;
Red Team audits for vulnerabilities&lt;br&gt;
↓&lt;br&gt;
 &lt;br&gt;
↓ ↓&lt;br&gt;
exploit details fed loop terminates ✅&lt;br&gt;
back to Blue Team&lt;br&gt;
↓&lt;br&gt;
Blue Team patches&lt;br&gt;
↓&lt;br&gt;
back to Red Team audit&lt;br&gt;
↓&lt;br&gt;
(hard cap: 3 iterations)&lt;/p&gt;

&lt;p&gt;text&lt;/p&gt;

&lt;p&gt;The agents communicate through sentinel tokens &lt;br&gt;
embedded in their output stream:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;done&amp;gt;&lt;/code&gt; — Blue Team has finished writing&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;vulnerable&amp;gt;&lt;/code&gt; — Red Team found at least one issue&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;secure&amp;gt;&lt;/code&gt; — Red Team confirms the code is clean&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The orchestrator parses these tokens from the &lt;br&gt;
streaming response in real time and routes accordingly.&lt;/p&gt;

&lt;p&gt;Here's the actual loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MAX_SWARM_ITERATIONS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;verdict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;runSwarm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userTask&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;iter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;verdict&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vulnerable&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;iter&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;MAX_SWARM_ITERATIONS&lt;/span&gt;&lt;span class="p"&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;patchTask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
The Red Team found these vulnerabilities:
&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;swarm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;redOutput&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;

Original code:
&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;swarm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;blueOutput&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;

Patch all vulnerabilities.`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;verdict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;runSwarm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;patchTask&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;iter&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The hard cap at 3 exists because some vulnerability &lt;br&gt;
classes genuinely can't be patched without redesigning &lt;br&gt;
the architecture. If the loop hits 3, it surfaces the &lt;br&gt;
remaining issues to the developer instead of spinning &lt;br&gt;
forever.&lt;/p&gt;
&lt;h3&gt;
  
  
  What the Red Team hunts for
&lt;/h3&gt;

&lt;p&gt;The Red Team system prompt is specifically tuned to &lt;br&gt;
find these vulnerability classes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;XSS&lt;/strong&gt; — unsanitized user input reaching the DOM&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQL Injection&lt;/strong&gt; — string concatenation in queries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Buffer Overflows&lt;/strong&gt; — unsafe memory ops in C/C++&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reentrancy&lt;/strong&gt; — Solidity withdraw-before-state-update&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSRF&lt;/strong&gt; — unvalidated URLs in server-side fetches&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Path Traversal&lt;/strong&gt; — unsanitized file path inputs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both agents stream simultaneously to a split terminal —&lt;br&gt;
blue glow on the left, red glow on the right. It looks &lt;br&gt;
exactly as dramatic as it sounds.&lt;/p&gt;


&lt;h2&gt;
  
  
  The part nobody else is building: Air-Gap mode
&lt;/h2&gt;

&lt;p&gt;I want to talk about this one because I think it's &lt;br&gt;
architecturally more interesting than it looks.&lt;/p&gt;

&lt;p&gt;Every "local AI" tool I've seen has the same problem.&lt;br&gt;
They &lt;em&gt;support&lt;/em&gt; local models but they don't &lt;em&gt;enforce&lt;/em&gt; &lt;br&gt;
local-only operation. There's always a fallback, &lt;br&gt;
always a telemetry call, always a condition where &lt;br&gt;
your code leaves the machine without you noticing.&lt;/p&gt;

&lt;p&gt;I wanted something stronger than a setting.&lt;br&gt;
I wanted a guarantee.&lt;/p&gt;

&lt;p&gt;So I built a physical-looking Kill Switch in the UI.&lt;br&gt;
When you flip it, a middleware layer in &lt;br&gt;
&lt;code&gt;/api/chat/route.ts&lt;/code&gt; intercepts every request &lt;br&gt;
&lt;em&gt;before&lt;/em&gt; any provider routing happens:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;EXTERNAL_PROVIDERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;openai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;anthropic&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gemini&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;groq&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deepseek&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;together&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;openrouter&lt;/span&gt;&lt;span class="dl"&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;isAirGapped&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;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x-air-gap-mode&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;true&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isAirGapped&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;EXTERNAL_PROVIDERS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AIR-GAP VIOLATION: External provider blocked.&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="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;403&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The enforcement is &lt;strong&gt;server-side&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is the important detail. A client-side check &lt;br&gt;
can be bypassed by anyone who modifies the request &lt;br&gt;
directly. The server-side middleware means the 403 &lt;br&gt;
fires regardless of how the request was constructed.&lt;/p&gt;

&lt;p&gt;The only provider that passes through is &lt;code&gt;ollama&lt;/code&gt; — &lt;br&gt;
which talks exclusively to &lt;code&gt;localhost:11434&lt;/code&gt;. &lt;br&gt;
Zero bytes leave the machine. Not as a claim. &lt;br&gt;
As a code guarantee.&lt;/p&gt;


&lt;h2&gt;
  
  
  Reverse Engineer Mode
&lt;/h2&gt;

&lt;p&gt;This one is simple conceptually but surprisingly &lt;br&gt;
useful in practice.&lt;/p&gt;

&lt;p&gt;One click swaps the entire system prompt for an &lt;br&gt;
aggressive decompiler prompt. The standard safety &lt;br&gt;
instructions are gone. What's left is a prompt &lt;br&gt;
specifically designed to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;De-obfuscate minified JavaScript and reconstruct 
readable ASTs&lt;/li&gt;
&lt;li&gt;Parse compiled WASM back into human-readable logic&lt;/li&gt;
&lt;li&gt;Rename obfuscated variables based on inferred 
purpose&lt;/li&gt;
&lt;li&gt;Explain malware behavior in plain English&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No refusals. No disclaimers. No "I can't help with that."&lt;/p&gt;

&lt;p&gt;An amber warning banner appears in the UI so you &lt;br&gt;
always know which mode is active. I didn't want &lt;br&gt;
this to be invisible.&lt;/p&gt;


&lt;h2&gt;
  
  
  Web3 Black-Hat Playground
&lt;/h2&gt;

&lt;p&gt;I added this specifically for smart contract auditors.&lt;/p&gt;

&lt;p&gt;One click hits &lt;code&gt;/api/web3/scaffold&lt;/code&gt; which initializes &lt;br&gt;
a full Hardhat project in your local &lt;code&gt;rogue_workspace&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;execAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;npm init -y&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="na"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;targetDir&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;execAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox&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="na"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;targetDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;120000&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It also writes a starter &lt;code&gt;Target.sol&lt;/code&gt; with an &lt;br&gt;
&lt;strong&gt;intentional reentrancy vulnerability&lt;/strong&gt; so you have &lt;br&gt;
something to audit immediately:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function withdraw(uint256 amount) public {
    require(balances[msg.sender] &amp;gt;= amount);
    // external call before state update ← reentrancy
    (bool success, ) = msg.sender.call{value: amount}("");
    require(success);
    balances[msg.sender] -= amount;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The Black-Hat Agent then generates PoC exploits &lt;br&gt;
against your local contracts to verify your defenses &lt;br&gt;
before you deploy anywhere real.&lt;/p&gt;

&lt;p&gt;The route is idempotent. Call it twice, the second &lt;br&gt;
call returns &lt;code&gt;{ status: "already_initialized" }&lt;/code&gt; &lt;br&gt;
instead of re-running npm install.&lt;/p&gt;


&lt;h2&gt;
  
  
  Ghost Deploy — Tor .onion Generator
&lt;/h2&gt;

&lt;p&gt;This was the most technically satisfying feature to ship.&lt;/p&gt;

&lt;p&gt;The pipeline:&lt;br&gt;
Detect tor binary (which tor)&lt;/p&gt;

&lt;p&gt;Spawn http-server on a random open port&lt;/p&gt;

&lt;p&gt;Write a torrc with HiddenServiceDir + HiddenServicePort&lt;/p&gt;

&lt;p&gt;Start tor daemon with the custom torrc&lt;/p&gt;

&lt;p&gt;Poll for hostname file (tor generates this async)&lt;/p&gt;

&lt;p&gt;Read the cryptographic .onion address from the file&lt;/p&gt;

&lt;p&gt;Stream bootstrap logs to the terminal&lt;/p&gt;

&lt;p&gt;Return the .onion URL to the UI&lt;/p&gt;

&lt;p&gt;text&lt;/p&gt;

&lt;p&gt;The part that took me the longest to understand: &lt;br&gt;
you don't &lt;em&gt;assign&lt;/em&gt; a .onion address. Tor generates &lt;br&gt;
one for you from an Ed25519 keypair the first time &lt;br&gt;
it starts with a &lt;code&gt;HiddenServiceDir&lt;/code&gt;. You discover &lt;br&gt;
it by reading the &lt;code&gt;hostname&lt;/code&gt; file after startup.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hostnameFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hiddenServiceDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hostname&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;onionAddress&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="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;onionAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hostnameFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf-8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;onionAddress&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// not generated yet, keep polling&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Poll for up to 30 seconds. In practice it generates &lt;br&gt;
in 3-8 seconds on a warm machine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Requires&lt;/strong&gt;: &lt;code&gt;brew install tor&lt;/code&gt; on Mac, &lt;br&gt;
&lt;code&gt;sudo apt install tor&lt;/code&gt; on Linux.&lt;/p&gt;


&lt;h2&gt;
  
  
  The API key security fix I almost missed
&lt;/h2&gt;

&lt;p&gt;The production test suite caught something I'd &lt;br&gt;
overlooked: the original implementation accepted &lt;br&gt;
API keys from the request body.&lt;/p&gt;

&lt;p&gt;Fine for local use. Dangerous for any hosted deployment.&lt;/p&gt;

&lt;p&gt;The fix uses a dual-source pattern — env vars take &lt;br&gt;
priority, client-provided key is only trusted if the &lt;br&gt;
request originates from localhost:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;host&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;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;host&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="dl"&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;isLocalhost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
  &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;localhost&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;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;127.0.0.1&lt;/span&gt;&lt;span class="dl"&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;ENV_KEYS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ANTHROPIC_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;gemini&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GOOGLE_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;groq&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GROQ_API_KEY&lt;/span&gt;&lt;span class="p"&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;apiKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ENV_KEYS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; 
               &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isLocalhost&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;clientApiKey&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This keeps the local-first UX intact — self-hosters &lt;br&gt;
can still paste their key into the UI — while being &lt;br&gt;
safe for any cloud deployment.&lt;/p&gt;


&lt;h2&gt;
  
  
  What the codebase looks like
&lt;/h2&gt;

&lt;p&gt;I spent real time on this.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript strict&lt;/strong&gt; — 0 errors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ESLint&lt;/strong&gt; — 0 warnings (37 errors when I started, 
took a full session to clean up)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 14 App Router&lt;/strong&gt; throughout&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MIT license&lt;/strong&gt; — do whatever you want with it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;any&lt;/code&gt; types are gone. The &lt;code&gt;let&lt;/code&gt; declarations &lt;br&gt;
that should be &lt;code&gt;const&lt;/code&gt; are fixed. The catch blocks &lt;br&gt;
use &lt;code&gt;unknown&lt;/code&gt; and narrow properly. It's the kind &lt;br&gt;
of codebase I'd be comfortable handing to someone &lt;br&gt;
else.&lt;/p&gt;


&lt;h2&gt;
  
  
  What's next and where you can help
&lt;/h2&gt;

&lt;p&gt;I'm actively looking for contributors. The things &lt;br&gt;
I haven't built yet:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Easy&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add SSRF and path traversal to the Red Team prompt&lt;/li&gt;
&lt;li&gt;Dark/light theme toggle&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Medium&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Playwright E2E test coverage&lt;/li&gt;
&lt;li&gt;Better real-time Tor bootstrap log streaming in UI&lt;/li&gt;
&lt;li&gt;Multi-provider failover when Air-Gap is OFF&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Hard&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VS Code extension that ports the agent sidebar&lt;/li&gt;
&lt;li&gt;Multi-file workspace swarm support&lt;/li&gt;
&lt;li&gt;LSP integration for inline Red Team annotations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The codebase is clean, the architecture is documented &lt;br&gt;
in the README, and PRs get reviewed fast.&lt;/p&gt;

&lt;p&gt;If you've been waiting for an AI coding tool that &lt;br&gt;
actually trusts you — this is it.&lt;/p&gt;

&lt;p&gt;→ &lt;strong&gt;&lt;a href="https://github.com/malgatyuvraj/Rogue-Studio" rel="noopener noreferrer"&gt;github.com/malgatyuvraj/Rogue-Studio&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Drop a ⭐ if you think this kind of tooling &lt;br&gt;
should exist. Issues and PRs are open.&lt;/p&gt;



&lt;p&gt;&lt;em&gt;If you have questions about the swarm orchestration, &lt;br&gt;
the Air-Gap middleware, or the Tor deploy pipeline — &lt;br&gt;
ask in the comments. I'll answer everything.&lt;/em&gt;&lt;/p&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__body flex items-center justify-between"&gt;
        &lt;a href="https://rougestudio.vercel.app" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;rougestudio.vercel.app&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>opensource</category>
      <category>ai</category>
      <category>cybersecurity</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
