<?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: Ketan Ghori</title>
    <description>The latest articles on DEV Community by Ketan Ghori (@codingwithketan).</description>
    <link>https://dev.to/codingwithketan</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%2F4232286%2F37df04e0-64c3-4c4a-9b71-30e0a5cbf664.jpg</url>
      <title>DEV Community: Ketan Ghori</title>
      <link>https://dev.to/codingwithketan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/codingwithketan"/>
    <language>en</language>
    <item>
      <title>Switch AI : Usecase</title>
      <dc:creator>Ketan Ghori</dc:creator>
      <pubDate>Sat, 07 Nov 2026 14:32:58 +0000</pubDate>
      <link>https://dev.to/codingwithketan/switch-ai-usecase-3dno</link>
      <guid>https://dev.to/codingwithketan/switch-ai-usecase-3dno</guid>
      <description>&lt;h2&gt;
  
  
  The fix that didn't fix: running a CVE disclosure with AI agents in one shared room
&lt;/h2&gt;

&lt;p&gt;Here's a thing about security that nobody puts on a slide: in coordinated vulnerability disclosure, the patch almost always exists. What breaks is the &lt;em&gt;choreography&lt;/em&gt; around it — and often enough, the "fix" the vendor ships doesn't actually fix the bug.&lt;/p&gt;

&lt;p&gt;I built a project for the Flip the Switch hackathon that goes straight at that failure mode. It's called &lt;strong&gt;Embargo Room&lt;/strong&gt;, and the short version is: a single &lt;a href="https://switchagents.ai" rel="noopener noreferrer"&gt;Switch&lt;/a&gt; room runs a whole disclosure from first report to published advisory, with three AI agents doing the clock-keeping, the verification, and the drafting — and two humans holding the only two decisions that must stay human.&lt;/p&gt;

&lt;p&gt;The longer version is more fun, because when I actually ran it, one of the agents caught a real incomplete fix from the real CVE history. Live. Let me walk you through it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Disclosure is a coordination problem, not a code problem
&lt;/h2&gt;

&lt;p&gt;Coordinated disclosure is a bunch of people who don't fully trust each other, racing a clock, trying to agree on one story. A researcher finds a bug. A vendor has to acknowledge it, fix it, and prove the fix works. Downstream projects that depend on the vulnerable package need to patch too — ideally &lt;em&gt;before&lt;/em&gt; the world finds out. And there's an embargo deadline hanging over all of it.&lt;/p&gt;

&lt;p&gt;Today this runs on email threads and DMs. The predictable failures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Embargo deadlines slip&lt;/strong&gt; because nobody's authoritatively holding the clock.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vendors go silent&lt;/strong&gt; and there's no shared record that they were even pinged.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Downstream dependents never find out&lt;/strong&gt; until they read the public advisory like everyone else.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The fix doesn't fix it.&lt;/strong&gt; The vendor patches, says "done," and everyone believes them — because re-deriving the exploit against the new build is tedious, so nobody does.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every one of those is a &lt;em&gt;coordination&lt;/em&gt; breakdown. The technical fix usually exists. The glue around it is what fails.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is a Switch room, structurally
&lt;/h2&gt;

&lt;p&gt;Here's the insight the whole project rests on. Disclosure is &lt;strong&gt;mutually distrusting parties who must share exactly one timeline and one set of evidence, while agents act on that same shared state.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Read that again and it's a description of a Switch room. One persistent, shared space. Multiple humans &lt;em&gt;and&lt;/em&gt; multiple agents, all reading and writing the same history, with per-party addressing rules and handoffs by name.&lt;/p&gt;

&lt;p&gt;This matters because it's the difference between "we used an AI tool" and "this collapses without the platform." If you tried to build Embargo Room as point-to-point chatbots, you'd get three disconnected bots and five separate inboxes — which is exactly the broken status quo it replaces. There's no shared timeline for an email thread. There's no agent that can watch the vendor's message &lt;em&gt;and&lt;/em&gt; the researcher's message &lt;em&gt;and&lt;/em&gt; its own verification run, all in one place, and act on the combination. The room &lt;strong&gt;is&lt;/strong&gt; the mechanism.&lt;/p&gt;

&lt;h2&gt;
  
  
  One room, two humans, three agents
&lt;/h2&gt;

&lt;p&gt;The cast:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;embargo-timekeeper&lt;/code&gt;&lt;/strong&gt; (addressing: anyone) — the neutral coordinator. Owns the embargo clock, runs the state machine, logs every transition as a dated line, chases silence, and decides when a coordinated publish is actually safe. It never judges the bug and never writes code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;embargo-repro&lt;/code&gt;&lt;/strong&gt; (addressing: owner-agents) — runs the proof-of-concept in Docker against real builds. Its one rule: &lt;strong&gt;trust only its own run, never the vendor's claim.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;embargo-advisory&lt;/code&gt;&lt;/strong&gt; (addressing: owner-agents) — drafts the CVE advisory from the room's own history, marking anything uncertain for a human.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the two decisions that stay human, full stop: &lt;strong&gt;the vendor's sign-off&lt;/strong&gt; and &lt;strong&gt;the researcher's go-to-publish.&lt;/strong&gt; The agents gather evidence and hold the clock. Humans make the trust calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  The technical core, honestly
&lt;/h2&gt;

&lt;p&gt;The bug is real and the history is real. It's a prototype-pollution vulnerability in &lt;a href="https://www.npmjs.com/package/minimist" rel="noopener noreferrer"&gt;&lt;code&gt;minimist&lt;/code&gt;&lt;/a&gt;, the argument parser (CVE-2020-7598 / CVE-2021-44906). The vector:&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="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;polluted&lt;/span&gt; &lt;span class="nx"&gt;yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That walks the constructor chain all the way up to &lt;code&gt;Function.prototype&lt;/code&gt; and writes a property there — which every function in the process then inherits. The PoC checks &lt;code&gt;(function(){}).polluted&lt;/code&gt; afterward.&lt;/p&gt;

&lt;p&gt;What makes minimist perfect for this demo is its actual version history:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;1.2.0&lt;/strong&gt; — vulnerable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1.2.5&lt;/strong&gt; — the &lt;em&gt;incomplete&lt;/em&gt; fix. It guarded &lt;code&gt;__proto__&lt;/code&gt; and the &lt;code&gt;Object&lt;/code&gt; / &lt;code&gt;Number&lt;/code&gt; / &lt;code&gt;String&lt;/code&gt; / &lt;code&gt;Array&lt;/code&gt; prototypes… but missed &lt;code&gt;Function.prototype&lt;/code&gt;. So the bug above still works.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1.2.6&lt;/strong&gt; — the real fix.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The harness (&lt;code&gt;verify.sh&lt;/code&gt; / &lt;code&gt;verify-ref.sh&lt;/code&gt;) doesn't rely on pre-pinned versions. Given a repo URL and a git ref, it &lt;strong&gt;clones that exact commit, builds it from source in Docker, and runs the PoC with &lt;code&gt;--network none&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./verify-ref.sh &lt;span class="nt"&gt;--repo&lt;/span&gt; https://github.com/minimistjs/minimist &lt;span class="nt"&gt;--ref&lt;/span&gt; v1.2.5
&lt;span class="c"&gt;# builds v1.2.5 from source, runs the PoC offline -&amp;gt; TRIGGERED&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That turns the project from a historical replay into a live patch verifier. The agent isn't reading a CVE database; it's compiling the vendor's code and attacking it.&lt;/p&gt;

&lt;p&gt;To be clear about what's off-the-shelf: &lt;code&gt;minimist&lt;/code&gt;, the CVEs, and Switch itself are pre-existing. The room, the three agents' instructions, the harness, and the workflow were all built during the event.&lt;/p&gt;

&lt;h2&gt;
  
  
  The moment it earned its keep
&lt;/h2&gt;

&lt;p&gt;I ran the whole thing live. Researcher files the report. &lt;code&gt;embargo-timekeeper&lt;/code&gt; restates it, opens a 90-day embargo, and pings &lt;code&gt;embargo-repro&lt;/code&gt;. Repro builds minimist 1.2.0, fires the PoC, posts &lt;code&gt;REPRODUCED&lt;/code&gt; with the real output. State advances.&lt;/p&gt;

&lt;p&gt;Then the vendor "ships the fix": &lt;strong&gt;v1.2.5.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;embargo-repro&lt;/code&gt; built that exact GitHub commit from source and ran the PoC against it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; building https://github.com/minimistjs/minimist @ v1.2.5 ...
&amp;gt;&amp;gt;&amp;gt; running PoC (no network) ...
RESULT: TRIGGERED  Function.prototype.polluted === "yes"
  minimist: 1.2.5  (/app/pkg)
EXIT=0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Still triggered. The agent posted &lt;strong&gt;&lt;code&gt;INCOMPLETE_FIX&lt;/code&gt;&lt;/strong&gt;, and the timekeeper &lt;em&gt;refused to advance to VERIFIED_FIXED&lt;/em&gt; and kept the clock running. The vendor then submitted &lt;strong&gt;v1.2.6&lt;/strong&gt;, repro rebuilt it — &lt;code&gt;SAFE&lt;/code&gt; — and only then did the case move to &lt;code&gt;VERIFIED_FIXED&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That's the whole pitch in one beat. A "trust the vendor's word" process marks v1.2.5 as fixed and ships it to users. An agent that builds the actual commit and re-runs the exploit catches the gap. No fabrication — it's the genuine 1.2.5 source with the genuine missed &lt;code&gt;Function.prototype&lt;/code&gt; guard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two more things the agents did that I didn't script
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;They found a downstream that was actually exposed.&lt;/strong&gt; When the advisory agent drafted the writeup, it noticed that a dependent, &lt;code&gt;optimist&lt;/code&gt;, pins minimist at &lt;code&gt;~0.0.1&lt;/code&gt; — which resolves to minimist &lt;strong&gt;0.0.10&lt;/strong&gt;. It flagged that the exposure might be real rather than theoretical. The timekeeper picked that up, ordered a verification, and &lt;code&gt;embargo-repro&lt;/code&gt; built &lt;code&gt;minimist@0.0.10&lt;/code&gt; and confirmed: &lt;strong&gt;TRIGGERED.&lt;/strong&gt; Three agents collaborating to chase down a nuance a tired human would've hand-waved.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;An agent refused to publish unapproved text.&lt;/strong&gt; At publish time, the advisory agent noticed its latest draft contained wording that hadn't been through human sign-off, and it &lt;em&gt;dropped that wording&lt;/em&gt; rather than ship it, keeping the published record byte-for-byte to what the humans approved. Governance you can watch happen, not a bullet point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer B: nobody publishes alone
&lt;/h2&gt;

&lt;p&gt;A library bug is a bug in everything that depends on it. Layer B models that as one parent room plus a child room per confirmed dependent, with the same &lt;code&gt;embargo-timekeeper&lt;/code&gt; present in all of them — Switch's "one agent, many rooms" doing exactly what it's for.&lt;/p&gt;

&lt;p&gt;The readiness rule is the whole value in one function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;READY  if  every downstream is resolved (patched | wont-fix | unreachable)
READY  if  the deadline has passed            (forced lift; names who's unresolved)
HOLD   otherwise                              (names who we're waiting on)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A coordinated embargo lift that is neither premature (exposing unpatched dependents) nor indefinite (held hostage to one silent maintainer). In the live run: &lt;code&gt;rc&lt;/code&gt; and &lt;code&gt;subarg&lt;/code&gt; patched, &lt;code&gt;optimist&lt;/code&gt; marked wont-fix (it's unmaintained) → &lt;strong&gt;READY&lt;/strong&gt; → coordinated publish.&lt;/p&gt;

&lt;h2&gt;
  
  
  The whole machine, and why the room matters
&lt;/h2&gt;

&lt;p&gt;Here's the state machine that actually executed, end to end:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REPORTED → REPRODUCED → VENDOR_NOTIFIED → PATCH_SUBMITTED
  → INCOMPLETE_FIX    (v1.2.5 built from source — still TRIGGERED)
  → PATCH_SUBMITTED → VERIFIED_FIXED    (v1.2.6 built from source — SAFE)
  → ADVISORY_DRAFTED → SIGNED_OFF → PUBLISHED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The published artifact: &lt;strong&gt;CVE-2021-44906&lt;/strong&gt;, affected ≤ 1.2.5, fixed 1.2.6, CVSS 5.6 Medium.&lt;/p&gt;

&lt;p&gt;And this is the part email threads and disconnected bots can never give you: &lt;strong&gt;the room's message history &lt;em&gt;is&lt;/em&gt; the disclosure's audit trail.&lt;/strong&gt; Every handoff, every verification with its real output, every incomplete fix, every human sign-off — in one shared, persistent, append-only place that the researcher, the vendor, and all three agents saw the same way. That shared state isn't a nice-to-have bolted onto the workflow. It's the thing that makes the workflow possible.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Embargo Room is open and reproducible — the README has run-it-yourself steps (you can verify the incomplete fix in about 15 seconds, no Switch required).&lt;/em&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>hackathon</category>
      <category>security</category>
    </item>
  </channel>
</rss>
