
MaxKB Attached a Shell Tool to Every Tool-Enabled Assistant and Never Gated It
- OrcaNEWOrcaCyber: GLM 5.3 Flash Abliterated2026-10-2796 tok/s
- OrcaNEWOrcaCyber: Qwen3.8 Flash Next Abliterated2026-10-26$0.80 / $1.60 per 1M tokens · 252 tok/s
- OrcaNEWOrcaCyber: MiMo V2.6 Flash Abliterated2026-10-26$0.80 / $1.60 per 1M tokens · 89 tok/s
- MoonshotNEWMoonshotAI: Kimi K3.1 Pro2026-10-2446Intelligence
- OrcaNEWOrcaCyber: DeepSeek V4.1 Flash Abliterated2026-10-23$0.80 / $1.60 per 1M tokens · 107 tok/s
- minimaxNEWMiniMax: M3.1 Flash2026-10-1929Intelligence
- OrcaNEWOrca: OrcaCyber Ultra 1.02026-10-17$5.00 / $10.00 per 1M tokens · 53 tok/s
- deepseekNEWDeepSeek: DeepSeek V4.1 Flash 10172026-10-1733Intelligence
- DeepSeekNEWDeepSeek: DeepSeek V4.1 Flash2026-10-1740Intelligence
- OrcaOrca: OrcaCyber Zero 1.52026-10-10$3.00 / $7.50 per 1M tokens · 116 tok/s
- openaiOpenAI: GPT-6.1 Sol2026-09-2955Intelligence
- anthropicAnthropic: Claude Sonnet 5.52026-09-2854Intelligence
- typesafeTypeSafe: Jev 1.132026-09-24$0.04 / $0.00 per 1M tokens · 140 tok/s
- OpenAIOpenAI: GPT-6 Luna2026-09-2228Intelligence
- OpenAIOpenAI: GPT-6 Sol2026-09-2248Intelligence
- AnthropicAnthropic: Claude Opus 5.52026-09-2258Intelligence
- xiaomiXiaomi: MiMo-V2.6-Flash2026-09-2127Intelligence
- xiaomiXiaomi: MiMo-V2.6-Pro2026-09-2130Intelligence
- xAIGrok 4.72026-09-2134Intelligence
- OrcaOrca: OrcaCyber Zero 1.02026-09-17$3.00 / $7.50 per 1M tokens · 182 tok/s
MaxKB, an open-source enterprise assistant platform published under the GitHub organisation 1Panel-dev, built its chat agents on a framework that silently adds a shell tool whenever a shell-capable backend is passed in — and MaxKB never removed the tool or asked anyone to approve its use. The flaw is CVE-2026-77521, published as GitHub advisory GHSA-f36j-f34j-h3rx on 2 September 2026 and scored 10.0 out of 10 under CVSS 3.1 for the case of a public or embedded assistant. Lasso Security, which found and reported it, demonstrated that a chat message — or text the assistant merely ingests through retrieval or an uploaded document — could drive the model to run commands: on a bare-metal deployment directly on the host, and on the official container through a wrapper the researchers say is bypassable with a semicolon. No cited source records the flaw being exploited in the wild. The record's own severity grade, confidence assessment and source list sit in the AI incident archive, alongside the neighbouring MaxKB and agent-tooling entries from the same disclosure batch.
MaxKB is a self-hosted product for building retrieval-augmented assistants: an operator creates an assistant, attaches capabilities to it — tools, Model Context Protocol servers, skills, sub-applications — connects a knowledge base built from uploaded documents or crawled websites, and then exposes the assistant either through an authenticated console or as a public, embeddable chat widget. That versatility is the exposure. The advisory's trigger condition is not an unusual configuration but the ordinary one: any assistant with at least one capability attached routes its chat through the affected agent path, while a chat with no capabilities attached does not. Lasso's write-up describes the project as one of the more widely adopted in its category, and notes that MaxKB is normally deployed as a multi-tenant service — which puts a command running as the application user underneath the tenancy model rather than inside one tenant's slice of it.
The shell tool arrived with the framework, not the product
MaxKB builds these agents with LangChain's deepagents library, pinned to version 0.6.11 in the project's pyproject.toml at both the vulnerable tag and the current one. In apps/application/flow/tools.py, at line 467 of the v2.10.3-lts tag, the project calls create_deep_agent with backend set to SandboxShellBackend, a MaxKB subclass that runs commands on the host. Per the advisory, deepagents auto-injects a set of tools whenever a shell backend is passed that way: execute, ls, read_file, write_file, edit_file, glob and grep. They are not part of the tools=list argument, which carries only the operator's own tools, MCP tools and skill tools. They cannot be removed from the interface or through configuration.
MaxKB also does not pass excluded_tools, the library argument that would strip them. The advisory is careful about why that matters even as a remedy: excluded_tools "removes the tool from what the model is told, not from the executor". The distinction between a tool the model is unaware of and a tool that cannot run is the whole of this bug in miniature.
A gate that lists three tools and omits the fourth
The human-in-the-loop control in that same call is one line, and it enumerates three operations: interrupt_on={"write_file": False, "read_file": False, "edit_file": False}. Writing a file, reading a file and editing a file are named. Command execution is not a key in the dictionary at all. In the advisory's reading, that means no approval is sought for execute — the three filesystem operations are named and explicitly set not to interrupt, and the shell tool is not named at all.
Put together, the path is: untrusted text reaches the model, the model calls execute, and the command runs. The advisory names two ways for untrusted text to arrive. The direct one is chat — a public or embedded widget, or another tenant's conversation. The indirect one is content the assistant ingests: a RAG document, an uploaded file, or a web page the platform crawls into a knowledge base. Lasso's post makes the second route concrete, observing that "the set of people who can put text in front of the model is larger than the set of people who can chat with it".
On a bare-metal install, the command is just a command
Whatever MaxKB does about containment happens in apps/application/flow/backend/sandbox_shell.py, and in v2.10.3-lts it begins with a default. Line 9 reads _enable_sandbox = bool(int(CONFIG.get("SANDBOX", 0))), and SANDBOX does not appear in Config.defaults in apps/maxkb/conf.py. Absent an explicit MAXKB_SANDBOX setting, the value is zero, the wrapper branch at line 65 is skipped, and execute reaches subprocess.run with shell=True directly on the host, as the user running the service — root, in the advisory's phrasing, if the service runs as root.
That is the configuration the researchers used for their host proof of concept. They ran MaxKB's real code from source with MAXKB_SANDBOX unset, created an assistant with one tool attached, and asked it in a single chat message to run system-information commands. The execute tool fired and wrote a file whose contents were the host's own uname, id and sw_vers output — output that, the advisory notes, was confirmed absent inside any container. Lasso also records the limit of what stopped it: a blatantly named proof file was refused by the model, while benign operational phrasing was not. Model alignment, in their words, is "a partial speed-bump, not a control".
On the official image the sandbox ran and still leaked
The official container sets MAXKB_SANDBOX=1 in the base image, at installer/Dockerfile-base line 48, so the wrapper is active there — and the wrapper is the second flaw. It built one string: env -i LD_PRELOAD=/opt/maxkb-app/sandbox/lib/sandbox.so followed by gosu sandbox and then the model-supplied command, handed to a shell running as root. Because the command was interpolated as text, only the first token of it sat under gosu. Any semicolon, pipe, redirect or command substitution in the model's output was evaluated by the outer root shell before the sandbox ever saw it.
Lasso's write-up gives the working shape of it: a payload of env -i LD_PRELOAD=... PATH="$PATH" gosu sandbox ls; whoami; id, in which ls is confined, whoami is not, and everything after it runs free. In testing, the researchers wrote a root-owned file with a redirect while the sandboxed inner command was blocked. Compounding it, neither installer/Dockerfile nor installer/Dockerfile-base contains a USER directive, so the application image runs as UID 0 — the advisory reports confirming root at runtime. The container therefore executed commands regardless, and the sandbox only decided which ones were cosmetically attributed to the low-privilege user.
The full attack flow Lasso describes needs no access to the target at all. The attacker puts commands on a web page, waits for a victim's agent to crawl it into a knowledge base, and the victim then asks an ordinary question. The answer comes back correct and legitimate; the injected curl has already fired at the attacker's server. The advisory notes the researchers tested only their own deployments, not any third-party or hosted MaxKB instance.
What the sources establish, and what is simply not measured
The mechanism, the two deployment modes, the credit and the fixed release agree across four documents: the GitHub advisory, the NVD record published on 21 September 2026, Lasso's own technical write-up of 10 September 2026, and GBHackers' report of 22 September 2026, which is the only independent outlet coverage found for this CVE. No source disputes any part of the finding, and the archive records the entry as undisputed at its highest confidence grade.
What the sources do not contain is any measure of exposure. There is no count of MaxKB deployments, no count of internet-facing or embedded assistants, no scan result, no telemetry and no named victim. Nothing in the record shows the flaw being used against anyone, and CISA's own exploitation assessment agrees: the SSVC block attached to the NVD record on 22 September 2026 rates exploitation as "poc", automatable as "yes" and technical impact as "total". FIRST's EPSS model put the probability of exploitation in the next 30 days at 1.05 percent, the 64th percentile, on 27 October 2026, and the CVE does not appear in the CISA Known Exploited Vulnerabilities catalogue dated 27 October 2026. The archive's own grade reflects the same evidence: severity high, real harm false.
The 10.0 deserves its scope stated, because it is the number most likely to be quoted out of context. It is the score for the public or embedded assistant case, where the CVSS vector reads AV:N/AC:L/PR:N/UI:N/S:C — network reachable, no privileges, no user interaction, with a scope change because a command inside the assistant crosses into the host operating system. The score is the CNA's, and the CNA here is GitHub's advisory programme, which is also where the CVE record's source identifier points. NVD carries the same vector as a secondary metric and, as of 28 October 2026, lists the entry in "Deferred" status, meaning NVD has published the assigner's analysis rather than its own.

The patch shipped a month before the advisory did
The chronology runs backwards from publication, and it is the least intuitive part of the record. Lasso reported the flaw privately through GitHub's advisory channel on 8 July 2026. MaxKB replied the next day, scoping the report to the official image and asking for a container proof of concept; the researchers supplied that and the sandbox bypass on 10 July. A fix commit, 594f50f2, landed on 9 July — one day after the report — and rewrote sandbox_shell.py so that the model's command string is parsed first and the gosu prefix is applied to every simple command rather than to the first one only, with each argument list re-quoted so that substitution cannot escape into the parent shell. Lasso's write-up describes the change as applying the gosu prefix "to every simple command, not just the first".
The release carrying it, v2.10.5-lts, was published on 6 August 2026. The GitHub advisory went up on 2 September, NVD published the CVE on 21 September, CISA's SSVC block was added and GBHackers reported on 22 September, and Lasso's own write-up appeared on 10 September — in the middle of that sequence, not at the start. An operator tracking release tags rather than advisory feeds had the patch roughly four weeks before the warning.
The version boundary is worth more attention than the advisory gives it, because the two primary sources disagree and the repository settles the question. The advisory form field records affected versions as "<= 2.10.3-lts", with a note that this was verified on 2.10.3-lts and that the vulnerable path "likely" affects all versions that build agents this way. Lasso's own write-up states the affected range as "<= 2.10.4-lts". The tags confirm the wider range: v2.10.4-lts, released 16 July 2026, carries the same 75-line sandbox_shell.py as v2.10.3-lts, and the rewritten 311-line file first appears in v2.10.5-lts. An operator on 2.10.4-lts who read only the advisory's range would have concluded they were outside it. They were not.

What the fix did not do
What 2.10.5-lts fixes is the wrapper: it no longer builds one shell string under root. What it does not do is anything about the tool. Direct reading of the repository at tag v2.10.8-lts, published 22 October 2026, shows the agent still constructed with backend=SandboxShellBackend and interrupt_on still carrying exactly three keys — write_file, read_file and edit_file — with no execute. The advisory's first two remediation suggestions, to build on a non-execution backend by default and to add "execute": True to the approval map, are not present in that release.
The fail-closed recommendation landed later, in v2.10.7-lts, and it matters for the deployment mode that was worst off. Published on 15 October 2026, it changes the line in sandbox_shell.py from CONFIG.get("SANDBOX", 0) to CONFIG.get("SANDBOX", 1). A source or bare-metal install that never set the variable now has the wrapper switched on by default rather than off, which is the "fail closed on non-container deploys" recommendation in the narrow sense. The advisory asked for more than that under the same heading — that the execute-capable flow refuse to start when the sandbox runtime is unavailable — and asked separately for the wrapper never to build a command string for a root shell. On the container side, a fact rather than a recommendation: neither installer/Dockerfile nor installer/Dockerfile-base carries a USER directive at the v2.10.8-lts tag, so the application image still starts as root.
Read together, the state of the record as of 28 October 2026 is this. The second half of the vulnerability — the sandbox that a semicolon walked out of — is closed, and the fail-open default on host deployments is closed. The first half, an execute tool that arrives with a backend object and is not a key in the approval map, is still how MaxKB builds a tool-enabled assistant. The researchers' own remediation advice was the narrow one: upgrade to 2.10.5-lts or later, and run the Docker version with the sandbox enabled. GBHackers relayed the same instruction plus a broader list for administrators — disable shell-capable agent backends unless code execution is explicitly required, require human approval before any execute action, run containers as non-root, and treat crawled pages, RAG documents and uploads as untrusted input.
The other MaxKB record from the same September batch
The archive's second MaxKB entry from this batch is a different bug with a worse ending. CVE-2026-77516, also published to NVD on 21 September 2026, is a permission bypass rather than a command injection: from version 2.0.0 through 2.9.2, a workspace member at the lowest role, explicitly denied access to a tool through WorkspaceUserResourcePermission, could still bind that tool's identifier through tool_ids, skill_tool_ids or mcp_tool_ids and execute it through the agent or workflow dispatch path. The dispatch path does not reapply the per-tool grant that the dedicated tool routes enforce, and tool execution decrypts server-side init_params, so the caller receives credentials carried by the tool they were denied. Its score is 5.4, and NVD's description closes with a sentence that CVE-2026-77521 does not have to carry: "No fixed version is available as of this review."
The contrast is the useful part for anyone triaging the pair. The flaw that scored 10.0 had a fix committed within a day and released a month before it was published. The flaw that scored 5.4 had no fixed version published at the time of its CVE.

What remains genuinely open is smaller than the score suggests and larger than a patch note implies. The finding is not in dispute and the mechanism was verified end to end on both deployment modes by the team that found it. The exposure is entirely unmeasured — nobody has published how many MaxKB assistants carry a tool, how many of those are reachable by an untrusted party, or how many run on a host without the sandbox — so the real-world consequence of the flaw is a function of deployment habits that no cited source counts. And the part of the design that drove the score to the maximum is still there in the current release: a capability that runs commands, attached by default, absent from the map that asks a human first.
