The Code Node Ran as Root: Astron Agent’s CVE-2026-108263 Turns a Workflow Block Into Cross-Tenant RCE
Agentic workflow platforms sell a comforting abstraction: users compose blocks, the platform executes them. CVE-2026-108263, published 9 October 2026, is what happens when one of those blocks is a Python interpreter running without a sandbox. In iFlytek’s Astron Agent (8,885 stars), the default workflow code-node path executed tenant-supplied Python through an unsandboxed local executor — as root, in the shared workflow container, with shared service credentials in reach. GitHub rates it 9.9 critical (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H) under CWE-95 (Eval Injection), CWE-306 (Missing Authentication for Critical Function) and CWE-653 (Improper Isolation). Affected: < 1.1.2. Fixed: 1.1.2.
The mechanism is a default, not an edge case. And like the Strawberry permission bypass disclosed the same week, the fix had been installable for over a month before the identifier existed: 1.1.2 shipped on 7 September 2026, and the CVE was reserved and published on 9 October — a 32-day window in which scanners had nothing to match against.
The default executor was “local”
We read core/workflow/engine/nodes/code/code_node.py at tag v1.1.1 directly. The executor selection was one line:
"e2b" if sandbox_config else os.getenv("CODE_EXEC_TYPE", "local")
Unless a per-node E2B sandbox was configured and carried an API key, the node fell through to whatever CODE_EXEC_TYPE said — and the default for that variable was "local". The CVE record states that LocalExecutor supplies complete Python builtins to dynamically evaluated code without the documented sandbox restrictions, reachable through two endpoints: /console-api/workflow/code/run and /workflow/v1/run. An authenticated low-privilege tenant could therefore execute arbitrary Python as root in the core-workflow container, pick up shared service and database credentials, bypass application-level tenant checks, and read or modify other tenants’ data — or disrupt shared services outright. The scope change (S:C) in the 9.9 vector is doing exactly the work it should: the vulnerable component is a workflow node, and what falls over is everything around it.
Note the quiet cruelty of the gating condition. E2B sandboxing was not absent — it was conditional on configuration that most deployments never set. A deployment that never touched sandbox settings got local execution silently. There was no warning, no degraded-mode banner, no refusal. Compare this with the pattern we documented in DB-GPT’s silent sandbox fallback: security that depends on optional configuration the operator never knew was load-bearing is not a default, it is a trap with documentation.
The fix refuses to guess — and we checked it
We read the same file at v1.1.2. The executor resolution is now gated by an allowlist, and anything else is a hard error:
ISOLATED_CODE_EXECUTOR_TYPES = frozenset({"ifly", "ifly-v2", "langchain"})
"No isolated code executor is configured. Enable the E2B sandbox, keep the "
f"built-in {DEFAULT_CODE_EXECUTOR_TYPE} executor enabled, or configure "
"CODE_EXEC_TYPE with another isolated executor. In-process local execution "
"is disabled."
The new _resolve_executor_type() raises with that message whenever the resolved type is not in the isolated set. The default moved from "local" to the built-in isolated LangChain/Pyodide executor; E2B stays optional; PR #1650 (by yjlu666, “migrate legacy executor defaults safely”) additionally migrates untouched legacy config templates to the isolated default while preserving explicit operator overrides — including operators who deliberately disabled code nodes. That last detail matters: the migration preserves an explicit “off” instead of re-enabling execution behind the operator’s back.
This is the correct shape for the fix, and it rhymes with the Strawberry resolution from the same week: when the platform cannot execute code safely, it must refuse rather than proceed insecurely. The v1.1.1 class docstring promised a “secure environment for executing user-defined Python code.” In v1.1.2, that promise is enforced by code instead of prose.
Who is actually exposed
The CVE record and the 1.1.2 release notes draw the blast radius carefully, and it is wider than “multi-tenant clouds”:
- Multi-tenant deployments — the worst case. Any authenticated user with workflow creation permissions could cross tenant boundaries and touch other tenants’ data. The privilege requirement is low (
PR:L), not zero: anonymous callers are not in scope, but any tenant user is. - Single-tenant deployments — still affected by the code-execution risk, per the release notes. The tenant boundary is not the only thing that falls; arbitrary code as root in the workflow container is a full compromise of that container regardless of tenancy.
- Deployments that set
CODE_EXEC_TYPEexplicitly to an isolated executor — not affected. If you overrode the default deliberately, the vulnerable path was never selected.
The uncomfortable question for operators is the credential one. The CVE record says shared service and database credentials were reachable from the workflow container. If you ran an affected version in multi-tenant mode, upgrading the executor fixes the entry point — it does not un-share credentials that a previous tenant’s code may already have read. Credential rotation belongs on the remediation checklist, not just the version bump.
The timeline, from published records
- 7 September 2026, 06:43:46Z — v1.1.2, “Security Release,” published. The notes name the unsafe code-node execution, the tenant-isolation impact, and the linked advisory GHSA-mh3w-4q3f-2fg5, and state that a CVE identifier had been requested and was awaiting assignment.
- 9 October 2026, 17:33:15Z — CVE-2026-108263 reserved.
- 9 October 2026, 20:47:38Z — CVE record published. 21:17:04Z — NVD ingestion, status “Received” with the 9.9 GitHub-supplied score; no independent NVD analysis at the time of writing.
Thirty-two days separate an installable, correctly labelled security release from the identifier that lets scanners see it. The project did everything right on the disclosure side — the release notes are explicit, the advisory is public, the CVE was requested promptly — and scanners were still blind for a month, because the ecosystem keys off the identifier, not the release note. If you pin Astron Agent, the operational lesson is the one we keep repeating: read the security-labelled release notes for the versions you skip; the advisory feed is a lagging indicator.
What to do
- Upgrade to 1.1.2 or later (current guidance at the time of writing; verify against the repository for newer releases). This is the floor, not the ceiling.
- Set
CODE_EXEC_TYPEexplicitly to an isolated executor (langchainbuilt-in, or E2B) rather than relying on defaults — and audit for any process-level override still pointing atlocal. - Rotate shared service and database credentials if you ran an affected version in multi-tenant mode. The fix closes the entry point; it does not revoke anything already read.
- Audit who could create workflows. Exploitability required workflow creation permissions, so your user-role matrix is part of the exposure assessment. Treat any low-privilege account with that permission on an affected version as a potential execution path.
- Check for unexpected code nodes and container-level anomalies in the window before upgrade — there is no evidence of exploitation, but code execution as root leaves no application-level audit trail worth trusting on its own.
Verification note: we confirmed CVE-2026-108263 against the CVE record (cveawg, state PUBLISHED, reserved 9 October 2026 17:33:15Z, published 20:47:38Z) including the 9.9 CVSS v3.1 vector, CWE-95/306/653 assignments, the < 1.1.2 affected range, the endpoint and file paths, and the six reference URLs, and against NVD (Received, published 21:17:04Z, GitHub-supplied score only). We read code_node.py at tags v1.1.1 and v1.1.2 from the repository first-hand and quote the executor-selection line, the isolated-executor allowlist and the refusal message verbatim. Release timing and the CVE-awaiting-assignment statement come from the v1.1.2 release object (published 7 September 2026 06:43:46Z); PR #1650 metadata (author, title, migration scope) from the GitHub API; star count and project description from the repository record. The CVE record credits no reporter, and we name none. We found no evidence of exploitation and do not imply any, and we did not execute code against any deployment.
Sources:
- GHSA-mh3w-4q3f-2fg5 — “Astron Agent: Unsandboxed code-node leads to cross-tenant RCE” (CVE-2026-108263, 9.9 critical; published 9 October 2026)
- NVD — CVE-2026-108263 (published 9 October 2026; Received at the time of writing)
- Astron Agent v1.1.2 — Security Release (7 September 2026; affected range, executor migration, hardening)
- PR #1650 — “fix(workflow): migrate legacy executor defaults safely”
- core/workflow/engine/nodes/code/code_node.py at v1.1.2 — the isolated-executor gate