| Titel | cosmicstack-labs mercury-agent <= 1.2.0 Exposure of Sensitive Information to an Unauthorized Actor (CWE-200) |
|---|
| Beschreibung | # Technical Details
A `run_command` safe-read approval bypass exists in the `checkShellCommand()` method in `mercury-agent/src/capabilities/permissions.ts` of Mercury Agent (npm package `@cosmicstack/mercury-agent`).
The shell permission manifest auto-approves `'wc *'` (permissions.ts#L94), and the approval check accepts any command matching an auto-approved pattern without modeling `wc --files0-from` semantics: `for (const pattern of shell.autoApproved) { if (this.matchPattern(trimmed, pattern)) { ... return { allowed: true, needsApproval: false }; } }` (permissions.ts#L327-L330). Mercury's path containment check (`hasPathBeyondCwd()`, permissions.ts#L448-L465) only scans literal path tokens already present in the command string, so it never inspects paths that the program itself will dereference later. Consequently `wc --files0-from=list0.bin` is approved as a safe `wc` invocation even when `list0.bin` (inside the workspace) contains a NUL-separated absolute path to a file outside the workspace; the out-of-scope file is read at execution time through the standard shell sink (`execSync(command, { cwd, timeout: 30000, maxBuffer: 1024*1024, encoding: 'utf-8', stdio: ['pipe','pipe','pipe'] })`, run-command.ts#L19-L40). Verified against the real exported `CapabilityRegistry` with the production `run_command` tool and real `PermissionManager`: the control `wc /abs/path/to/secret` triggers the path gate and is denied (`No permission to access ...`, prompt count 1), while `wc --files0-from=list0.bin` triggers no approval (prompt count 0) and returns counts for the out-of-scope target file (`1 4 42 .../outside-secret/wc-secret-canary.txt`), classified `[VULNERABLE-PATH-REPRODUCED]`.
# Vulnerable Code
File: mercury-agent/src/capabilities/permissions.ts (lines 94, 317-330, 448-465); sink in mercury-agent/src/capabilities/shell/run-command.ts (lines 19-40)
Method: PermissionManager.checkShellCommand() / hasPathBeyondCwd() / run_command
Why: The default auto-approval list whitelists `wc *` and accepts any matching string without modeling `--files0-from` semantics; `hasPathBeyondCwd()` only searches for explicit path tokens already present in the command, so it cannot see paths later dereferenced from the NUL-separated list file, and the command is then executed through the real shell sink.
# Reproduction
1. Use a Mercury source checkout of `cosmicstack-labs/mercury-agent` with Node.js dependencies installed (so `node_modules/.bin/vite-node` is available); no external services required (PoC uses an isolated exp directory and dedicated `MERCURY_HOME`).
2. Download the verification script `verification_test.py` (https://gist.github.com/YLChen-007/fe90a0ddd30ed25da7f84490871e9bee), the control script `control-direct-path.py` (https://gist.github.com/YLChen-007/28fc48f4f32fa6e21655d19701f2e7bd), the shared harness `experiment_common.py` (https://gist.github.com/YLChen-007/9daa07aece6ca7ac63555ef0011eff15), and the probe `tool_dispatch_probe.ts` (https://gist.github.com/YLChen-007/43a6beeaf7d81f5ff252cdf7e692471d).
3. From the repository root run the control path: `python3 .../control-direct-path.py` — confirm `Prompt count: 1` and an error containing `No permission to access`.
4. Run the vulnerable path: `python3 .../verification_test.py` — the harness creates a workspace-local `list0.bin` containing a NUL-separated absolute path to an out-of-scope secret file and issues `wc --files0-from=list0.bin`.
5. Confirm the vulnerable result shows `Prompt count: 0` and returns `1 4 42 .../outside-secret/wc-secret-canary.txt` (parsed wc tuple (1, 4, 42) matching the expected tuple).
# Impact
- Approval-bypass and information disclosure in Mercury's shell safety model: any actor reaching the standard `run_command` path can turn approval-gated out-of-scope file access into approval-free metadata disclosure.
- Discloses file existence, absolute path, line count, word count, and byte count for files readable by the Mercury process but outside the current approved workspace.
- Weakens the advertised Ask Me boundary and demonstrates that other "safe" commands with file-indirection flags may be similarly misclassified.
- Severity Medium, CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N. |
|---|
| Quelle | ⚠️ https://github.com/cosmicstack-labs/mercury-agent/issues/102 |
|---|
| Benutzer | Eric-a (UID 96353) |
|---|
| Einreichung | 11.08.2026 15:07 (vor 1 Monat) |
|---|
| Moderieren | 13.09.2026 18:30 (1 month later) |
|---|
| Status | Akzeptiert |
|---|
| VulDB Eintrag | 403313 [cosmicstack-labs mercury-agent bis 1.2.0 Shell Permission Manifest permissions.ts PermissionManager.checkShellCommand Information Disclosure] |
|---|
| Punkte | 20 |
|---|