Skip to the content.

ag2ai/ag2 - security scan

Repository: ag2ai/ag2 Commit scanned: b6f271ed99a5ca65a586bbcde6bda6cbaafd3315 Scan date: 2026-06-26 Disclosure status: public — post-only (no real, high-confidence item cleared the bar; no upstream issue filed)

Summary

Severity Count
Critical 0
High 44
Medium 29
Low 0 (filtered at --min-severity medium)
Info 0

Total findings: 73 (0 real, reachable, undefended after curation)

AG2 (formerly AutoGen) is the open-source multi-agent framework — the canonical “agents that write and run code” toolkit. Scanning it is interesting precisely because the scary findings are supposed to be there: a framework whose job is to execute LLM-generated Python, run Docker sandboxes, and exec() retrieved tools will light up every code-execution rule a scanner owns. The curation question isn’t “does it run code” — it’s “is anything running code it didn’t intend to,” and “did the maintainers guard the one spot where an injection actually crosses a trust boundary.” On both counts AG2 comes out clean: the deps are current (Dependabot is wired and trivy found a single devcontainer nit), the one genuine eval-injection vector is already patched against AG2’s own advisory, and all 19 secret hits are false positives.

Top findings

1. The eval() that matters is already patched against AG2’s own advisory

2. Every code-execution finding is the product, not a bug

3. All 19 secret hits are false positives

4. The one genuine hardening observation: ag2 serve ships no auth and a --ngrok flag

Patterns observed

A code-execution framework inverts the usual curation question. For most repos the job is finding the one dangerous call in a sea of safe ones. For AG2 the dangerous calls are the API — exec, docker run, LocalCommandLineCodeExecutor, Jupyter kernels — and the job flips to “is there execution the framework didn’t mean to allow, and is the one real injection boundary guarded?” The answer is no unintended execution and yes guarded: the ContextExpression eval, the single place where attacker-influenced data meets eval(), is escaped and carries a GHSA reference. That’s the signature of a project that has already done its own security review.

The false-positive profile is textbook, and the maintainers pre-annotated it. 18 insecure-websocket hits are mostly ws:// in blog/docs .mdx files; the secret scanner fires on docstring examples and a renderer’s string constants. The # pragma: allowlist secret on the docstring key is the detail that matters — it means the maintainers already ran a secret scanner, saw the same FP, and suppressed it. Re-reporting it as “high” would be noise.

The residual is a missing feature, not a flaw. The honest takeaway from AG2 is the ag2 serve exposure story: no auth, wildcard CORS, an internet-exposure flag, on a framework whose agents can run code. It’s a real hardening opportunity, but it’s gated entirely behind operator choices (build a code-exec agent, serve it, expose it) and the CORS is the credential-less variant. On a sophisticated, responsive, Apache-community project that has demonstrably patched its own eval-injection, the disciplined call is to document it here rather than file a marginal issue — the same call the Kiln scan reached the day before.

Notes on the tool

Disclosure timeline

This is a post-only write-up. Curation found no real, reachable, undefended item that clears the quality gate: the code-execution surface is the documented product, the one eval-injection boundary is patched against AG2’s own GHSA, the secret hits are pre-annotated false positives, and the ag2 serve exposure is a hardening opportunity gated behind operator choices, below the bar for an unsolicited issue.

Reproduce

git clone https://github.com/ag2ai/ag2 /tmp/scan-target
python scanner/run_scan.py --repo /tmp/scan-target \
  --reports-dir ./reports/ag2ai-ag2 \
  --min-severity medium --ignore-samples