OSV 1.4.0 · github-reviewed · 修改于 2026-09-03 06:00
发布时间
2026-09-03 06:00
GitHub 审查时间
2026-09-03 06:00
NVD 发布时间
2026-08-22 02:16
源文件
advisories/github-reviewed/2026/09/GHSA-p8rw-8qj3-hf33/GHSA-p8rw-8qj3-hf33.json
An authenticated, non-admin user can obtain arbitrary host-filesystem read/write (and host environment-secret disclosure) on an Omnigent runner by uploading an agent bundle whose os_env.cwd points outside any intended workspace (e.g. / or /home/<victim>). The cwd field is taken verbatim from the bundle with no validation, normalization, or boundary check anywhere in the spec pipeline.
This is a different sink from GHSA-jrrm-9hc7-2v3h (CWE-94, shared-agent bundle overwrite -> stdio MCP RCE). It shares the bundle-upload vector but is reached through the user's own session-scoped agent and is not addressed by that advisory's proposed shared-agent guard.
OMNIGENT_RUNNER_WORKSPACE set. When that env var is set (CLI- and host-launched sessions set it), the spec cwd is overridden and the attack is neutralized — so this is deployment-gated, not universal._require_user only checks identity). No shared-agent overwrite needed.omnigent/spec/parser.py:696 stores cwd=str(cwd_raw) verbatim. Absolute paths (/, /etc), ../.., etc. are all accepted. The sandbox.type is likewise author-chosen and "none" is legal.omnigent/spec/validator.py _validate_os_env checks only fork/scratch/egress combinations; it never references cwd (the sole mention, line ~526, is a comment). No boundary is applied to the cwd itself. The boundary in server/schemas.py validates a caller-supplied workspace against the spec cwd (treating the author cwd as trusted) and only for host-launched sessions — it does not bound the cwd.omnigent/inner/os_env.py:890 sets cwd = Path(spec.cwd or os.getcwd()).resolve(strict=False) as the environment root; os_env.py:934 does shutil.copytree(src=cwd, ...) when fork=true. All agent file/shell tools are bounded by _assert_within_cwd (os_env.py:1040), which checks resolved.relative_to(cwd) — but since cwd is attacker-controlled, cwd=/ makes the entire host filesystem in-bounds for read and write; fork=true with cwd=/home/victim copies that tree into the agent-readable workspace.omnigent/runner/resource_registry.py:648-654: cwd = default_cwd only when self._runner_workspace is not None or spec_os_env.cwd in (None, ".", "./"); otherwise cwd = spec_os_env.cwd (the attacker's absolute path). So OMNIGENT_RUNNER_WORKSPACE is the only thing standing between the spec and the host FS — and it is an operational control, not an in-code guard. A code comment at tool_dispatch.py:~4207 claims cwd "is treated as a boundary at session-create time," which is not true on this path.POST /v1/sessions (multipart) with an agent bundle whose config.yaml contains:
os_env:
cwd: "/" # or /home/<victim>, with fork: true for one-shot exfil
sandbox: { type: none }
OMNIGENT_RUNNER_WORKSPACE, the agent's sys_os_read/write/edit/shell tools now operate over the whole host filesystem, and (sandbox inactive) inherit the runner's full environment — exposing host secrets via e.g. sys_os_shell("env").Arbitrary host-filesystem read/write and runner-environment secret disclosure, available to any authenticated user on an affected deployment. High severity (deployment-conditional).
Add a control on the cwd field itself in omnigent/spec/_validate_os_env (and/or at parse): reject absolute paths and .. traversal, and require cwd to resolve within the runner workspace / an allow-listed root. Do not rely on OMNIGENT_RUNNER_WORKSPACE being set as the sole defense. Consider also disallowing bundle-author sandbox.type: none for server-realized (non-CLI) sessions.
GHSA-jrrm-9hc7-2v3h (same bundle-upload vector, different sink; that fix does not cover this).