<?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: Adith Biji</title>
    <description>The latest articles on DEV Community by Adith Biji (@adith_biji_2227c916082ddd).</description>
    <link>https://dev.to/adith_biji_2227c916082ddd</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%2F4166889%2F7366d179-6a7a-4476-9a6a-868d9b836900.jpg</url>
      <title>DEV Community: Adith Biji</title>
      <link>https://dev.to/adith_biji_2227c916082ddd</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adith_biji_2227c916082ddd"/>
    <language>en</language>
    <item>
      <title>Most AI security tools lock you into one agent. We didn't.</title>
      <dc:creator>Adith Biji</dc:creator>
      <pubDate>Tue, 27 Oct 2026 19:01:39 +0000</pubDate>
      <link>https://dev.to/adith_biji_2227c916082ddd/most-ai-security-tools-lock-you-into-one-agent-we-didnt-3hf7</link>
      <guid>https://dev.to/adith_biji_2227c916082ddd/most-ai-security-tools-lock-you-into-one-agent-we-didnt-3hf7</guid>
      <description>&lt;p&gt;If you're running security reviews with an AI coding agent, you've probably noticed that different agents produce wildly different output for the exact same task. Ask Claude Code to do a SAST pass and you get one shape of report. Ask Gemini CLI or Codex the same question and you get another, different headings, different severity language, sometimes a different idea of what counts as a "finding" at all.&lt;/p&gt;

&lt;p&gt;Most agentic security tools deal with this by picking one agent and building around it. We built SecFoo to work with whatever you've already got instead: Claude Code, Cursor, Gemini CLI, Codex, GitHub Copilot CLI, Antigravity, Factory Droid, or Devin. Same 9 security skills (SAST, secret scanning, threat modeling, SCA reachability, security architecture review, and a few others), your choice of agent, comparable output every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that was actually hard
&lt;/h2&gt;

&lt;p&gt;Writing a good security review prompt isn't the hard part. The hard part is getting nine wildly different agents to produce results you can parse, compare, and track over time, without hardcoding around any single one of them.&lt;/p&gt;

&lt;p&gt;SecFoo handles this with an adapter layer. Every agent integration subclasses a common AgentAdapter base class that owns the boring-but-critical stuff: binary detection, timeouts, process-tree kill on timeout (important: some agents spawn grandchildren that outlive a naive kill()), and result capture. Each adapter's actual job is small: build the right command line for that agent, and parse its usage/cost figures if it reports them.&lt;/p&gt;

&lt;p&gt;On top of that, every skill has a fixed output contract: a required "Overall risk rating:" line, and "### [SEVERITY] ID: title" headings for every finding. It doesn't matter if Claude Code phrases a finding one way and Codex phrases the same category of bug completely differently, SecFoo can still parse severity, CWE, and location out of either, because the contract is enforced at the skill level, not left to whatever the agent feels like producing that day.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a run actually does
&lt;/h2&gt;

&lt;p&gt;For anyone curious about the mechanics, here's the pipeline for a single --skill run (skills run concurrently when you pass more than one):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Resolve the target - a local path as-is, or a shallow clone of a GitHub URL, cleaned up afterward.&lt;/li&gt;
&lt;li&gt;Detect the stack - languages from file extensions, frameworks from manifests (package.json, requirements.txt, pom.xml, go.mod). Never inferred from the model's own prose, so it's consistent across runs and across agents.&lt;/li&gt;
&lt;li&gt;Render the prompt - a read-only safety preamble, the skill's instructions, depth guidance, scope exclusions, and the skill's output contract.&lt;/li&gt;
&lt;li&gt;Run the agent - the adapter launches the agent CLI as a subprocess (or calls a model API directly for the api agent), with a timeout and process-tree kill.&lt;/li&gt;
&lt;li&gt;Capture - report, prompt, and logs get written locally, plus token/cost figures where the agent reports them.&lt;/li&gt;
&lt;li&gt;Parse - severity counts and structured findings get pulled out of the report using the fixed contract, and CVSS scores get computed by SecFoo itself rather than trusted from the agent's own text.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Steps 3 through 6 are where the adapter pattern earns its keep: everything downstream of "run the agent" is agent-agnostic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this is still rough
&lt;/h2&gt;

&lt;p&gt;Not every agent gets equal treatment yet. MCP tooling (used for things like Confluence context) is wired up automatically for Claude Code, and available via a one-time secfoo mcp sync for Cursor and Gemini CLI, but Codex, Copilot, Droid, and Devin don't have it wired yet. Antigravity's CLI doesn't expose an MCP mechanism at all, so it's a dead end there for now. The api agent (plain model API via LiteLLM, no CLI) has no tool loop, so it just gets the target's source pasted into the prompt, fine for small to medium repos, not great for anything large.&lt;/p&gt;

&lt;p&gt;None of that is hidden. It's the honest state of an open source project that's still adding adapters.&lt;/p&gt;

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

&lt;p&gt;SecFoo is MIT licensed: &lt;a href="https://github.com/secfoo-com/secfoo" rel="noopener noreferrer"&gt;https://github.com/secfoo-com/secfoo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're already running Claude Code, Cursor, Gemini, Codex, Copilot CLI, or any of the others for day to day work, this points the same agent at your repo for a security pass instead of needing a separate, agent-specific tool. Built at RakFort (&lt;a href="https://www.linkedin.com/company/rakfort" rel="noopener noreferrer"&gt;https://www.linkedin.com/company/rakfort&lt;/a&gt;). Curious what agent CLIs people are actually standardizing on, and whether consistency across agents is a problem anyone else has run into outside of security review specifically.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>security</category>
      <category>ai</category>
      <category>cli</category>
    </item>
    <item>
      <title>We caught our own AI security scanner making up vulnerabilities</title>
      <dc:creator>Adith Biji</dc:creator>
      <pubDate>Tue, 06 Oct 2026 16:26:03 +0000</pubDate>
      <link>https://dev.to/adith_biji_2227c916082ddd/we-caught-our-own-ai-security-scanner-making-up-vulnerabilities-e6i</link>
      <guid>https://dev.to/adith_biji_2227c916082ddd/we-caught-our-own-ai-security-scanner-making-up-vulnerabilities-e6i</guid>
      <description>&lt;p&gt;SecFoo is an open-source CLI that runs AI coding agents (Claude, Copilot, Codex, or a plain API key) as security reviewers against your codebase, tracks findings over time, and serves a local dashboard. One of the agent options — call it &lt;code&gt;secfoo&lt;/code&gt; — is supposed to work with nothing but an OpenAI/Anthropic/Gemini API key, no coding-agent CLI installed.&lt;/p&gt;

&lt;p&gt;While testing it end-to-end, we found it was fabricating entire security reports.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we found
&lt;/h2&gt;

&lt;p&gt;We ran it against a small, intentionally-vulnerable Flask app (the whole codebase is one file, &lt;code&gt;app.py&lt;/code&gt;) and asked it to do a SAST scan. It came back with "Confirmed" findings — SQL injection, XSS — at files like &lt;code&gt;app/db.py&lt;/code&gt; and &lt;code&gt;app/upload.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Neither file exists anywhere in the repository.&lt;/p&gt;

&lt;p&gt;We ran it again with a different scan type (secret scanning) against the same target. This time it reported a "Confirmed, looks live" AWS access key in &lt;code&gt;deploy/ci.yml&lt;/code&gt;, with a recommendation to rotate it immediately.&lt;/p&gt;

&lt;p&gt;There is no &lt;code&gt;deploy/&lt;/code&gt; directory in that repository. There is no AWS key anywhere in it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it happened
&lt;/h2&gt;

&lt;p&gt;The root cause was almost embarrassingly simple once we traced it: that agent's code builds the message it sends to the model from the prompt text alone — it never reads the target's actual source files and attaches them. The model is asked "review this codebase for SQL injection, XSS, etc." with no codebase attached. It has no way to say "I don't have the file," because nothing tells it a file was supposed to be there. So it does what a language model does when asked a confident question with no grounding: it generates a plausible, well-formatted answer that matches the shape of a real report.&lt;/p&gt;

&lt;p&gt;We'd already built a second, correct implementation (&lt;code&gt;api&lt;/code&gt;) that does read and attach the actual files before calling the model — the bug was that the old, broken draft never got deleted when the new one shipped. Both were selectable, with nothing distinguishing a working scan from a hallucinated one. The existing unit test for the broken version actually asserted the broken behavior as correct, so CI never caught it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we did about it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Reproduced it twice, on two different scan types, against the same real target, to rule out a fluke&lt;/li&gt;
&lt;li&gt;Root-caused it to the exact missing step (the broken agent never attaches source files, confirmed via the code and via a passing-but-wrong unit test)&lt;/li&gt;
&lt;li&gt;Deleted the broken implementation entirely rather than patch around it&lt;/li&gt;
&lt;li&gt;Ran the full test suite (700+ tests) plus security linting on the fix&lt;/li&gt;
&lt;li&gt;Opened it as a PR with the full repro steps attached, so anyone can verify it independently: &lt;a href="https://github.com/secfoo-com/secfoo/pull/20" rel="noopener noreferrer"&gt;https://github.com/secfoo-com/secfoo/pull/20&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why this matters beyond our own bug
&lt;/h2&gt;

&lt;p&gt;This is the failure mode you should worry about with any "AI reviews your code" tool: a run that reports &lt;code&gt;success&lt;/code&gt;, produces a professional-looking report, uses confident language like "Confirmed" and "high confidence" — and is completely disconnected from the actual code. Not a crash, not an error message. A clean green checkmark hiding zero actual review.&lt;/p&gt;

&lt;p&gt;We think the fix for that isn't "trust the AI less," it's "verify the AI the same way you'd verify any other system" — reproduce, trace to root cause, and write a test that would have actually caught it. That's what we did here, and it's the standard we're trying to hold every skill and every agent in SecFoo to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&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;secfoo
secfoo run &lt;span class="nt"&gt;--skill&lt;/span&gt; sast &lt;span class="nt"&gt;--agent&lt;/span&gt; claude &lt;span class="nt"&gt;--target&lt;/span&gt; https://github.com/your/repo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repo: &lt;a href="https://github.com/secfoo-com/secfoo" rel="noopener noreferrer"&gt;https://github.com/secfoo-com/secfoo&lt;/a&gt; — MIT licensed, 9 skills (SAST, secret scanning, threat modeling, architecture review, and more), works with Claude, Copilot, Codex, or a plain API key.&lt;/p&gt;

&lt;p&gt;We're a small team building this in the open. Issues, PRs, and skepticism all welcome.&lt;/p&gt;

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