DEV Community

Srikanth Vuppala
Srikanth Vuppala

Posted on

Your AI coding agent is a security reviewer. It just needs a brief.

Ask Claude Code, Cursor or Gemini CLI to "review this repo for security issues" twice, and you'll get two different answers in two different shapes. The review itself can be good. But you can't compare runs, track a finding across releases, or show an auditor what "passed" means.

We built secfoo (MIT) to fix that. It doesn't replace your agent. It gives the agent a disciplined brief and holds the output to a fixed contract.

The idea: skills, not rules

Most security scanners are rules engines. secfoo takes a different approach. A skill is a structured prompt that defines the activity, the method, and the exact shape of the report. secfoo gives the skill and a target to the coding-agent CLI you already have on your PATH, and the agent reads the code the way a human reviewer would.

Supported agents: Claude Code, Cursor, Antigravity, Gemini CLI and Codex CLI (--agent claude|agent|agy|gemini|codex).

Quick start

pip install secfoo
secfoo run --skill security-architecture-review --agent claude
Enter fullscreen mode Exit fullscreen mode

Run several activities at once. They execute concurrently:

secfoo run --skill sast --skill threat-modeling \
  --target https://github.com/org/repo --agent claude
Enter fullscreen mode Exit fullscreen mode

Then browse every assessment, across every project, locally:

secfoo serve
Enter fullscreen mode Exit fullscreen mode

Prefer not to use Python? npm install -g @rakfortltd/secfoo or docker run --rm ghcr.io/rakfortltd/secfoo --help.

What's in the catalog

Activity Skill ID
Security Architecture Review security-architecture-review
Threat Modeling (STRIDE + LINDDUN) threat-modeling
SAST sast
SCA reachability & upgrade triage sca-reachability
Secret scanning (code, git history, Confluence) secret-scanning
Prompt review (LLM prompts & agent tools) prompt-review
Deployment readiness deployment-readiness
Responsible AI compliance responsible-ai-compliance

Three design choices we'd make again

1. One case file per system. Repeat runs are grouped under the same application ID. Findings move between Open and Closed as you rescan, so they don't pile up in a new report each time.

2. Local-first. Runs, reports and the dashboard stay on your machine. You don't need an account for your first scan.

3. Honest about what a report can support. If a report can't back up a number, the dashboard shows zeros or hatching rather than guessing.

No agent CLI? Use an API key (good for CI)

pip install "secfoo[api]"
export ANTHROPIC_API_KEY=...   # or OPENAI_API_KEY / GEMINI_API_KEY
secfoo run --skill sast --agent api --target https://github.com/org/repo
Enter fullscreen mode Exit fullscreen mode

The built-in api agent is a LangGraph workflow routed through LiteLLM. Keys are read from the environment and never stored. It works best on small and medium repos, because the whole target goes in one request.

Know what the AI review cost

secfoo cost                 # by agent
secfoo cost --by skill --since 2026-09-01
Enter fullscreen mode Exit fullscreen mode




Try it and tell us what breaks

We'd especially value feedback on the skill format. If you write a skill for an activity we don't cover yet, open a PR.

Top comments (2)

Collapse
 
hamid_ahmadian_3570449f72 profile image
Hamid Ahmadian

The "one case file per system, findings move between Open/Closed" design is the part I'd push hardest on, because that's the piece most rules-engine scanners get wrong for agent-generated output specifically. Two runs of the same prompt against the same repo commit can phrase a finding differently enough that a naive diff treats it as new — so the dedup key can't just be "message text," it has to be something closer to (rule/skill id, file path, code-region hash) that's stable across paraphrase. Curious how secfoo identifies "the same finding" across runs when the agent's wording drifts — is it doing any embedding-similarity matching on the finding description, or is it keying purely off structural fields the skill's prompt forces the agent to fill in (file, line range, CWE, etc.)? If it's the latter, that's honestly the more robust approach — it works because the constraint is on the input contract, not on post-hoc text matching.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.