Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
layout: default
title: AI PatchLab Scans
description: "95 curated security scans of open-source AI agents, MCP servers and LLM apps - 21 confirmed fixes, run local-first with Semgrep, Gitleaks, Trivy and pip-audit."
description: "97 curated security scans of open-source AI agents, MCP servers and LLM apps - 21 confirmed fixes, run local-first with Semgrep, Gitleaks, Trivy and pip-audit."
---

# AI PatchLab Scans
Expand All @@ -20,7 +20,7 @@ remediation and confidence rules to normalize the findings.

> **Want this run privately against your own codebase?** I do independent
> security review of AI agents, MCP servers, and LLM apps —
> [**work with me →**]({{ '/work-with-me' | relative_url }}). 96 scans, 21 confirmed fixes, methodology in the open.
> [**work with me →**]({{ '/work-with-me' | relative_url }}). 97 scans, 21 confirmed fixes, methodology in the open.

> **OpenAI just launched [Daybreak](https://openai.com/index/daybreak-securing-the-world/) and Patch the Planet.**
> Same remediation loop, opposite trade-off: their path is a cloud frontier model;
Expand Down Expand Up @@ -94,12 +94,13 @@ login and static assets. Fifty-two flagged, none reported.

## All scans

96 scans, newest first. **Findings** is the raw count the tools produced;
97 scans, newest first. **Findings** is the raw count the tools produced;
**Real** is what survived curation. The gap between those two columns is the
entire job.

| Date | Repository | Findings | Real | Outcome |
|---|---|---:|---|---|
| 2026-09-07 | [realiti4/claude-swap](scans/realiti4-claude-swap.html) | 22 | 0 real | — |
| 2026-09-06 | [ApodexAI/FrontierAgent](scans/apodexai-frontieragent.html) | 58 | 1 real — withheld | private |
| 2026-09-05 | [doobidoo/mcp-memory-service](scans/doobidoo-mcp-memory-service.html) | 176 | 0 real | — |
| 2026-09-04 | [basicmachines-co/basic-memory](scans/basicmachines-co-basic-memory.html) | 270 | 0 real | — |
Expand Down
3 changes: 2 additions & 1 deletion docs/scan-log.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ description: "The complete AI PatchLab scan log: every public repository scanned

# Full scan log

Every scan in the series, newest first, with the summary written on the day of the scan. 96 scans. For the compact index, see the [scan log home]({{ '/' | relative_url }}).
Every scan in the series, newest first, with the summary written on the day of the scan. 97 scans. For the compact index, see the [scan log home]({{ '/' | relative_url }}).

- **2026-09-07** — [realiti4/claude-swap](scans/realiti4-claude-swap.html) — 22 findings (20 above the medium floor), **zero real after curation; thirty-first clean scan** — a **multi-account credential switcher for Claude Code** (2.4k★, MIT, eight months old, 52 merged PRs from 27 authors and 40 closed issues from 31 authors in 60 days): a tool whose entire job is reading, copying, refreshing, exporting and handing off OAuth refresh tokens, chosen as the stress test for the credential-handling question set four days after the [davinci-resolve-mcp](scans/samuelgursky-davinci-resolve-mcp.html) token-in-log finding. **Full coverage for once** — Semgrep 55 files, 0 skipped, `errors: []`; Trivy on `uv.lock` and pip-audit on `pyproject.toml` both empty and agreeing. **Every one of the 22 collapsed**, and five of them are the clearest [active-harm false positive](scans/roflcoopter-viseron.html) yet: `insecure-file-permissions` fired five-for-five on `os.chmod(dir, 0o700)`, the project *tightening* its directories, with a remediation that would loosen them. Four `dynamic-urllib` hits on four constant URLs (Anthropic's token/profile/usage endpoints and PyPI); the lone High is Gitleaks on Claude Code's own *public* OAuth client id (13th placeholder-tier vote); the logger rule matched a parameter name in scope. **The hand sweep is a defence inventory, and several entries close classes this series has filed elsewhere**: `/usr/bin/security` pinned by absolute path with secrets passed over stdin so they never reach argv (the davinci class, anticipated); every credential writer on `mkstemp` with a docstring explaining why write-then-chmod is wrong; a salvage copy that uses `copy` not `copy2` because a prior cut *measured* a `primaryApiKey` landing world-readable; session launch scrubbing five auth-override env vars then `execvpe`; import validating email and slot before either reaches a filename; export that strips device-bound tokens and machine identity and refuses an envelope claiming to be encrypted; OAuth error classification by the RFC 6749 `error` member rather than a substring. **One hardening note, published in full because it is a race with a one-line fix, not a vulnerability**: `_write_json` is the single writer of eight that still does write-then-chmod, and four of its call sites write the *live* `~/.claude.json` — a temp file in `$HOME`, a directory the project does not own, at umask mode for the duration of the write; the file is secret-adjacent (MCP server `env`/`headers`), verified against a current install, and the fix is the project's own `atomic_write_json`, already used at seven sibling sites. Graded Low, three preconditions, not filed — the [Nth-implementation-that-differs](scans/zilliztech-memsearch.html) shape on file writers. Not strict-norm (no `SECURITY.md`, PVR off) · post-only, nothing filed
- **2026-09-06** — [ApodexAI/FrontierAgent](scans/apodexai-frontieragent.html) — 58 findings (58 above the medium floor), **1 real — withheld** — an **agent runtime, terminal product and evaluation suite** (1.8k★ two weeks after going public, Apache-2.0, Apodex AI): ReAct and coordinator-plus-sub-agents workflows over a task-scoped sandbox, a fifty-module plugin tool tree, and an optional Gradio demo for a Hugging Face Space, with a real `SECURITY.md` (named mailbox, 48h ack, public vuln issues forbidden) and private vulnerability reporting enabled. **Every one of the 58 collapsed on inspection** — loader imports keyed on a runtime class, an execution epoch logged as a "token" (seven-for-seven false), `sk-test-…` placeholders inside the project's own *leak-guard test suite*, operator-configured endpoints behind the `urllib` rule, the sandbox shell itself behind `shell=True`, a tar extractor that both resolves members and passes `filter="data"`. **The real finding is the composite class no rule sees:** a download allow-list one directory too wide, in a component whose README records — as *verified* — that the sibling directory it exposes is never served to a browser; the [docstring-as-oracle](scans/hkuds-openopc.html) diff between that paragraph and one launch argument is the whole finding. Verified by execution both ways: the artifact served, then the one-line remedy keeping deliverables downloadable while the artifact returns 403. Same-session only, filed Low; class only here · reported privately via GitHub PVR, post-only
- **2026-09-05** — [doobidoo/mcp-memory-service](scans/doobidoo-mcp-memory-service.html) — 176 findings, **zero real after curation; thirtieth clean scan** — a persistent memory server for AI agents (1.9k★) that published **four critical advisories on the exact day of the scan**, all fixed at HEAD, and the tools surfaced none of them: every one was an absence or a parity gap (an auth check missing on one transport that its sibling had). The dominant cluster was the parameterized-SQL identifier FP, ninth appearance in the series · post-only, strict-norm target
- **2026-09-04** — [basicmachines-co/basic-memory](scans/basicmachines-co-basic-memory.html) — 270 findings, **zero real after curation; twenty-ninth clean scan** — a local-first Markdown knowledge base with an MCP server; the volume was fixtures, identifier-only SQL and by-design file tooling on a project whose purpose is reading and writing the user's own notes · post-only, strict-norm target
Expand Down
Loading
Loading