A public issue filed on July 8 is still open eight releases later, and VulnCheck assigned it CVE-2026-85623 this morning with the affected range running through a build that shipped yesterday.
What happened
VulnCheck published CVE-2026-85623 at 10:17 a.m. Central today, September 4, 2026, against goose, the open-source AI agent maintained under the Agentic AI Foundation at the Linux Foundation. The record scores it 8.8 on CVSS v3.1 (AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H) and 8.7 on v4.0, both from VulnCheck as the scoring source, and classes it CWE-94, code injection. The affected range is 0 through 1.49.0, semver. There is no fixed version in the record, and no solution or workaround entry in the CVE Program copy either. Version 1.49.0 is the current release; it shipped yesterday, September 3, at 7:34 p.m. UTC.
goose distributes reusable agent configurations called recipes. They travel as files, as deeplinks, and as content in GitHub repositories — the ordinary way one developer hands another a working setup. Two fields inside a recipe cause programs to run. An extensions entry of stdio type carries cmd and args, and the process is spawned before any MCP handshake takes place. A retry entry can carry shell checks, which are executed through sh -c.
goose ships a recipe inspection routine, Recipe::check_for_security_warnings. Severity Daily read it in the v1.49.0 source that the CVE record itself cites. In full, what it examines is this:
if [self.instructions.as_deref(), self.prompt.as_deref()]
.iter()
.flatten()
.any(|&field| contains_unicode_tags(field))
{
return true;
}
if let Some(activities) = &self.activities {
return activities
.iter()
.any(|activity| contains_unicode_tags(activity));
}
false
Three fields — instructions, prompt, and activities — checked for one thing, hidden Unicode tag characters. The Recipe struct in the same file has extensions and retry fields. The function does not read either of them.
The finding is not new; the identifier is. A researcher publishing as geo-chen, credited in VulnCheck’s advisory as George Chen, opened issue #10325 on the goose repository on July 8, 2026, titled “A shared recipe silently runs arbitrary commands (stdio extension cmd / retry shell checks), and the recipe security scan does not cover those fields.” The issue includes a proof of concept executing a command on version 1.37.0 with no consent prompt and no warning, and it recommends four mitigations: an explicit consent step naming the commands, extending the scan to flag process-spawning extensions, invoking the scan in the CLI path, and restricting inline stdio commands that arrive from remote sources. As of this writing the issue is open, carries no labels, and has no maintainer reply. The third recommendation rests on a further claim of the researcher’s that Severity Daily has not independently verified: that the scan is not called at all on the CLI path.
One discrepancy worth noting in the record. The description reads “goose 1.37.0 executes arbitrary commands from recipe stdio extensions and retry.checks without security inspection” — naming the single version the proof of concept ran on — while the CPE configuration covers everything up to and including 1.49.0. The range is the accurate statement of scope, and our own read of the current source supports it.
CVE-2026-85623 arrived inside a batch. NVD received 60 records from VulnCheck between 3:17:32 and 3:17:48 p.m. UTC, sixteen seconds, and nearly all of them are AI and machine-learning tooling: MCP servers for Excel, Postgres, Git, and shell access; Aim, Xinference, LLaMA-Factory, ms-swift, Chroma, and Marqo; document pipelines including marker, zerox, surya, and MegaParse; and two more AI coding agents, aider and Plandex, at 7.8 each. Severity Daily has covered VulnCheck’s batch-assignment pattern three times before; this story is about one record in the batch, not the batch.
Why it matters
goose has already published an advisory for a defect in this exact class. GHSA-r5pp-p5r8-466r, released July 24, 2026 and carrying CVE-2026-72718, covers arbitrary command execution in the goose CLI by way of Git’s core.fsmonitor key: a repository’s own configuration file names a program, and the agent runs it while collecting workspace context. It was scored 7.0 and fixed in 1.44.0, which shipped July 23, the day before the advisory went out. Severity Daily covered that class on September 2, across seven agents.
Put the two side by side. Both are attacker-controlled configuration data naming a program that the agent executes before asking the user anything. One was triaged, fixed, and advised on. The other, reported publicly fifteen days before that fix shipped, is still open after eight releases — 1.42.0, 1.43.0, 1.44.0, 1.45.0, 1.46.0, 1.47.0, 1.48.0, and 1.49.0 — and the third party that eventually assigned it an identifier scored it 8.8, nearly two points above the one that got fixed.
The obvious explanation is the honest one, and it is not misconduct. The fsmonitor report came in through GitHub’s private advisory workflow, which is a security intake. The recipe report came in as a public issue on a bug tracker, which is not. Maintainers are entitled to run a private channel and to treat it as the queue that gets security attention, and a project’s own advisory page is a poor place to look for defects nobody reported there. That asymmetry explains the fifty-eight days.
It does not dispose of them. The issue has been public since July 8 with a working proof of concept in it, which means the disclosure decision was made on day one by the reporter and is not recoverable. Today a CNA read that same public issue, scored it high, and stamped an identifier on it that will appear in every scanner keyed to CVEs. The window in which a private channel would have helped closed in July. What remains is a defect that is public, identified, and unfixed in the current release.
The narrower point is about what the scan was built to catch. Someone wrote check_for_security_warnings deliberately: the design intent is that a recipe arriving from a stranger should be inspected before it runs. What it inspects — hidden Unicode tag characters in the natural-language fields — is a prompt-injection defense, and a reasonable one. The fields that spawn operating system processes were never in its scope. That is the gap this record actually documents, and it is not confined to one project: agent tooling has spent two years hardening the path where text reaches a model, while the configuration format that ships alongside the text quietly grew a field that runs sh -c.
What to do
There is no fixed version to move to. Until there is, treat any goose recipe originating outside your own organization as an executable file, because that is what it is.
Before running goose run --recipe or opening a recipe deeplink, read the recipe’s extensions and retry keys directly. Any extension with type: stdio carries a cmd and args pair that will be executed under your account, and it runs before the MCP handshake, so an extension that never speaks MCP still gets its process. Any retry check of shell type goes through sh -c. The deeplink path deserves the most caution precisely because it looks least like running a program.
Do not rely on goose’s own security warning to catch this. Verified against the v1.49.0 source today: it does not read those fields.
If you distribute recipes internally, keep them in a repository you control and review changes to extensions and retry with the same scrutiny you would apply to a CI workflow file, which is the closest analogue. For monitoring, watch issue #10325 and the project’s published advisories; no GHSA has been issued for this defect as of this writing.
Sourcing note
Checked: the NVD record for CVE-2026-85623, the CVE Program record at cveawg.mitre.org (state PUBLISHED, assigner VulnCheck), VulnCheck’s own advisory page for the finding, GitHub issue #10325 in its current state, the goose repository’s published security advisories, the repository’s release list, and the v1.49.0 source of crates/goose/src/recipe/mod.rs — the last of these is how the scan’s field coverage was verified first-hand rather than taken from the reporter’s account. The claim that the scan is not invoked on the CLI path is the reporter’s and is labeled as such above; we did not trace the call sites. Scoring on this record is single-source: VulnCheck supplied both the v3.1 and v4.0 vectors, and no other scorer has weighed in. There is no vendor statement of any kind — no maintainer reply on the issue, no advisory, no fixed release — so nothing here reflects the project’s own assessment, and that absence is part of the story rather than a gap we could close. cisa.gov refuses automated fetching, so KEV status is inferred from the absence of CISA fields in the NVD record rather than read from the catalog; there is no indication of exploitation, and none is claimed. Prior Severity Daily coverage of the related core.fsmonitor class and of VulnCheck’s batch-assignment pattern is linked inline.

