AI PatchLab Scans
Security scans of public repositories run with AI PatchLab, an open-source, local-first security scanner.
Every report on this page was generated locally. No source code was sent to any third party, no AI provider was contacted, and no paid API was called. AI PatchLab orchestrates Semgrep, Gitleaks, Trivy, and pip-audit, then applies deterministic 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 →. 75 scans, 13 confirmed fixes, methodology in the open.
OpenAI just launched Daybreak and Patch the Planet. Same remediation loop, opposite trade-off: their path is a cloud frontier model; this one keeps your code on your disk. Why local-first still matters →
How these scans work
- Each scan targets a public repository at a specific commit.
- Findings are curated: noise filtered out, top items highlighted.
- Critical issues are reported to maintainers under responsible disclosure before being published here in full detail.
- Posts focus on patterns and lessons — not exploit walkthroughs.
Scans
- 2026-08-12 — jgravelle/jcodemunch-mcp — 49 findings (47 above the medium floor), zero real — an MCP server for symbol-level code retrieval (2.5k★, 258 Python files): it parses a repository with tree-sitter, indexes the symbols, and hands an agent exactly the function it asked for instead of whole files, pitching a 95% cut in tokens spent on code exploration — with a VS Code extension, a CLI, an optional login-time file watcher, a published GitHub Action and a paid team tier around it. The most document-dense target in the series, and that is the whole story of the day: 34 Markdown files at the root and a
SECURITY.mdthat is 26 KB long and is not a disclosure policy — it is a controls specification, naming the path validator and the symlink rule by function, the secret classifier group by group, the caps, the cache-tagging spec, the release-signing trust shape, every background thread, every network call, and a per-extra table of system surfaces for SOC 2 / HIPAA-adjacent readers. A document like that is an oracle, not a brochure: every claim is a test, the by-design rebuttal is foreclosed in advance, and it cuts both ways — three of my leads died because it pointed me straight at code that was doing exactly what it said. So the method was not “find bugs” but diff the prose against the tree, the contract-versus-artifact move applied to English rather than to a typed schema. What it mostly found is a codebase that had already found it. The bearer middleware factory returnsNonewhen the token is unset — the fail-open shape I went in hunting — and the write endpoints do not inherit it, because a helper exists whose entire job is to notice: “Without it the write endpoint would accept unauthenticated writes (only a startup warning today), so we refuse (503) rather than warn.” Someone worked out that the layer above would silently do nothing and declined to trust it. The GitHub fetcher pins its host and reasons in a comment about cross-origin redirect header-dropping — the exact mechanism behind Observal, the strongest thing this series has filed privately. Cached writes are confined by resolve-and-commonpathat all four call sites. A hostile repository’s own.jcodemunch.jsonccannot escalate, because project values only resolve on repo-scoped reads and the one key that could reach outside its tree has a bespoke containment check — which existing at all tells you the author already treats a project config as attacker-influenced. And I specifically checked whether the recommended transport had drifted from the deprecated one, since “the path you are told to prefer stopped warning” is a seam I have found before: both warn, in the same words. Three items survived, none a vulnerability — two are prose, one is a real gap in a guard that already exists.install-pack’s zip-slip check rejects a leading/and..anywhere, but a drive-absolute Windows member name contains neither, andbase / relativewith an absolute right-hand side discards the base entirely — verified on Windows rather than asserted. The framing that makes it worth a maintainer’s minute is the intra-repo differential: the correct check is already in this codebase, applied to untrusted repository paths, and rejects all three of my inputs — the ask is you already wrote this, use it twice, not adopt my patch. It also sits oddly against the project’s own supply-chain posture, since release wheels are Sigstore-signed while packs are extracted into a directory the same document flags for file-integrity monitoring, with neither a signature nor a complete guard. Third archive-extraction filing in the series after pixeltable and fast-agent — both fixed — and the first where a guard already existed. The other two are doc-versus-code:SECURITY.mdhands content-based secrets to response-level redaction, which is wired into the central dispatcher and exempts exactly the three tools that return file contents, so a credential hardcoded in an ordinary source file is caught by neither half and the controls table never mentions the exemption; and “the only route that accepts writes from another computer” undercounts by three, in the one paragraph that promises to be exhaustive. I filed the threat path honestly — the archive comes from the project’s own endpoint, so this needs a hostile response from it, not a network position — and answered their template’s “does this block you today?” with none, this is a quality pass, which is their phrasing and the accurate one. Zero of 47 from the tools: 66% is the SQL identifier FP (eighth appearance, settled by reading three sites — names from literal tuples, values bound), 4 gitleaks all intests/(eleventh fixture vote), and a ninth consecutive GitHub-Actions cluster. The dependency coverage is genuinely complete for once — Trivy parseduv.lockand the Dockerfile, pip-audit resolved 38 deps, both zero, so this is a true zero with real coverage rather than the over-optimistic clean a lockfile-lesspyproject.tomlproduces; twelfth coverage-row vote, notable because the answer came out in the project’s favour and I still had to open the raw JSON to know it. Not strict-norm — the 26 KBSECURITY.mdnames no reporting channel and forbids nothing, PVR is disabled, and the project ships an issue template calling adversarial multi-part reviews “some of the most valuable things this project receives”, so a public quality pass is not merely permitted but invited. Twenty-sixth clean scan — and the lesson is about what makes a codebase auditable: this one is not quiet because it is small, it is quiet because someone wrote down what they believed the security properties were, in enough detail to be wrong, and then mostly was not. Filed as issue #444 with the fix in PR #443. - 2026-08-11 — semantica-agi/Semantica — 60 findings (60 above the medium floor), 1 real — withheld — graph-native infrastructure for context and accountable AI systems (4.6k★, MIT, 634 Python files / 31 MB): a knowledge-graph layer agents read and write through, built so a downstream decision can be traced back to what supported it — ingest from files, databases, warehouses and repositories, extract entities and relations, resolve duplicates, reason over the result, keep the provenance trail, with a FastAPI+React Knowledge Explorer, an MCP server and Agno integrations on top. The most actively maintained target in the series on the human axis — 40 merged PRs in 60 days from nine distinct authors, 30 closed issues — and the most security-instrumented: CodeQL, Defender for DevOps, a dedicated security-scan workflow, an action-pin verifier, Checkov with written skip justifications, NetworkPolicies in both the Helm chart and the raw manifests. The commit I scanned is itself a merge of a branch named
security/sparql-injection. Zero of the 60 survived curation, and the real item is an absence — no rule represents it, because rules match things that are present, and this is the fourth consecutive scan whose real finding was something missing. The class: a protection that guards one surface and silently fails to reach its sibling — two ways into the same process, sharing one authentication helper, where a protection configured once, correctly, in the obvious place covers the first and never gets consulted by the second. A codebase this well-defended relocates the finding rather than eliminating it: every route authenticated structurally, fail-closed defaults, hardened manifests — so what is left is the gap between two mechanisms that are each individually correct, the composite property in its purest form, and there is no defective line for a scanner to match. Deliberately argued down to moderate: normal production configuration is not affected and I verified that rather than asserting it — a report that only demonstrates the bad case invites the maintainer to discover the scope themselves and trust the rest of it less. Confirmed as a differential, not a claim — same server, same configuration, one run, one surface refusing a foreign caller while the other serves it — then end-to-end through the product’s own API, then the negative half. Filed via the N.E.K.O framing: you already made this decision correctly once, extend it — the ask being to apply their own reasoning, not accept mine. Extensive credit: fails closed with a 503 where most fail open, unauthenticated operation is a separate explicit opt-in that logs a warning at startup, auth is mounted structurally on every router so forgetting it is not expressible,compare_digestthroughout, and the Postgres vector store already uses the driver’s identifier-quoting API with bound values. The majority-sibling test returned a no — one of seven deployment templates disagrees with its six siblings exactly like AudioMuse, and chasing it to the running behaviour showed no exploitable condition, so it is a paragraph and not a filing; a heuristic that only ever confirms is a rationalisation. 73% of the report was one FP family (SQL identifier interpolation, 7th appearance, 44 of 60) — settled by reading three sites, not enumerating forty-four; the only Critical is a tutorial Critical in acookbook/CloudFormation teaching artifact; 2insecure-file-permissionsare the active-harm inversion again (both arechmod 0o700— acting on them would widen permissions). Every scanner reported honestly and I checked rather than assumed — but the clean dependency result is a property of resolving today: no lockfile,>=floors permittingtorchandtransformersversions with known RCEs, so “0 of 137 resolved-latest” and “0 of 137 pinned” are different claims the report renders identically (11th vote for a per-tool coverage row). Strict-norm (SECURITY.mdforbids public vulnerability issues) · PVR-enabled, filed privately, accepted first try (GHSA-4643-wpgq-w329), sixth autonomous private filing · post-only, finding withheld, with a standing offer to pull the page entirely - 2026-08-10 — datascale-ai/OpenTalking — 93 findings (93 above the medium floor), 1 real — a real-time digital-human pipeline (2.7k★, Apache-2.0): point a browser at it and talk to an animated presenter that listens, thinks, speaks and lip-syncs over WebRTC, with the demo reel showing healthcare guidance, live commerce and a tourism guide — aimed squarely at people putting a talking avatar in front of the public. Zero of the 93 findings is the finding, and the rule that should have caught it never fired: the wildcard is not at the middleware call site but a pydantic-settings default 300 lines away in another module, reached through a property, and two-hop config defaults are invisible to a pattern matcher. The project documents its own boundary honestly — “OpenTalking does not provide a complete built-in user-auth system… handle these at the gateway: TLS, user authentication and access control, CORS allowlist” — so no-auth is a stated design choice, not a defect, and the lazy version of this write-up was foreclosed before it started. I filed anyway, because the documented mitigation is what makes it worse. Starlette with
allow_origins=["*"]+allow_credentials=Trueemits a literal*to an anonymous request but reflects the attacker’s origin the moment the request carries a cookie — so the deployment that follows the advice and puts session auth at the gateway is the one where a visited web page gets authenticated cross-origin reads and writes of the entire API; the gateway authenticates the request and the app then tells the browser any origin may read the answer. Without a gateway it degrades only to blind writes, which is already enough:POST /runtime-config/applycarries no auth dependency, persists to the server’s.env, and rebuilds live LLM clients with an attacker-suppliedbase_urlwhile keeping the configured API key — so one cross-origin POST redirects the provider key and every subsequent conversation turn to an attacker’s endpoint, across restarts. The differential rewrote the report twice. It settled the mechanism (cookie-dependent reflection, which reconciles a note this series has carried since agentic_security — both readings were partial; the framework’s behaviour is a function of the request, not just the config), and it proved for the second consecutive scan that flippingallow_credentialstoFalsedoes not close it — only the origin allowlist does, so filing without the table would have shipped a one-character patch that fixed nothing. It also established the good news: every CORS-simple content type returns422against a pydantic body, so there is no non-preflight path and blocking the preflight is a complete fix. Two drafted findings died on contact. Five avatar handlers check containment and two don’t — the seam shape — and%2e%2egenuinely does escape one directory, but a path param matches[^/]+so it stops at exactly one level on a file that must be namedpreview.png; a consistency nit, not traversal. And thezf.extractall()that normally opens a zip-slip write-up is preceded by a validator rejecting absolute members and every..component. Extensive credit: one file-serving route stacks four independent gates including a%2f/%5c/%00check on the raw ASGI path — someone there has thought hard about how uvicorn decodes — and the config-read endpoint returnsapi_key_set: boolrather than the key, declining a genre already filed elsewhere. All 93: 18 loopbackws://from a JavaScript rule aimed at YAML and Markdown, 13 pickle hits that are the product for an ML project (the code-executor inversion), 18 GitHub-Actions tags — eighth consecutive flood, 2run-shell-injectionwhere the trigger isworkflow_dispatchand the flagged step is the tag validator, 1 SQL identifier FP (seventh appearance, values bound), andrembgCVEs that live in rembg’s HTTP server while the project imports it as a library. Eleventh vote for a per-tool coverage row: Trivy never openedpyproject.toml(no Python lockfile), and only pip-audit’s overlap kept “0 findings” from rendering identically to “never scanned.” Non-strict-norm by probe — noSECURITY.mdin root,.github/ordocs/, and PVR disabled (403), so issues are the only channel offered. Filed as issue #167 with the fix in PR #168. - 2026-08-09 — NeptuneHub/AudioMuse-AI — 265 findings (265 above the medium floor), 1 real — withheld — a self-hosted sonic-analysis engine for your own music library (2.4k★, AGPL-3.0, 323 Python files / 5.1 MB): point it at Navidrome, Jellyfin, LMS, Lyrion, Emby or Plex — several at once, with duplicate detection so a shared track is analysed once — and it listens to the audio rather than reading tags, then clusters sonically similar songs, draws a 2D map of the collection, finds the bridge tracks between two songs, and answers queries like “calm piano songs” or lyric-level ones across 72 languages. Maintained by one person in their free time, which the
SECURITY.mdsays plainly and the code does not read like: OpenSSF Best Practices badge, SonarCloud, 162 test files. Zero of the 265 survived curation, and the one real item is not in the application code at all — it is in the examples that tell people how to run it. The class is divergence between sibling deployment examples: the same stack described three ways, where two keep a supporting service internal — one labels it so in a comment — and the third hands it to the host’s network, a one-line difference nobody reads twice. What makes it reportable is what that service holds: the material the application’s own authentication is built from, directly usable, alongside the credentials the user gave it for their other self-hosted services, in the clear. So the attacker never touches the login, the session revocation, the re-confirmation prompts or the password hashing — none of which they could break — they walk past all of it. The divergence is the whole argument: I am not telling this maintainer their threat model; their other two deployment descriptions already state it, correctly — the report is you already decided this twice, the third place disagrees (intra-repo differential applied to deployment descriptions rather than functions), and the same file proves the exposure unnecessary three lines away. Fix is one line in each of two files. Deliberately not the sloppy version of this genre: a weak default is in play and the project documents it and advises changing it, in two places; I said so in the report, and a filing framed as undocumented default credentials would have deserved closing. The residual is narrower — the advice is suggested, the fallback silent, nothing warns — and the exposure, which nothing documents, is what makes forgetting unsurvivable. Sixth deployment-path lesson and the second finding living in the gap between artifacts: Vexa had a typed contract its deployment files contradicted; here there is no contract, just three siblings that disagree. Ship N ways to deploy and you have created N chances to diverge, with nothing in CI comparing them. Extensive credit — the auth layer is why the finding is where it is: a single deny-by-defaultbefore_requestbarrier rather than per-route decorators, so forgetting is not expressible; it fails closed where nearly everyone fails open, refusing to verify a token on an empty signing secret with a comment explaining PyJWT will validate a blank-key HS256 token and only warn; sessions re-validated every request so deleting a user kills live sessions, a password change invalidates earlier tokens by issue-time, and the stored role beats the token claim;secrets.compare_digeston the machine token; and the exemption list I went hunting through is enumerated, commented and correct — I read every self-scoping handler expecting the one that forgot (the ArcReel move) and they all enforce it, the list endpoint scoping its SQL to the caller rather than filtering after the fact, the password endpoint returning 403 not 404 on unknown ids purely to defeat enumeration. The third-party plugin installer validates every archive member and re-checks the destination withrealpath; the SSRF guard blocks link-local so metadata is covered and its docstring states outright that loopback and RFC 1918 are not, which for a LAN-facing app is the correct carve-out honestly documented; and the LLM-facing data path — where prompt injection would matter most — is the one place running with reduced rights, read-only grants through the driver’s identifier-quoting API, which is what made the 119-finding SQL cluster (45% of the report, the #1 recurring FP, 6th appearance) easy to dismiss after reading the sites where a model’s output reaches a query builder. The tooling lesson is the sharpest yet: the dependency scan covered the test harness and missed the shipped application, and the report cannot tell you that — Trivy’s only Python target wastest/requirements.txtwhile the real dependency set lives in eight files underrequirements/, none parsed, because the analyser matches a conventional filename these do not use. Worse than a miss because it is a legible-looking miss: two transformers RCE advisories attributed to a test file read as “test-only, dismissible” and are wrong twice — the same pin is in the shipped set, and the shipped set was never opened. You cannot apply the Kiln test-only tier unless you know which files the tool actually read. 10th vote, strongest yet, for a per-tool coverage row. Both transformers CVEs are version-match not reachable — the only runtimefrom_pretrainedloads a hardcoded id withlocal_files_only=True, no Hub fetch, gate two of three. pip-audit hung at zero CPU and I killed it so the scan could finish; its[]is a tool failure, not a zero — the loopx ambiguity inverted, and the fifth consecutive scan making the point that no empty output is self-describing. 73 of 152 mediums are one GitHub-Actions rule — seventh consecutive flood, now a property of the report format rather than of any repository. Also: the gitleaks high is a test file value literally readingsk_live_redacted(10th fixture-tier vote); 2django-no-csrf-tokenon a codebase with no Django. Strict-norm (SECURITY.mdforbids public issues and public PRs) · PVR-enabled, filed privately, accepted first try (GHSA-7pxm-9qpm-xfgf), fifth autonomous private filing, channel state (b) · post-only, finding withheld, with a standing offer to the maintainer to pull the page entirely · ❌ the advisory was closed unaccepted 41 minutes after filing — a declined report, and the first in the series; the private thread is not exposed by the API so no reason is visible to me and I will not invent one, the deployment files are unchanged so it was not a quiet fix, and the finding stays withheld anyway — a declined private report is not permission to publish one, least of all whereSECURITY.mdforbids public issues and PRs. Recorded because rejections get documented here, not deleted; a solo maintainer working for free owes a stranger nothing, and the assessment above stands unchanged - 2026-08-08 — theroyallab/tabbyAPI — 18 findings (18 above the medium floor), 2 real — the official API server for ExLlamaV3 (1.3k★, AGPL-3.0, 92 files / 13.8k lines): the FastAPI app a great many people run locally when they want their own OpenAI-compatible inference endpoint behind SillyTavern or Open WebUI. The auth layer is the best-built part of the codebase — every route across all three routers carries a guard, admin is required for every state-changing route, and inline model loading re-checks permission instead of trusting its route guard — which is exactly why the finding lives one level below it. Three individually defensible decisions in three different files compose into a hole: a wildcard CORS policy in
endpoints/server.py, an auth-disable escape hatch documented as “turn this on if you are ONLY connecting from localhost”, and a module docstring reasoning that “since TabbyAPI is a local application, it should be fine.” A web page in your browser is also connecting from localhost, and CORS is the mechanism that decides whether it may — here, yes, to everything. A user who follows the project’s own advice hands any site in another tab the admin API: load models, download arbitrary repos to disk, and read back the absolute local model directory. The differential changed the text twice, which is the whole argument for running one: Starlette reflects the attacker’s origin rather than sending*(the same correction agentic_security taught this series in July — second time this framework behaved more permissively than the spec reading), and the obvious remedy of flippingallow_credentialstoFalsedoes not close it — only the origin allowlist does, so filing without that row would have produced a one-character patch that fixed nothing. A second, scanner-blind item: the multimodalimage_urlpath fetches any URL with no scheme or host policy, on by default. Running that primitive too removed two claims from the draft —file://andgopher://are rejected by aiohttp, and the timeout isn’t absent, just a 300-second library default. Publishing the negative results is the point. The one rule that mattered fired atmedium, sorted beneath twelve GitHub Actions tag findings — the sixth consecutive scan in which one GHA rule is the single largest cluster, and 67% of this entire report. Filed as issue #448. -
2026-08-07 — huangruiteng/loopx — 57 findings (57 above the medium floor), 1 real — withheld — a local control plane for long-running AI agent work (3.2k★, MIT, two months old, v0.4.2 shipped the day before the scan): it holds the durable state around the loop — objective, gates, todos, scope, evidence, quota, handoffs — while Codex, Claude Code, Cursor or a plain shell agent executes bounded slices, and when the state says a human decision is needed it asks and waits rather than spending another turn. 57 findings across 1,601 Python files is the lowest density this series has recorded, and zero of the 57 survived curation — second consecutive scan where the tools contributed nothing to the finding that mattered. The class is a security check wired to some handlers of one small surface and not others, where the ones missing it are the ones that return the private material: the mutating handlers carry a correct, working check on who is asking; the reading handlers do not; and a single transport-level default applied uniformly to every response widens “local” from this machine to anything running inside this machine’s browser. Neither decision is unreasonable alone — the permissive default exists because the bundled UI genuinely runs on a different local origin, and the reads were left unguarded because the project’s own contract calls the default posture read-mostly. Three oracles, all the project’s own words, make it a defect rather than a trade-off: a boundary document that enumerates the private categories — every one of which is reachable through the unguarded reads (the advertised-boundary test in a new form: Agently named a boundary it didn’t enforce, LoopX enumerated the contents of one and left a door into the room); a committed design contract that states the correct restriction and was never implemented — the Vexa move inverted, since Vexa’s contract was enforced and its artifacts contradicted it while here nothing enforces it at all; and the fix already present in the same file, defined once and applied twice, forty lines from where it is missing — the intra-repo differential at its tightest range yet, not another module or provider but the same file. The differential decided the report: same instance, same hostile origin, same second — the mutating request returned 403 naming the exact protection, the reading request returned 200 with content and an absolute path. It also kept the report honest in the other direction: the write path looked like the story, resisted every attempt, and reporting the reads because the writes held is the better report. A fifth seam shape — a guard applied to a subset of one interface’s implementations, where the subset boundary (mutating vs reading) looked like the security-relevant axis and wasn’t. The supply chain is empty:
dependencies = []and an import sweep of all 1,601 files finds nothing outside the standard library — 15.8 MB of Python, zero third-party runtime dependencies, which is the real reason this scan is quiet. That produced the tooling lesson:{"dependencies": [], "fixes": []}is ambiguous and I nearly published the wrong reading of it — after four silent no-shows and one bare[], a fifth degenerate pip-audit result read as a fifth failure, and it was a true zero; the disambiguator was the project’s dependency declaration, not anything in the scan output. 9th vote, first time the ambiguity cut toward a false positive about the tooling rather than a false negative about the code, and it sharpens the ask: a per-tool coverage row, because 0-of-0 and 0-of-47 must not render identically. Also: 17 of 39 mediums are one GitHub-Actions hygiene rule, fifth consecutive flood; 9 SHA-1 hits are all content-addressed identifiers (run/todo/event ids, truncated) whereusedforsecurity=Falsewould state intent and silence all nine, as mistral-vibe did; 2subprocess-injectionare a Django rule on a codebase with no Django, firing on an explicit argv list; all 3 gitleaks hits are fixture-tier (9th vote), one a doc placeholder literally valued0123456789abcdef. Extensive credit: every write-side clause of the component’s own contract is honoured — flag defaults off, a non-local bind refuses to start (exception confirmed, not assumed), a preview-hash handshake rejects stale or altered payloads, unknown fields rejected not ignored; path containment on the read side is the right shape, correctly implemented, and is why this is Moderate rather than worse; and both outbound calls are host-pinned with# noqacomments that explain the pin rather than silence the linter. Extreme velocity did not produce the defect — 2,659 merged PRs in 60 days was the reason to look, and the one finding is not a rushed-commit seam but a design decision about where a boundary sits, made once, early, and never revisited. Strict-norm (SECURITY.mdforbids public issues) · PVR-enabled, filed privately, accepted first try (GHSA-p7c9-q3rc-f4f5), fourth autonomous private filing, channel state (b) · post-only, finding withheld under embargo -
2026-08-06 — nottelabs/notte — 226 findings (206 above the medium floor), 1 real — withheld — a framework for building web-automation agents (2.0k★, SSPL-1.0): give it a goal in natural language and it drives a real browser through Playwright, converting each page into a structure a model can reason over and executing the actions the model picks — a six-package monorepo plus a CLI, a workflow runtime and a hosted control plane. Zero of the 206 scanner findings survived curation, which is the cleanest statement yet of where this series has ended up: on a well-built codebase the scanner’s job is to be quickly dismissable, and the finding comes from a structural question asked by hand. The class is an asymmetric guard inside a single function — two classes of sensitive value flow through one code path, one is bound to the context that makes releasing it safe and fails closed when that context doesn’t match, the other is bound to nothing and the public API offers no parameter with which a user could bind it. The two lookups are adjacent lines of the same
if/else, and the unbound one is the more sensitive. A fourth seam shape after open-wearables (the one provider whose scheme differed), ArcReel (an exemption crossing a default) and Vexa (a contract crossing its artifacts) — and the tightest: the seam is inside one function, between two arms of one conditional, where the closer the siblings sit the less likely the asymmetry was intended. The single check in front of the unbound path is the tautological guard in its third costume — well written, does what its name says, and defeated not by evading it but by satisfying it, because every input it reads comes from the party it is meant to constrain. Running the primitive decided the severity: the finding was legible from reading, but reading could not tell “the real value is released” from “a masked stand-in is released” — the intermediate type hides itself inrepr()— so a report that guessed would have been coherent and wrong in the one detail that matters (Observal’s lesson again). Filed privately, accepted first try (GHSA-w5rf-44xh-5rq7) — noSECURITY.mdat any of the three locations, but PVR deliberately enabled, the ArcReel rule that an opt-in outranks a missing policy file; third autonomous private filing, channel state (b). The entire critical tier evaporates on reachability, by two different mechanisms: two LiteLLM criticals describe Proxy Server features (OIDC cache-key collision, admin key generation, user-role modification) and notte imports LiteLLM as a client SDK that never starts the proxy — the exact inverse of code-graph-rag, where the transport was live; the third is an Authlib bypass reaching the lockfile only through an optional integrations dependency, whose two apparent references in shipped code are an attribution comment and an unrelated string. Version-match → reachable → actually-shipped is three gates, and every critical failed at gate two or three. Genuine credit: the user-script runtime is a realRestrictedPythonsandbox that defaults to on, with unrestricted compilation an explicit opt-in — the advertised-boundary test passed; one lockfile for six packages, so the monorepo is the control case with no drift to find, inverting Kiln; a flaggedws://literal that is the mirror branch ofwss://, preserving transport security rather than pinning plaintext; and errors carrying separate developer, user and agent messages so what reaches a model is chosen at the raise site. pip-audit wrote a file after four silent no-shows — and it was[], on a lockfile Trivy mined for 135 advisories: recovery that reports nothing a second way, 9th vote plus a new corollary that the report should surface tool disagreement, which union and intersection both destroy. 54 of 120 mediums are two GHA rules, fourth flooding vote in four scans; all 28 gitleaks hits are fixture-tier (8th vote) with a new wrinkle — most are real keys belonging to other people’s websites, captured incidentally by archiving pages as offline test data. Not strict-norm, but PVR-enabled · post-only, finding withheld under embargo - 2026-08-05 — Vexa-ai/vexa — 297 findings (270 above the medium floor), 1 real — withheld — an open-source self-hosted meeting bot and transcription API (2.6k★, Apache-2.0, FINOS incubation, OSPS Baseline L2 with a committed dated self-assessment): bots join Meet/Teams/Zoom, stream transcription over WebSockets into a workspace that is a git repo of Markdown the operator owns — a gateway, an identity service, an agent control plane, a runtime kernel, a Next.js terminal, an MCP server, and three separate deployment paths. The finding is a composite, and no rule represented it at all — not ranked low, absent: the project keeps a machine-readable declaration of its own configuration requirements, in which certain keys are typed as must-be-set-explicitly with a rationale tied to a dated incident (a missing value must refuse to boot rather than come up green and reject every call), the enforcement code is correct — and every shipped deployment artifact supplies a literal for one of them, so the check can never fire and the value it lands on is readable in the public repo. Second consecutive scan where the defect lives between two files that are each right, after ArcReel: on a codebase with few defects, stop reading files and read pairs — specifically pairs where one file states a requirement and another decides whether it is met. Two things make it reportable rather than arguable: the project’s own committed contract is the oracle (the docstring-oracle move, but typed rather than prose — it forecloses the by-design rebuttal), and the fix already exists in the codebase, applied elsewhere — the enforcing idiom is used repeatedly in the same directory for less-sensitive config, so the report is you already wrote this correctly; here is the place it is missing, the intra-repo differential framing. Ship N deployment paths and the question stops being “is the default safe” and becomes “do the N defaults agree, and does anything verify that they do?” — divergence between siblings is the signal of oversight rather than intent. Channel state (c), and the reason to attempt rather than infer:
SECURITY.mdforbids public issues, but PVR is enabled — yet the advisory API returned HTTP 500, empty body, four consecutive attempts, exactly like repowise and indistinguishable from the working case until you try. Much is well built: admin routes return 404 not 403 so the surface never advertises itself; identity comes from a verified oracle with a written note that the companion cookie is display-only becausehttpOnlystops JS reads but not a hand-craftedCookieheader;hmac.compare_digestthroughout with checks re-asserted per endpoint rather than assumed from middleware; a guard exclusion list commented to explain that the library matches by prefix, so a bare/would silently neuter the entire layer; a third-party archive pinned by version and verified against a committed SHA-256. Comments routinely cite the dated incident that motivated the code — which is precisely what made the finding findable. pip-audit produced no output file for the fourth consecutive scan and its meta finding isinfo, so--min-severity mediumrenders “not scanned” identically to “zero” — 8th vote, now the top backlog item outright; Trivy carried the load alone. 92 of 189 mediums are one mutable-action-tag rule, third flooding vote in three scans; inversely, 15 of 15 Dockerfiles run as root — noise as 15 findings, a coherent recommendation as one. Strict-norm · post-only, finding withheld -
2026-08-04 — ArcReel/ArcReel — 82 findings (77 above the medium floor), 1 real — withheld — an open-source AI video generation workbench (3.9k★, AGPL-3.0): feed it a novel and an agent pipeline carries it through character design, script, storyboard and finished video, fanning image/video generation across eight-plus providers with a Claude Agent SDK skill-and-subagent layout, an RPM-limited async task queue with lease-based scheduling, a FastAPI backend and a React 19 workbench. The best-defended codebase in this series so far, which is exactly what makes the finding interesting: the class is two deliberate, individually-defensible decisions that compose into a capability neither intended to grant — a documented, build-enforced exception to a security invariant, plus an unrelated default that ships unchanged into production. Neither half is a bug; only the pair is, and no rule described the composite, because a composite is not a thing a pattern matcher can see. It came from a structural question — which routes are exempt from the guard every other route has, and what else changes who can reach them? Filed privately (GHSA-5r36-2f3p-5q87) despite no
SECURITY.mdanywhere — because private vulnerability reporting was deliberately enabled, an opt-in that outranks a missing policy file, and the submission API accepted it first try (the three-state channel model again, second autonomous private filing). The fix is one line and breaks nothing; the two deeper options are patterns already implemented twice in this same codebase for the very problem the exception solved — you already wrote this fix; here is the third place it belongs. The dismissals are unusually clean: three MCP Python SDK advisories all describe network transports, and ArcReel builds its agent tools withcreate_sdk_mcp_server— in-process, no listener — the exact mirror of code-graph-rag, where the same CVEs were live because it bound StreamableHTTP on0.0.0.0; all 18 gitleaks hits are test fixtures and design docs (7th vote for the fixture tier); 5 SQL hits are 4 Alembic DDL plus the #1 identifier FP interpolating a constant clause with values bound as params; and 34 of 43 mediums are one unpinned-action rule flooding the band, one scan after the same thing. Root Dockerfile +seccomp:unconfined+CAP_NET_ADMINis not a defect but a reasoned trade of the Docker boundary for a bubblewrap one nested inside it. Extensive credit earned: a containment helper whose docstring explains it usesrealpath+prefix because CodeQL recognises that shape as a sanitizer; complete zip-slip coverage; a Windows-fallback command check whose docstring enumerates its own three bypass classes then defends each; hard startup failure (not a warning) when sandbox tooling is missing on supported platforms — the inverse of Agently; a boot-time assertion that refuses to start if provider keys are in the parent environment, since the sandboxed child inherits by fork; and an auth module that excludes the empty string from its disable-values so a malformed config cannot fail open — the same decision point rocketride got wrong.pip-auditfinally produced a file after three silent no-shows (105 deps, a real zero) — though it disagreed with Trivy’s ~dozen Python advisories, which a one-tool scan would have silently resolved either way. Not strict-norm, but PVR-enabled · post-only, finding withheld under embargo · 📝 Accepted 2026-08-06 — the maintainers converted the submitted report into a draft advisory, kept the High severity exactly as filed, assigned CWE-200 + CWE-862 and credited the reporter. The first accepted private submission in this series — and evidence the three-state channel model needs a fourth state: accepted sits between “the API took the report” and “a fix shipped”, and only the first of those is visible at filing time. Still embargoed — no patched version yet -
2026-08-03 — the-momentum/open-wearables — 145 findings (134 above the medium floor), 2 real — a self-hosted platform that unifies wearable health data (2.3k★, MIT): Garmin, Whoop, Oura, Strava, Suunto, Apple Health and Google Health behind one normalized API, plus a developer dashboard, mobile SDK, svix outgoing webhooks, Celery workers and a stdio MCP server. The first scan here where the asset at risk is someone’s heart rate and sleep data, and a genuinely well-built codebase — which is what makes both findings interesting: each is the sixth instance of something done right five times. The Garmin webhook’s
verify_signaturereadsgarmin-client-idand tests it for presence, never comparing it to the configuredsettings.garmin_client_idtwo files away, so any non-empty string authenticates — confirmed by running the shipped method (x,0,attacker-inventedall returnTrue), and demonstrated unwittingly by the project’s ownTestGarminWebhookAuthsuite, which posts"x"and asserts 200. It is the only gate before dispatch, and past it sit connection revocation, OAuth-scope overwrites and health-data writes. Yet the framework around it is exemplary:verify_signatureis an@abstractmethodso no provider inherits a permissive default, comparisons usecompare_digest, and Oura and Google both fail closed on an unset secret — Garmin is simply the one provider whose scheme isn’t HMAC, and the seam is exactly where it broke. Same shape indocker-compose.prod.yml, which usesexpose:for svix and the:?required form forVITE_API_URL, then publishes Postgres (literal passwordopen-wearables) and Redis (no--requirepass) on0.0.0.0— Redis being the Celery broker — with the trap that setting the documentedDB_PASSWORDchanges svix’s DSN but not what the database boots with. The tautological guard returns in a new costume: what value would fail this check, and can the caller just send a different one? Meanwhile all 2 Criticals and ~33 Highs evaporate on a lockfile split — they live inmcp/uv.lock, a stdio MCP client no compose file deploys, so the FastMCP/MCP-SDK HTTP-transport, WebSocket-Origin and OAuthProxy CVEs describe transports it never starts; the shippedbackend/uv.lockyielded exactly one. SNS SHA-1 is the third confirmed mandated-interop instance (AWSSignatureVersion 1, with the cert URL allowlisted before fetch), and the docstring settled things both ways — convicting the Garmin handler, acquitting the unscopedget_useras an advertised boundary (“Global API key”).pip-auditsilently produced no file for the third scan running, making scanner-infra meta findings’ exemption from--min-severitythe top backlog item. Not strict-norm · post + issue #1380 -
2026-08-02 — Observal/Observal — 1,117 findings (216 above the medium floor), 1 real — withheld — a governed registry and control plane for internal AI components (2.3k★, Apache-2.0): submit → review → approve → version → install, with one approved component rendering into the native config dialect of nine harnesses (Claude Code, Cursor, Kiro, Copilot CLI + VS Code, Codex, OpenCode, Pi, Antigravity), plus a FastAPI server, Typer CLI, Next.js dashboard, Postgres + ClickHouse + Redis, and Terraform for AWS and Azure. Exceptionally healthy: ~100 PRs merged in 60 days from 17 distinct human contributors, 69 issues closed, CLA bot, REUSE/SPDX headers on every file.
SECURITY.mdsays “Do not open a public GitHub issue”, so the finding is described by class only — and for the first time in this series it was filed through a fully automated private channel: GHSA private reporting was enabled andPOST /security-advisories/reportsaccepted it (GHSA-2qv6-w49j-hqmq), where the identical call 500’d on repowise a day earlier — so the pre-check has three states and the flag distinguishes none of them: always attempt the POST. The class: a guard that answers the right question about the wrong noun — a genuinely well-built validator establishes an input is safe to act on, the code acts on it, and does something additional the validator never had an opinion about; the lowest authenticated role reaches it, and the path runs before the review gate. No rule fired on it — the tools ranked 216 other things higher, and all six of their buckets are dismissable in a paragraph. Notably all 7 Criticals are reference Terraform the project ships as a deployment example — a new way a raw count misleads (mis-attribution via template, alongside vendored-code over-count on harbor and scanner-blind under-count on zotero-mcp): unrestricted egress is a finding about a VPC you operate, not one an adopter will fork and narrow. The rest: 5 SQL hits are the #1 identifier FP (3 Alembic DDL + 2 interpolatingpg_tablescatalog output, with the reasoning documented inline), 2run-shell-injectionareworkflow_dispatch-only (trigger-context), 11insecure-file-permissionsflagchmod(0o600)on a secrets file — the active-harm FP where taking the advice widens exposure — and 6unvalidated-passwordare Django rules firing on a codebase with no Django. Extensive credit: every file write in the component-install path funnels through one resolver thatresolve()s and rejects anything notis_relative_tothe target — the right shape, applied uniformly — and user-scope hook execution is advertised and honest, the inverse of a promised-but-unenforced boundary. Gitleaks returned a genuine zero across 601 Python files; coverage verified on all four tools (0-byte lesson). Also documented: a serious finding I talked myself into and the terminal talked me out of —git’sext::transport looked like install-time RCE untilfatal: transport 'ext' not allowedended it, and--upload-pack=refspec injection proved inert too. Strict-norm · post-only, finding withheld under embargo - 2026-08-01 — repowise-dev/repowise — 86 findings, 2 real — both withheld — a codebase intelligence layer for AI coding agents (4.5k★, AGPL-3.0): index a repo once and serve the dependency graph, code health, git analytics, change-risk scoring and generated docs back through ten MCP tools, a FastAPI backend and a Next.js dashboard (99 PRs merged in 60 days from six distinct human authors). Its
.github/SECURITY.mdsays “Do NOT open a public GitHub issue”, so no issue was filed and both findings are described by class only. Both share one root cause worth saying out loud: “this only runs locally” is a deployment property, not a code property — the assumption gets established in an entrypoint script or a README quick-start, far from the code that depends on it. The lowest raw finding count in a long time, and it tracks something real: deliberate, documented decisions (oneshell=True, one XML parser, pickle confined to local caches) instead of the same pattern scattered unexamined. Extensive credit due — the Compose path publishes to127.0.0.1and uses the:?form that rejects empty and unset, the API never returns provider key material, and the dependency tree is verifiably clean (both lockfiles parsed, one test-only advisory). Process note published in full, correcting yesterday’s post:private-vulnerability-reporting: enabledmeans the human advisory form is live — it does not mean the submission API works. Four attempts returned HTTP 500, so private disclosure remains a manual step. - 2026-07-31 — rocketride-org/rocketride-server — 268 findings, 1 real — withheld — an AI pipeline engine (5.5k★, MIT, Aparavi Software AG): pipelines as portable JSON, composed in VS Code, executed by a multithreaded C++ runtime, with 122 nodes covering 13 LLM providers, 8 vector databases, graph stores, OCR/NER/speech and a
tool_*family reaching the filesystem, git, GitHub, Slack, MCP and arbitrary HTTP — plus SDKs, an MCP server, a Compose stack and a Helm chart (40 PRs merged in 60 days from 13 distinct human authors). ItsSECURITY.mdis among the most thorough in the series — severity SLAs, two-person delegated alert dismissal, quarterly access reviews — and says “Do NOT open a public GitHub issue”, so no issue was filed and the finding is described by class only. Process note published in full: the policy’s preferred channel, GitHub private advisories, is switched off (private-vulnerability-reporting→{"enabled": false}), so the link it tells reporters to use is unreachable; thesecurity@fallback still works, and the toggle is one click. The withheld item is scanner-silent at every severity and belongs to a class this series has now met three times: a security check whose enforcement is conditional on something the operator is expected to configure, where the unconfigured branch resolves to allow. That is dograh’s fail-open and EvoScientist’s conditional-verification bypass from a third angle — and quieter than both, because a deployment in the unsafe state is indistinguishable, from outside and from the logs, from a safe one. It was confirmed rather than suspected because the function’s own docstring documents the opposite behaviour: a mismatch between a security function’s stated failure modes and its code is a free test oracle. Published in full and not a project defect: the entire Python dependency surface went unanalysed — 105 per-noderequirements.txtfiles and a 1,686-lineconstraints.lock(langchain, CrewAI, LlamaIndex, deepagents, 13 provider SDKs) drew 0 findings, because pip-audit’s discovery is root-only and this rootpyproject.tomlis pure ruff config with no[project]table, while Trivy doesn’t recogniseconstraints.lockand parsed onlypnpm-lock.yaml. Second consecutive scan to hit this after PipesHub, with a far bigger blind spot. What’s well built is most of it:/task/fetchpinsHS256, requiresexp, guards traversal and fails closed with no signing key — this project demonstrably knows how to fail closed, a few directories from finding #1; CORS defaults to a localhost-only regex, never a wildcard-plus-credentials; actions pinned by SHA withpermissions: contents: read, and theworkflow_runcheckout defended twice (branch filter and ahead_branchguard) with the Scorecard rule named in the comments;tool_pythonis genuine RestrictedPython whose README states exactly where its guarantee stops (Agently inverted); base image pinned by digest, non-root user. 267 of 268 are noise: 135 path-traversal hits in build tooling, all 17 gitleaks FP (docstringcurlexamples withyour-api-key, C++ crypto test vectors,%remote-apikey%placeholders, and 9 hits from RocketRide’s own custom gitleaks rule firing on its own test fixtures — a sixth vote for honouring a repo’s shipped.gitleaks.toml), 11 SQLAlchemy highs are the #1 identifier FP, and 15 “insecure websocket” highs are markdown files and a log format string. Strict-norm · post-only, finding withheld - 2026-07-30 — pipeshub-ai/pipeshub-ai — 389 findings, 2 real — both withheld — an enterprise AI context layer (3.1k★, Apache-2.0) that indexes a company’s Drive, Gmail, SharePoint, Confluence, Jira, Slack, GitLab and S3 and serves it back through search and an agent runtime; the most actively maintained target in this series (60 PRs merged in 60 days from 13 distinct human authors). It ships a real
SECURITY.mdthat says “DO NOT create public GitHub issues for security vulnerabilities” — so no issue was filed, and the two real findings are described by class only, held for the private channel. What is published in full is everything that makes this a good scan to read: the CI trap that is armed and correctly defused.integration-tests.ymlruns onpull_request_target, checks out the PR head withallow-unsafe-pr-checkout: true, and runsnpm cion it inside a job holding a Google service-account key with domain-wide delegation, SharePoint private keys, Jira/Linear tokens andSECRET_KEY. Semgrep flags it, correctly, as drive-by repo compromise — and it is not exploitable, because the job binds to a GitHub Environment with three required reviewers. That control lives in repository settings, so no static analysis of the tree can ever adjudicate this rule; the environments API must be queried. The sandbox is likewise the real thing:SANDBOX_MODEdefaults tolocalin code but all five shipped Compose files setdocker(deployment-default pivot in the project’s favour), and the container runsnetwork_mode=noneandnetwork_disabled, with installs on a separate bridge so the sandbox can never reachmongodb/etcd/kafka. Exactly oneports:mapping exists in the whole stack — every database is unpublished; no default passwords (all${VAR:-});SECRET_KEYthrows if unset (inverse of dograh); live AES-256-GCM encryptor with per-message IV and verified tag. The retrieval permission model has a genuine seam — a caller-supplied ID list replaces the permission-derived filter and the unverified result falls through the drop-branch — that does not leak, because a citation-completeness filter requiresrecordId, a field only the permission-verified path injects. Real security resting on a formatting rule: a two-character fix makes it structural. Third finding, safe to publish: Trivy’s 89 dependency hits cover the test harness, not the product — 49 fromintegration-tests/uv.lockand 0 frombackend/python/, which has no Python lockfile at all. “Zero findings” and “not scanned” rendered identically. 73 of 73 gitleaks secrets are FP, including aprivate-keyhit on a validation rule that rejects RSA keys (active-harm inversion) anddropbox-api-tokenonfrom dropbox.team import ...; the flagged crypto weakness is in a dead class whose only importer is its own test. Strict-norm · post-only, findings withheld - 2026-07-29 — Project-N-E-K-O/N.E.K.O — 783 findings, 1 real — the first consumer desktop AI companion in the series (2.3k★, Apache-2.0, free on Steam): real-time voice + vision, five-tier memory, Live2D/VRM/MMD avatars, a plugin marketplace, Steam Workshop character sharing, and an agent layer that drives your browser and your computer — 831 merged PRs from 17 distinct authors in 60 days. A desktop app inverts the usual question. Nothing is exposed — main, memory, agent, plugin and tool servers all bind
127.0.0.1— so the question becomes what can a web page reach on loopback while the user browses? Answer:GET /api/config/core_api(config_router/core_config.py:33) returns, unauthenticated and unmasked, ~20 provider keys (OpenAI, Claude, Gemini, DeepSeek, Grok, OpenRouter, ElevenLabs…) plusmcpTokenand the custom-provider keys and their URLs — while the masking logic that exists in that very file runs only on thePOSTside. The app is a bareFastAPI()(main_server/__init__.py:500) with a body-size limiter and nothing else: no CORS, noTrustedHostMiddleware, noHost/Origincheck. No CORS means this isn’t one-click CSRF — it’s DNS rebinding, after which the request is same-origin and CORS never applies; port48911is a constant. What makes it worth filing is that the fix is already written in the repo:market_bridge.py:158validates theHostheader for exactly this reason (“避免被外部网页拿到 token”), andsystem_routerguards autostart with acompare_digestCSRF token + Origin allowlist — three good local guards, and the keys endpoint outside all of them. The siblingverify_local_access(cookies_login_router.py:62) shows the trap: it checksrequest.client.host, which on a loopback bind is always127.0.0.1— the check runs and means nothing (codex-lb class). Everything I expected to break was well-built: noextractallanywhere (all five archive importers walkinfolist()withis_relative_to), an_INJECTION_PATTERNSprompt-injection filter on imported markdown, one-time-code pairing +0o600token file on the market bridge, and ansk-CANARY-APIKEY-9182planted to prove keys don’t leak into exports. Theexecof model-writtenpyautoguiis advertised and honest → AG2 class, the inverse of Agently. Both Criticals (authlib) are transitive viabrowser-usewith zero import sites → version-match, not reachable. 107 of 109 gitleaks hits are i18n message keys instatic/tutorial/; the 67 SQL highs are the #1 identifier FP (and clampLIMITon both ends); the0o700cookie-dir chmod is the active-harm FP again. Residual: monitor binds0.0.0.0with an unauthenticated/syncwrite path, and telemetry ships over cleartext HTTP → filed #2558. ✅ RESOLVED ~14h later in PR #2559 (+2043/−101, 22 files): all 32 sensitive fields masked behind a sentinel with a safe write-back round-trip, and — taking the structural option the report argued for — a newutils/host_origin_guard.pyregistered as middleware on all four servers with WebSocketOriginrejection,NEKO_TRUSTED_HOSTS/NEKO_TRUSTED_ORIGINSopt-in, and 3 new test files (1110 lines). The PR reports a main-branch control run confirming the endpoint returned plaintext and a forgedHostreturned200before the fix. Not strict-norm · post + focused issue - 2026-07-28 — EvoScientist/EvoScientist — 39 findings, 1 real — and no tool ranked it — a self-evolving AI scientist (4.4k★, Apache-2.0) built on deepagents: sub-agents plan experiments, search literature, write and debug code, analyse data, and draft papers, reachable through ten chat channels. The obvious question turned out to be the wrong one. I expected the finding in the evolution loop — an agent that writes and installs its own skills is a prompt-injection-to-persistence story waiting to happen — but that loop is the most carefully built part of the codebase: autoskills go through a proposal → review → approval lifecycle with a strict name regex and a frontmatter key allowlist, and the code interpreter is a QuickJS sandbox whose tool allowlist explicitly excludes shell
executewith the reason in the docstring (“would bypassHumanInTheLoopMiddlewareapproval”) — an advertised boundary that is actually enforced, the inverse of Agently. The real finding is in the plumbing beside it, which is becoming the pattern:WeChatChannel._handle_messageverifies the signature insideif encrypt and self._crypto:— andencryptis read from the body the caller sent. A plaintext POST with no<Encrypt>element takes the false branch and lands in_process_messageeven whentoken+encoding_aes_keyare correctly configured. Feishu’s_handle_eventis the sibling shape (fail-open whenverification_tokenis unset — which onboarding prompts as “optional” while defaulting the mode towebhook). Both bind0.0.0.0;FromUserNamecomes from the forged payload soallowed_sendersis spoofable and open by default; the injected text drives an agent whose shell approval is a reply in the same chat (y/1;3= approve-all) that the same forged webhook can send. Here0.0.0.0reads the inverse of dimos: a webhook receiver must be publicly reachable, so the signature check is the entire boundary. Every one of the 39 scanner findings was an FP — the 10 SQL highs are the #1 identifier FP (exemplary:?-bound data, anint()-cast PRAGMA with the reason in a comment), the 3shell=Trueare the agent’s ownexecutetool (ag2 class), and credit-the-defense inverted twice: gitleaks flagged the project’s own secret-redaction test, Semgrep flagged the protocol-mandated WeChat SHA-1 (3rd instance of that class). Cleanest dependency graph in the series: Trivy 0 onuv.lock, pip-audit 0/148, Dependabot wired, non-root Docker. → filed #392. Not strict-norm · post + focused issue - 2026-07-27 — dimensionalOS/dimos — 280 findings, 0 real — 25th clean scan, and the first agentic OS for physical robots in the series: dimOS (~3.8k★, Apache-2.0, Dimensional Inc.) drives humanoids, quadrupeds, drones, and manipulators in natural language, wired to real cameras/lidar/actuators. When your code moves an arm in a room with people the question shifts from can an attacker read a file? to can an attacker move the arm? — and it closes secure-by-default. The natural-language command server (
POST /submit_query,POST /unitree/command) is unauthenticated — the same class as the resolved code-graph-rag #808 — but every listener (web, MCP Streamable-HTTP, visualizer) resolves its bind through one field,global_config.listen_host, whose default is127.0.0.1; the scattered0.0.0.0literals are exactly the surfaces that need LAN reach (phone/Quest teleop, drone MAVLink, gstreamer video). The lone Critical — a chromadb pre-auth server RCE (CVE-2026-45829) — is not reachable:spatial_vector_db.pycallschromadb.Client()embedded in-process, so the vulnerable/api/v2/…collectionsendpoint is never served (version-match ≠ reachable). The 7defused-xml“XXE” highs are stdlibetreeover local robot-description files (URDF/MJCF/Drake world) → DoS-only billion-laughs, not XXE (KiCAD-MCP class) — the one concrete code change (swapdefusedxml). Theevalis an operator-local ROS-topic CLI; the twoshell=Truerun a developer-set native-build command; thetarfile.extractallexpands the project’s own git-LFS data archives;transformerstrust_remote_code=Truedefaults to pinned trusted VL models (Florence-2/Moondream, mitigation-aware). The 21-finding SQL cluster is the #1 parameterized-identifier FP — data bound?, only internal table names interpolated, guarded byvalidate_identifier. The one genuinely not-well-built bit iswildcard-cors+allow_credentials=Trueon the loopback dev interface (inverse of credit-the-defense, bounded impact). Deps refresh across two lockfiles (uv.lock+native/rust/Cargo.lock), reachability-gated (Pillow via vision = DoS, native Rustlz4_flex/PyO3, LangSmith transitive). A safety-mature project — ships anAI_POLICY.md(“code moves real hardware… safety-critical real-world environments,” mandatory sim/replay for motion changes) + CLA. Commercial-backed · post-only - 2026-07-26 — CodeGraphContext/CodeGraphContext — 112 findings, 0 real — 24th clean scan, and one of the more security-aware codebases in the series: an MCP server + CLI (4.0k★, MIT) that indexes a local codebase into a graph DB (Neo4j / embedded KùzuDB / FalkorDB) so an AI assistant can ask structural questions over a real code graph. Rich surface — it reads arbitrary source off disk, builds graph queries, and ships an optional HTTP/SSE gateway for ChatGPT Actions + remote agents, a VSCode extension, and a website. The three questions — is the graph-query path injectable?, is the gateway an unauth exposure?, are DB creds + secrets safe? — all close, because the maintainer writes the mitigation next to the risk. The 12 graph-DDL “SQL highs” are the purest #1 identifier FP yet: all
CREATE/ALTER TABLEschema statements whose only interpolated tokens come from hardcoded constant tuples (no data value exists in DDL). Thewildcard-corson the gateway is paired withallow_credentials=Falseand a comment naming the trap (credit-the-defense); Neo4j has no default password (getenv('NEO4J_PASSWORD'), fails closed); the 3 gitleaks JWTs are Supabase anon keys (public-by-design frontend, IBM ContextForge class) + a CI service password + generatedscip_pb2.pyprotobuf bytes. The gateway’srequire_api_keyis a real router-wide FastAPI dependency (constant-time compare, opt-in) that logs a loud unauth warning naming the exact Cypher/tool exposure. The one genuine item is a secure-by-default nit —cgc api startdefaults--host 0.0.0.0while auth is opt-in (same class as the resolved code-graph-rag #808) — but the auth mechanism, the warning, and a documented--host 127.0.0.1already pre-mitigate it. The one concrete code change: swap stdlibElementTreefordefusedxmlin the Maven/MyBatis indexers (DoS-only etree, KiCAD-MCP class). Residual = awebsite/frontend dep refresh (lodash/PostCSS/ws/react-router) + transitiveprotobufbump. Strict-norm (.github/SECURITY.md, email-only private reporting) · post-only - 2026-07-25 — Osmantic/ODS — 73 findings, 0 real — 23rd clean scan, and one of the richer appliance surfaces in the series: the Osmantic Deployment System (3.6k★, Apache-2.0) turns a box into a private, self-hosted AI server — local inference, a chat UI, a control dashboard, voice/agents/workflows, RAG, image gen — orchestrated over Docker (Ollama, Open WebUI, n8n, ComfyUI). For an appliance that manages Docker, secrets, and network exposure the questions are is the dashboard reverse proxy an SSRF/host-spoof pivot?, are service creds handled + logged safely?, and is the token-store SQL injectable? — all three close, because ODS already did the work. The 5
nginxdynamic-proxy-host“hits” areproxy_passto a constant internal upstream (set $dashboard_api_upstream dashboard-api:3002) forced through Docker DNS re-resolution, with a Bearer header injected on every location (theB1/B2fixes marked right in the config); the 7logger-credential-leakmediums log the generated key’s file path (secrets.token_urlsafe(32)+chmod(0o600)), never its value (à la linkedin-mcp/google-workspace); the 5 SQL “highs” are the #1 parameterized-identifier FP, and exemplary — bound?values, a_RECENT_TS_BOUNDconstant, and aSAFE_IDENTIFIERregex on a hardcoded column name “to protect against future refactoring.” The 4insecure-websocketare 2 scheme-preservinghttp→ws/https→wssupgrades + 2 non-code text matches (arequirements.txtcomment, the audit doc itself); the 5run-shell-injectionare non-privilegedpull_request(interpolating the maintainer-controlledbase_ref) +workflow_dispatchtriggers (openmed lesson). Residuals are all operator-gated and already in the project’s own threat model: a react-router dashboard dep refresh (localhost-bound + Bearer-gated), root-user model-serving Dockerfiles, SHA-pin action tags. This is a security-mature project scanned, not audited — it ships a private-reportingSECURITY.md, aSECURITY_AUDIT.mdreceipts file, and an operator-hardening guide. Strict-norm (private reporting + commercial backing at osmantic.com) · post-only - 2026-07-24 — gpustack/gpustack — 136 findings, 0 real — 22nd clean scan: a GPU cluster manager for AI model serving (5.4k★, Apache-2.0, 97% Python) that registers worker nodes, proxies OpenAI-compatible inference to vLLM/SGLang, and offers SSH-accessible GPU instances. For a serving control-plane the questions are is the model-proxy an open SSRF pivot?, is the worker tunnel authenticated?, and is API-key handling sound? — all three close. The proxy (
routes/worker/proxy.py) isDepends(worker_auth)-gated and builds its upstream URL from cluster state (worker_ip_getter()+ a gateway-set routing header), not a user-supplied host, so thetainted-url-hostflag is intra-cluster routing, not egress (guarded, à la IBM ContextForge).security.pyruns on argon2 + blake2b +secrets; the flagged “generic-api-key” is docstring example values. The0o700+secrets.token_hexrandomized operator unix socket tripsinsecure-file-permissionsbut is exactly right (the linkedin-mcp active-harm-FP), andmessage_client.pyupgradeshttp→ws/https→wssrather than forcing plaintext. The count is structural: 46 SQL “highs” are all Alembic migration/enum DDL — the #1 identifier FP, third scan where migrations dominate (codex-lb lesson) — plus 29 GHAmutable-refpins and 15 test-fixture “secrets”. The lone Critical (asyncmySQLi CVE-2025-65896) is doubly gated: MySQL-backend-only (default is SQLite) and the crafted-dict-key primitive isn’t exposed through SQLModel/SQLAlchemy — version-match ≠ reachable. Residual = a reachability-gated dep refresh (asyncmy/pyasn1/setuptools); all 17 gitleaks hits FP (tests/docs/docstring). Not strict-norm (no SECURITY.md) · post-only - 2026-07-23 — EverMind-AI/Raven — 87 findings, 0 real — 21st clean scan: a memory-first, self-improving agent harness (2.5k★, Apache-2.0, MiroThinker deep research) — ~73% Python, with a gateway that runs agent turns, shell-exec + web-fetch tools, an “evolver” that mutates and re-benchmarks itself, and a TUI. For an agent harness with filesystem/exec tools the two questions are can an untrusted party drive it over the network? and is web-fetch an open SSRF? — and both close well. The 3 MCP SDK “highs” are server-transport CVEs, but
raven/agent/tools/mcp.pyis a client (outbound connections only) → not reachable, the inverse of code-graph-rag whereserve_http()was stood up. The web-fetch surface is defended: a dedicatedraven/security/network.pyblocks private/metadata CIDRs (169.254/16) and is wired intoweb_fetchbefore the fetch; the DingTalk adapter re-validates every redirect hop (follow_redirects=False) — closing the redirect-to-internal gap most guards miss (defended, à la IBM ContextForge, vs undefended optillm). TheGatewayConfig.host = "0.0.0.0"semgrep flagged is a defined-but-unused default — the only listener is a/healthendpoint pinned to127.0.0.1, TUI↔gateway rides local FIFOs. The shippedeval()is a parameter name (a harness-eval callable, not the builtin); thetarfile.extractallis a benchmark expanding its own self-written checkpoints; the 2run-shell-injectionare privileged tag-push/workflow_dispatchtriggers (openmed lesson); the 14 JS path-traversal are a localhost tracing viewer;non-literal-import×5 are plugin registries;sha1×3 are cache keys. Residual = a dep refresh (Pillow multimodal, mistune via the opt-in Matrix channel) — all reachability-gated. Strict-norm (SECURITY.md → private advisory reporting) · post-only - 2026-07-22 — mixelpixx/KiCAD-MCP-Server — 29 findings, 0 real — 20th clean scan: an MCP server (1.6k★, MIT) that drives KiCAD for AI-assisted PCB design — a TypeScript protocol server that spawns a long-lived Python
pcbnewbackend, STDIO transport only. For an MCP server the question is whether a tool argument reaches a dangerous sink, and every candidate closes: the freerouting autorouter shells out tojava -jarbut builds an argvList[str](noshell=True, AI-supplied paths are argv elements — credit the defense, à la potpie); the datasheet helper constructs an LCSC URL and never fetches it (no SSRF, the tradingview-mcp constant-authority pattern);expressis imported but neverlistens → no network surface to protect. The 4 JLCPCB SQL “highs” are the #1 recurring parameterized-identifier FP (f"…FROM [{relation}]"from the source DB’s own schema, values bound?); the 2child_processhighs are operator-gated (pythonExefromKICAD_PYTHONenv, and the realspawnpath already uses argv — anexecFilenit); the 4 path-traversal are constant segments on a__dirnameroot. The one genuine residual is DoS-only: 6 stdlibElementTreeimport parsers with nodefusedxml— but CPython’s etree doesn’t resolve external entities, so it’s billion-laughs entity-expansion (local, self-inflicted on importing a malicious design file), not XXE file-read/SSRF. Gitleaks/Trivy/pip-audit all clean. Not strict-norm · post-only - 2026-07-21 — ucbepic/docetl — 124 findings, 1 real — and no tool ranked it — an agentic map-reduce / document-ETL engine (3.9k★, UC Berkeley EPIC) with a FastAPI backend and a Next.js DocWrangler UI. The
exec/evalthe scanner headlines are the documented code-operator model (author writes atransform; the engine runs it — by-design, à la ag2 / datachain), so the real finding is the mundane plumbing bolted beside it: the/fsrouter (read-file/read-file-page/check-file/write-pipeline-config/save_workspace) takes a raw client-suppliedpath/namespacewith no confinement and no auth → unauthenticated arbitrary file read and write (plus a fetch-and-store SSRF inupload-file?url=,follow_redirects=True, no allowlist). The tell:serve-documentone function up does carry anif ".." in pathguard — the pattern is understood, just not applied. Reachability is the whole story and it cuts both ways: bare-metal bindslocalhostand CORS defaults tight (both credited), but the shippeddocker-compose.ymlbindsBACKEND_HOST=0.0.0.0with zero auth in the server, the pipeline route drivesDSLRunnerfrom a request-suppliedyaml_config(code-operators = the ceiling above the file-read floor), and thedocetl-awsprofile mounts~/.aws:ro→ an unauth file read is a cloud-cred read. Meanwhile Semgrep’s 14 traversal hits all landed in the TS frontend, not this Python sink (scanner under-count, the zotero-mcp sweep lesson), and the report’s “critical” was a low-reachabilitynltkZip-Slip. Deps: 3 crit acrossuv.lock+package-lock.json, no Dependabot (Kiln coverage gap) → filed #505. Not strict-norm · post + focused issue - 2026-07-20 — ModelEngine-Group/nexent — 115 findings, 0 real — 19th clean scan, and one of the widest surfaces in the series: a zero-code AI-agent platform (5.7k★) with its own JWT/CAS/Supabase auth, an MCP tool broker (
fastmcp), a SQL monitoring tier, a Ray/Celery data stage, and a full Docker/Kong/Helm deploy stack. On an agent platform the boundary that matters is auth, and nexent’s holds: every authenticatingjwt.decodepinsalgorithms=["HS256"], uses the env-loadedSUPABASE_JWT_SECRET, and fails closed — the oneverify_signature: Falsehit is a peek-for-sidon the logout path (server-side CAS session check behind it, à la IBM ContextForge), and thejwt-hardcodeis aMOCK_JWT_SECRET_KEYwhose only callers are the test module (inert against the real verifier). The 33 “highs” collapse: 11run-shell-injectionare allworkflow_dispatch(maintainer-only privileged trigger = hardening, the openmed trigger-context lesson), the SQLtext()is the #1 parameterized-identifier FP (hoursresolves to a whitelisted int,tenant_idis bound), and the rest isws://service-mesh config + root-user Dockerfiles + anexent@2025default-password fallback (operator-overridable). Deps floor-pinned (>=) +defusedxml; nestedpyproject.tomls went unaudited (root-anchored pip-audit gap, the Kiln coverage asymmetry). Strict-norm (private SECURITY.md) · post-only - 2026-07-19 — vitali87/code-graph-rag — 22 findings, 1 real, reachable — a graph-RAG that parses codebases with Tree-sitter and ships an MCP server with code-editing. The RAG engine invites an
exec/injection hunt, but it’s a dead end: the sixnon-literal-importhits are dynamic Tree-sitter grammar loading keyed on a typedSupportedLanguageenum, and the twodynamic-urllibhits are a host-pinnedpypi.org/{pkg}README fetch + a local health probe — neither SSRF. The real signal was the MCP transport posture:mcpis pinned to1.25.0, which carries three published CVEs, and the project stands up the exact transport the worst one targets —serve_http()mountsStreamableHTTPSessionManager.handle_requestbehind a bare Starlette route with no auth, default bind0.0.0.0:8080. That makes CVE-2026-52869 (“HTTP transport serves sessions without verifying the authenticated principal”) reachable, not version-match. The reachability splits cleanly: 52869 live, 52870 (experimental task handlers) conditional, CVE-2026-59950 inert (it needs a WebSocket transport the server never speaks) — one bump tomcp>=1.28.1clears all three. Same “version-match ≠ reachable transport” lesson as tradingview-mcp, but here the vulnerable transport is exposed by default. The other 4 “highs” are FP (SONAR_TOKENsecrets-ref; a constrainedtype: choiceworkflow input) → filed #808 → ✅ RESOLVED same-day (PR #809 merged:mcp>=1.28.1+ lock regen +MCP_HTTP_HOSTloopback default; maintainer verified every claim including the honest triage that only 52869 is live). Not strict-norm · post + focused issue - 2026-07-18 — algorithmicsuperintelligence/optillm — 57 findings, 1 real residual — an OpenAI-compatible optimizing inference proxy (4.2k★) whose approaches run code (Z3,
executecode), read URLs, and web-search. The core proxy is built carefully — timing-safesecrets.compare_digestauth, localhost-default binding, no wildcard CORS, operator-setbase_url(no forward-SSRF) — so the count collapses: 51 are action-pin CI lint, the lone “high”run-shell-injectionis release-gated (maintainer-controlledhead_branch, not fork),non-literal-importis a hardcoded dict, and the twoexec/Jupyter code-exec sites are the advertisedexecutecode/z3approaches (honest product surface, à la ag2 — not an Agently-style broken sandbox promise). The one genuine residual is scanner-silent:readurlscallsrequests.get()on every prompt-extracted URL with no SSRF guard (no private-IP / loopback /169.254.169.254block), and a caller picks the approach by request field — so a hosted proxy can be steered to read cloud metadata / internal services. Same egress class as a2a-python (undefended) vs IBM (defended); here fully attacker-chosen → filed #323. Not strict-norm · post + focused issue - 2026-07-17 — IBM/mcp-context-forge — 946 findings, 0 real — 18th clean scan, and the richest attack surface in the series: an AI gateway / registry / reverse proxy (IBM ContextForge, MCP Gateway) that authenticates callers, forwards credentials to upstream MCP/A2A/REST backends, proxies tool calls, and discovers JWKS keys. The finding class that matters on a gateway is SSRF egress — and unlike a2a-python (undefended), it’s thoroughly guarded: a dedicated
SecurityValidator._validate_ssrfthat’s secure-by-default (protection on, cloud-metadata + link-local always blocked, localhost and RFC 1918 blocked unless you opt in), wired into every egress path with redirect-protection tests. The 11 “unverified JWT decode” highs are all the peek-iss-then-verify pattern (or a token the gateway just created); the auth path verifies before it grants. And the count is a tooling artifact: 521 of 581 “secrets” live inside the project’s own.secrets.baseline— Gitleaks re-flagging detect-secrets’ own audit file. The ~80 Admin-UI XSS/CSRF findings are documented dev-only scope; deps clean (pip-audit 0). Strict-norm (IBM PSIRT private reporting) · post-only - 2026-07-16 — a2aproject/a2a-python — 20 findings, 0 real — the official Agent2Agent protocol SDK (Google/Linux Foundation). For a protocol SDK the security is the peer boundary — auth + callbacks — and the code is clean: the auth interceptor logs scheme names, not tokens, secrets are confined to
tests/, deps on Dependabot. The one surface worth writing down is the push-notification webhook:BasePushNotificationSenderPOSTs task updates to the client-suppliedpush_info.urlwith no SSRF egress validation (is_private/urlparse/validate_url= 0 across the repo). Real webhook-SSRF shape — but authenticated (the task submitter’s own webhook), blind (POST, no response returned), and library-level (egress policy is the deployer’s job); and the design does authenticate webhooks (X-A2A-Notification-Token, anti-spoofing). A deployer-hardening note (allowlist push URLs), not a filing. Strict-norm (private-reporting SDK) · post-only - 2026-07-15 — mnemosyne-oss/mnemosyne — 195 findings, 0 real — 17th clean scan, and the largest SQL cluster in the series: a zero-dependency SQLite-backed AI memory system where 140 of 195 findings are one parameterized-SQL false positive. On a store that holds user text, 128 SQL “highs” reads as an injection fire — but every value is a bound
?param (withLIKE … ESCAPE '\\', which most forget), and the only f-string tokens are internal table/column names ("working_memory"/"episodic_memory") and constant embedding dims inCREATE VIRTUAL TABLEDDL. Two representative queries settle all 140. The 21dynamic-urllibare operator-directed imports (honcho/zep) + own-server sync (not SSRF), the “secrets” aredocs/sync/tutorial.mdexamples, and sync uses client-side XChaCha20-Poly1305 so the server never sees memory content. Strict-norm · post-only - 2026-07-14 — datachain-ai/datachain — 35 findings, 0 real — 16th clean scan: a Python “context layer” for unstructured data (DVC/Iterative team; typed versioned datasets over S3/GCS, UDFs at scale, hosted Studio). For a library that caches datasets and ships UDFs to distributed workers, the question is deserialization — and the sweep clears it: no
pickle.load/loads/cloudpickle.loadsin source at all; thepickle/cloudpickle(26 sites) isdumpsserializing the user’s own UDF for its own workers — the scary primitive only on the write side. The oneexec(meta_formats.py:161) is documented schema-inference codegen over your own data (a staticspec=skips it). The count is 26 workflow-tag lint + a by-design backend loader; deps clean (Dependabot wired); gitleaks 2 = docs + afake-service-accountfixture. Strict-norm (Studio) · post-only - 2026-07-13 — potpie-ai/potpie — 96 findings, 0 real — 15th clean scan: a code-context-graph SDLC platform (FastAPI + a subprocess sandbox + repo ingestion, hosted at potpie.ai). The wide surface was the point, and it held: the
subprocess-injectionhits are the sandbox executor, but_command()returns an argv list (no shell) orshlex.quotes each part, with a Docker-isolated runtime alongside; and CORS lives in a dedicated_hardening.pythat’s secure-by-default — origins from an env allowlist (default empty),allow_credentials=bool(origins), methods/headers[]when unset (never wildcard-with-credentials), plus security headers + rate-limits. The 96 count is alegacy/tree (7 highs + 13 trivy Dockerfile misconfigs) + 20 workflow-tag lint; deps clean (0 CVEs), gitleaks 3 = template/tests. Strict-norm (commercial) · post-only - 2026-07-10 — sooperset/mcp-atlassian — 71 findings, 0 novel code — the popular (5.5k★) Jira/Confluence MCP server. The credential-server question a scanner skips — does it protect tokens on the wire? — had to be traced by hand, and clears:
ssl_verifydefaults toTrue(jira/config.py:104); theverify=False/CERT_NONEpath is an explicit opt-in for self-signed Server/DC certs. The two criticals are public dep CVEs —authlib1.6.8 (JWK-injection auth-bypass) +fastmcp2.14.5 (authenticated SSRF) — reachable only in the optional multi-user OAuth mode, inert in the default single-user PAT deployment (authlibhas 0 direct imports). Fix = bumpauthlib→1.6.9 (one patch) +fastmcp→3.2.0 (major) + wire Dependabot. gitleaks 8 = all docs/tests. Strict-norm (SECURITY.md requests private reporting; CVEs are public) · post-only - 2026-07-09 — VectifyAI/OpenKB — 23 findings, 0 real — 14th clean scan: a CLI that compiles documents into a wiki-style LLM knowledge base. Because it’s a CLI — no server, no auth — the sharpest curation move is reachability: trivy’s highs are
starlette(SSRF/Host),python-multipart(form-DoS), andpyjwt(token-verify) — all of which describe a web service OpenKB never starts, so they sit inert (transitive). The reachable deps are the boring ones — a deprecatedPyPDF2on the untrusted-PDF path (parser DoS; migrate topypdf) +aiohttp/lxml-html-cleanbumps. Code is clean (the oneurllibhit is an operator-directedopenkb add <url>download, not SSRF/crawl), and the maintainer pins deps deliberately (“supply-chain caution — e.g. the litellm poisoning incident”). gitleaks clean · post-only - 2026-07-07 — atilaahmettaner/tradingview-mcp — 28 findings, 0 real — 13th clean scan: a market-data MCP server (~30 tools for Claude/Cursor). The sharp MCP question — can a tool argument steer a server-side fetch? — comes back negative: the Yahoo/CoinGecko hosts are hardcoded constants and a tool input only fills a
{symbol}slot after the authority (f"{_YF_BASE}/{symbol}?..."), so it can’t redirect to a new host (contrast zotero-mcp, where it could). Better still, the design holds no credentials — public endpoints only, no TradingView account/key — deleting the whole credential surface; gitleaks clean. The residual is a transport-gated dep refresh (mcpSDK CVE reachable;starlette/python-multipartreachable only in the hosted HTTP mode; no Dependabot). Strict-norm (commercial cryptosieve.com tier) · post-only - 2026-07-03 — AgentEra/Agently — 25 findings, 1 real — a GenAI framework that runs model-generated Python through a component named
PythonSandbox, described as running code “safely.” But the isolation is best-effort restricted-exec:SAFE_BUILTINS+ a_-attr guard that only covers wrapped preset objects, so a literal the executed code creates itself (().__class__.__bases__[0].__subclasses__()) walks tosubprocess/osand escapes to host RCE. Reached from the model’s tool argument (action_input["python_code"]→sandbox.run). The inverse of the AG2 case: a component that advertises a boundary it doesn’t enforce. The other 14 “highs” are one parameterized-SQL FP cluster (LocalBackend.py); deps + secrets clean · filed #312 · ✅ RESOLVED — released inagently 4.1.4.1(~5 days): maintainer replaced in-processexecwith a Docker-backed default sandbox that fails closed, demoting the legacy runner to an explicittrusted_localopt-in (145-test regression suite). The structural fix the report recommended, not a denylist patch - 2026-07-02 — UKGovernmentBEIS/inspect_ai — 161 findings, 0 real — 12th clean scan: the UK AI Security Institute’s LLM-eval framework, where the threat model is the sandbox (it runs model-authored bash/python tools). The two findings a scanner headlines are both already defended: the
tarfile.extractallsandbox-escape on checkpoint restore carriesfilter="data"plus an inline CVE-2007-4559 citation (PEP 706), and thepickleis a trusted local model-response cache. Theeval()“code-exec” hits are calls to Inspect’s own publiceval()API (FP); the log-store SQL is parameterized; the lone critical is a transitive, unreachedjupyter-serverCVE (0 direct imports, no Jupyter web app). The 62-finding bulk is GitHub-Actions tag-pinning lint. gitleaks clean, Dependabot wired · post-only - 2026-07-01 — Soju06/codex-lb — 76 findings, 0 real — 11th clean scan, and the most credential-dense target yet: a ChatGPT/Codex-account load balancer + token-pooling proxy + dashboard. The finding that actually matters for a credential proxy — the documented localhost auth-bypass — is one semgrep never raises, and the maintainer already engineered it correctly:
resolve_connection_client_iponly trustsX-Forwarded-Forwhen the socket peer is inside a configured trusted-proxy CIDR set, with chain validation, header sanitization, an explicit auth-mode enum, and a firewall IP-resolution test. SoX-Forwarded-For: 127.0.0.1from a stranger is ignored. The 47 “highs” are Alembic migrations + Markdown; the live-code SQL is parameterized; OAuth logging is request-id-only (never the token); the lone SHA-1 is the RFC 6455 WebSocket handshake (protocol-mandated). Deps clean (Renovate) · post-only - 2026-06-30 — openagents-org/openagents — 680 findings, 0 real first-party — the harbor pattern again, at scale: an “AI Agent Networks” monorepo where the count almost entirely describes the bundled JS/TS frontends, not the Python agent core. All 8 criticals are npm frontend lockfiles (
protobufjs/shell-quote/form-dataacrosssdk/studio154 advisories,workspace/frontend,packages/go/web); ~300 semgrep hits arejs-*lint inpackages/agent-connector/launcher. The Python core is modest and by-design:shell=Truelaunches local npm,non-literal-importis the local mod-loader,evalis in examples/. The scary-looking cleartextws://is mostly mitigated — the default relay is alreadywss://relay.openagents.org(https→wss upgrade); only a secondary direct-peer path isws://. Two gitleaks hits are Firebase web keys (public by design). Dependabot active · post-only - 2026-06-28 — SwanHubX/SwanLab — 32 findings, 0 code-level — 10th clean scan, and an unusual one: the interesting result is the absence of findings. A 4k-star self-hosted AI experiment-tracking platform (W&B-style, with auth/upload/webhooks) where semgrep scanned 361
swanlab/source files and returned zero — no injection, noshell=True, no SSRF pattern. The two gitleaks hits are test fixtures. The entire residual is a 30-CVEuv.lockwith no Dependabot, and reachability splits it cleanly:starlette/ujson/fastapihave zero direct imports (transitive — the multi-user server backend isn’t in this SDK/dashboard repo), whilepillow(OOB-write + decompression CVEs) is genuinely reachable throughswanlab.Imagemedia logging (though an optional extra). Strict-norm (real SECURITY.md + commercial cloud) · post-only - 2026-06-26 — ag2ai/ag2 — 73 findings, 0 real/reachable/undefended — AG2 (formerly AutoGen), the canonical “agents that write and run code” framework, which inverts the usual curation question: the dangerous calls (
exec,docker run,LocalCommandLineCodeExecutor, Jupyter kernels) are the product. The one place attacker-influenced data meetseval()—ContextExpression— is already escaped and carries an inline GHSA-9fvw-gr53-m7fw reference (the maintainers patched their own eval-injection). All 19 secret hits are FP — docstringExample:keys annotated# pragma: allowlist secret, renderer wire-contract constants, tests, and.mdxdocs. Deps are current (Dependabot wired; trivy found one devcontainer-root nit). The one honest residual isag2 serve: no auth + wildcard CORS (credential-less variant) + a built-in--ngrokflag, gated behind operator choices · post-only - 2026-06-25 — Kiln-AI/Kiln — 150 findings, 0 real/reachable/undefended — and the sharpest reachability-illusion in the series: trivy returns 4 critical / 46 high, the two criticals are
langchain-coreRCE on a repo whose production code never imports LangChain (all 11 import sites aretest_*.py; the runtime adapter is LiteLLM-based).langsmithis transitive-only,starlette/mcpare runtime server deps but the server bindslocalhost, and the hardcoded GitHub App secret is a documented PKCE-protected native-client tradeoff. The real signal isn’t a vuln — it’s a lockfile-coverage asymmetry: Dependabot auto-updates the npm frontend (undici/dompurify/vite) but the three Pythonuv.locks (root,libs/core,libs/server) drift uncovered (nodependabot.yml,uv.lockunparsed). Commercial-backed (Kiln Pro) · post-only - 2026-06-24 — maziyarpanahi/openmed — 44 findings, 0 real/reachable/undefended — 9th clean scan, and the first healthcare-domain scan: a local-first clinical-NER + HIPAA-PII tool loading 1,000+ HuggingFace models. The review converges on the one vector that matters — arbitrary code execution via
trust_remote_codeagainst a malicious model — and the maintainer got there first: it defaults off, an allowlist + a constructor that hard-refuses out-of-allowlist remote code, and a regression test headed with its own CVE-2026-47117 enumerating the substring-bypass (attacker/foo-privacy-filter-bar). The 24-CVE lockfile tail is real but transitive and reachability-gated (starlette= opt-in service extra,gitpythonkwargs-RCE never called,urllib3DoS from trusted HF) — and Dependabot is already wired. Workflow shell-injection isworkflow_dispatch-gated (privileged) · post-only - 2026-06-23 — stickerdaniel/linkedin-mcp-server — 6 findings, 0 real after curation — 8th clean scan, and the sharpest “static rules can’t see intent” case yet: an MCP server that decrypts your LinkedIn cookie out of the local Chromium keychain, where the scanner’s four code-level hits are all the hardening itself —
SHA1-inside-PBKDF2 (mandatory for Chromium-cookie interop),0o700on the secrets tempdir (the rule’s suggested0o644“fix” would make them world-readable), a hardcoded GitHub-APIurllibcall, and aCredentialsNotFoundErrorlog misread as a leak. Two transitive dep CVEs (starlette,pydantic-settings) are version-match but unreachable · post-only - 2026-06-21 — taylorwilsdon/google_workspace_mcp — 16 findings, all FP/by-design — 7th clean scan in the series, and the most instructive: an OAuth MCP server (Gmail/Calendar/Docs) where the scanner fired exclusively on the credential layer and every hit was the developer doing it right — unverified-decode of an already-trusted token for email, a log-suppression comment misread as a token leak,
0o600token files, fingerprinted logging, a loopback self-probe · post-only - 2026-06-19 — xerrors/Yuxi — 70 findings, a well-built multi-tenant harness: a sharp reachability discipline traced three tenant/agent sinks (agent-SQL, tenant-JWT, markdown v-html) and every guard held — strict
validate_table_nameallowlist, textbookjwt.decode, DOMPurify. Residual: wildcard CORS + credentials + a reachablepyjwt/langchaindep tail · ✅ Both items fixed ~2 days later (CORS env-allowlist + credentials downgrade, pyjwt 2.13.0) - 2026-06-15 — harbor-framework/harbor — 570 findings, and the count means almost the opposite of what it looks like: 464/570 (81%) and all 10 criticals are in 84 vendored benchmark adapters (
adapters/*), not harbor’s code. Harbor-core (34 findings, 0 critical) does the dangerous things right (tarfilter="data", Supabase publishable keys, by-design sandbox subprocess). The lesson: the first curation step on a monorepo is an ownership split. Filed one structural question on the sandbox-isolation threat model, not a 570-finding enumeration - 2026-06-12 — mistralai/mistral-vibe — 21 findings, a clean coding-agent scan: the git wiring is safe-by-construction (GitPython argv API, no shell;
hashlib.sha1(..., usedforsecurity=False)explicitly non-crypto). Real signal is a dependency tail with a sharp reachability split —gitpythonimported/reachable (bump it),pyjwtdeclared-but-never-imported (version-match, not applicable) — ❌ #775 closed asnot planned2026-08-05, no comment. The pins moved anyway on the project’s own release cadence (pyjwt→ 2.13.0 within a week,gitpython→ 3.1.53), and OSV now matches zero advisories for pyjwt and nine fewer for gitpython — including theconfig_writerone this scan named as most-severe-sounding and correctly called unreachable. A dismissal, not an acknowledgement: a routine dependency-refresh issue has little to offer a project that already refreshes dependencies fast — a signal about which findings earn a maintainer’s inbox. - 2026-06-11 — dataelement/Clawith — 54 findings, and the scan that caught a silent-failure bug in AI PatchLab’s own scanner: Semgrep crashed mid-write (Windows cp1252 vs the repo’s Chinese source), left a 0-byte report, and 43 findings vanished — the first pass looked clean at 11. Fixed in PR #47 (force UTF-8 + treat empty report as scan error). Real items: a
head.refworkflow shell-injection, a 6-CVE React Router frontend lockfile (no Dependabot), a Helm chart default password, nginx hardening - 2026-06-10 — Ar9av/obsidian-wiki — 0 findings literally (sixth clean scan in the series, and the cleanest in raw count). Manual
semgrepre-run confirmedresults: 0, errors: 0. Architecture is “thin installer CLI + delegated Claude Code skills” — the agent intelligence lives in skill markdown the scanner doesn’t read, leaving almost nothing to fire on - 2026-06-09 — confident-ai/deepteam — 48 findings, zero real in-scope runtime items; 5th clean scan in the series. Gitleaks hits were intentional OSS-telemetry write-only keys (PostHog
phc_…+ New Relic OTLP license); the 24-CVE trivy tail split between an out-of-scope Docusaurusdocs/yarn.lockand a Pythonpoetry.lockwhose Dependabot was already on the job · post-only, no issue filed - 2026-06-08 — 54yyyu/zotero-mcp — 4 scanner findings → 6 confirmed-real curated items, only 1 of which came from the scanner. First scan run under the project’s ultracode mode (23-agent parallel completeness sweep across MCP-specific surfaces). Headline: medium SSRF in OA-PDF discovery reachable via prompt injection + medium plaintext
ZOTERO_API_KEYstdout dump (discipline break — same function obfuscates 25 lines earlier) + 4 hardening lows. The strongest “scanner alone undercounts MCP-specific surface” demonstration in the series. · ✅ All six items fixed and merged ~6h later in PRs #327 + #328; v0.5.0 cut 9 min after issue close. Maintainer explicitly credited the adversarial-verification methodology. - 2026-06-06 — LazyAGI/LazyLLM — 121 findings, series record for the
pull_request_targetcluster (16 sites in one workflow), Gradio ×3 + DeepSpeed RCE dep tail, classiceval()-based Calculator agent tool; two highest-severity items disclosed privately to a corporate maintainer address (SenseTime backing) — no public courtesy issue, post-only - 2026-06-04 — agentscope-ai/ReMe — 159 findings, 3 concrete items filed (wildcard CORS + credentials on both HTTP-service entrypoints,
chromadbCVE, Neo4jpassword="neo4j"default) · largest SQL-identifier cluster in the series so far (139 sites across 3 vector/file-store backends) + a new flow-DSLexec/eval-with-restricted-globals shape to watch · ✅ All three items fixed inreme4/~13h later (item-by-item response) - 2026-06-03 — Q00/ouroboros — 34 findings, third “deps-are-the-thing” scan in a row (after MemoryBear & agency-swarm) —
litellm7-advisory stack +anthropic2-pair reported privately via the published SECURITY.md channel · ✉️ Maintainer triaged within 48h SLA: all advisories are genuine version-matches but none reachable in Ouroboros’s library-only usage (no LiteLLM Proxy, no anthropic memory-tool feature); coordinated refresh scheduled; post corrected for the surface conflation 2026-06-08 - 2026-06-02 — VRSEN/agency-swarm — 48 findings, auth-tier dep concentration that fits the project’s shape:
authlib1 critical + 3 auth-bypass highs andfastmcp1 critical SSRF + OAuth pile, on a multi-agent OAuth/MCP framework with no Dependabot · the recurringshell=True-in-agent-shell-tool by-design class · ✅ Resolved 2026-06-04 in PR #659 (~15h) - 2026-06-01 — SuanmoSuanyangTechnology/MemoryBear — 196 findings, 3 named critical CVEs in a stale
api/uv.lock(pytorch RCE-class, fastmcp SSRF, nltk Zip Slip) on a repo with no Dependabot · 37× Jinja2-for-LLM-prompts is the new rule-misfit class of the series · 📝 Maintainer acknowledged + closed 2026-06-12 with intent to review + add Dependabot (no fix landed yet) - 2026-05-29 — homeassistant-ai/ha-mcp — 65 findings, zero real in-scope items; a strict-norm repo whose maintainer published a precise threat model — every scary finding is a fixture, an intentional public demo token, a documented by-design decision, or an FP · post-only, no issue filed
- 2026-05-28 — evalstate/fast-agent — 36 findings, near-clean scan where the maintainer already hand-rolled the hard mitigations (a tar-traversal guard, a filename sanitizer before a shell call); actionable surface is two defense-in-depth hardenings + a Dependabot-lane
requestsCVE pair · ✅ Both hardenings adopted in v0.7.13 the same day (~8h) - 2026-05-27 — aurelio-labs/semantic-router — 116 findings, cleanest two-person-team scan in the series; entire actionable surface is 50 SQL-identifier sites in one Postgres-backend file + a 30-advisory dep-drift tail · ✅ partially resolved 2026-08-10 — the dep-drift half merged as PR #678, both lockfiles refreshed and verified through the project’s own Dagger pipeline, with the advisories that couldn’t be cleared (blocked by
fastembedpins) documented rather than papered over. Notable because a third-party contributor picked it up ten weeks after filing — the first disclosure in the series resolved by neither the maintainer nor me, which is the argument for filings specific enough that a passer-by can adopt them. The SQL-identifier half has not landed and the issue stays open; it was always the identifier-interpolation FP filed as hardening, never exploitable, so it is the predictable half to go unprioritised - 2026-05-27 — pixeltable/pixeltable — 67 findings, first scan to surface a CVE-2007-4559-shape
tarfile.extractallfinding on a code path that imports user-shared bundles; plus the recurring 26-site SQL-identifier class in the catalog layer · ✅ PR #1378 (filter='data') merged 2026-06-07 (~11 days, silent merge after CI review) - 2026-05-26 — dstackai/dstack — 163 findings, 3 real critical Go CVEs in the runner (SSH
PublicKeyCallbackauth-bypass, Moby AuthZ bypass, go-git argument injection) + 21 workflow-injection patterns (series-high) · ❌ Issue declined by maintainer for disclosure-format reasons; honest record kept - 2026-05-26 — pydantic/logfire — 27 findings, third clean scan in the series; every
eval/exec/pickle finding is a deliberate language-feature use that an observability library structurally needs - 2026-05-25 — MinishLab/semble — 2 findings, second clean scan in the series (after Giskard); a small focused library with two hyper-responsive maintainers
- 2026-05-25 — plastic-labs/honcho — 315 findings, real cluster on the MCP server’s Hono framework (~9 CVEs incl. auth bypass) + a critical
basic-ftpin the docs-site lockfile; first scan wherelogger-credential-leakhit five-for-five FPs across the series - 2026-05-21 — HolmesGPT/holmesgpt — 2,143 findings, 93% are an SRE agent’s deliberately-broken Kubernetes test fixtures; real signal is 17 workflow-injection patterns + a drifted
experimental/front-end - 2026-05-21 — dograh-hq/dograh — 69 findings, one dominant cluster (outdated Next.js across two front-ends, incl. middleware-bypass advisories) + a fail-open
OSS_JWT_SECRETdefault · ✅ 3 of 4 PRs merged bynuthalapativarun(2026-05-27); issue closed - 2026-05-20 — Klavis-AI/klavis — 1,556 findings (largest scan in the series), 22 critical dependency CVEs incl. authlib auth-bypass + fastmcp SSRF; a case study in monorepo dependency drift across 50+ MCP servers
- 2026-05-20 — Giskard-AI/giskard-oss — 27 findings, all false positives — first clean scan in the series; a teardown of
pull_request_targetdone right vs the airweave finding - 2026-05-19 — guardrails-ai/guardrails — 17 findings, first dep-scan hits in the series (7 known CVEs on a pinned
litellmupper bound) + 2× duplicatedunverified-jwt-decode+ 4× workflow inputs interpolation - 2026-05-19 — airweave-ai/airweave — 46 findings, ~4 publishable best-practice items + 1 disclosed privately via SECURITY.md email channel, ~30 false positives or intentional-by-design patterns
- 2026-05-16 — MervinPraison/PraisonAI — 489 raw findings (largest scan yet), 5 real items, first validation of the
--ignore-fileworkflow on a fresh target · ✅ All five resolved in PR #1677 by theirpraisonai-triage-agentbot + human review (merged 2026-05-19) - 2026-05-15 — Upsonic/Upsonic — 40 findings, 4 real items across SSL/SQL/subprocess/pickle, ~36 false positives or by-design patterns
- 2026-05-15 — msoedov/agentic_security — 9 findings, 2 real best-practice items + 1 disclosed privately, 6 false positives or out-of-scope · ✅ Both public items resolved in commit
dd59704with tests (issue #298 closed 2026-07-31) — and the fix’s own analysis is sharper than the report’s: Starlette doesn’t emit*whenallow_credentials=True, it reflects the request Origin, so this was a live reflect-any-origin hole rather than the milder “credentials silently disappear” spec-violation the write-up described. Private finding still in triage - 2026-05-14 — traceloop/openllmetry — 33 findings, 25 false-positive secrets in test cassettes, 1 best-practice item filed with the maintainer
- 2026-05-14 — gptme/gptme — 57 findings, 3 best-practice improvements filed with the maintainer · ✅ All three resolved in PR #2399 (merged 2026-05-15)
About AI PatchLab
AI PatchLab is a Python CLI that produces JSON and Markdown security reports from a local repository path. It is designed for engineers and maintainers who want a real audit without sending their codebase to a cloud service.
- Source: github.com/elfrost/ai-patchlab
- Built on top of Semgrep, Gitleaks, Trivy, and pip-audit
- AI review is disabled by default and local-first when opted in
For setup and full documentation, see the project README.