{"record":{"id":"3241d0e5ed6b0e57","repo":"Hmbown/CodeWhale","slug":"reviewed-plugin-stdio-cwd-escaped-its-staged-root","errorCode":null,"errorMessage":"reviewed plugin stdio cwd escaped its staged root","messagePattern":"reviewed plugin stdio cwd escaped its staged root","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/mcp.rs","lineNumber":701,"sourceCode":"            if path.is_absolute() && path.starts_with(staged_root) && path.is_file() {\n                launch.args[index] = launch.bind_file(staged_root, path, &validated.file_hashes)?;\n            }\n        }\n        #[cfg(target_os = \"macos\")]\n        if is_node_command(command) {\n            let entry_index = args.iter().position(|argument| {\n                let path = Path::new(argument);\n                path.is_absolute()\n                    && path.starts_with(staged_root)\n                    && path.extension().is_some_and(|extension| extension == \"mjs\")\n            });\n            if let Some(entry_index) = entry_index {\n                launch.args = node_esm_descriptor_args(&launch.args, entry_index);\n            }\n        }\n        if let Some(cwd) = cwd {\n            if !cwd.starts_with(staged_root) {\n                anyhow::bail!(\"reviewed plugin stdio cwd escaped its staged root\");\n            }\n            launch.bind_cwd(cwd)?;\n        }\n        // A final authority pass detects any non-executed companion/config\n        // drift while handles were opened. Execution itself uses the handles.\n        self.validate_before_stdio_spawn(server_name)?;\n        Ok(launch)\n    }\n\n    fn required_capability(&self) -> crate::plugins::activation::PluginActivationCapability {\n        if self.approved_remote_endpoint.is_some() {\n            crate::plugins::activation::PluginActivationCapability::McpRemote\n        } else {\n            crate::plugins::activation::PluginActivationCapability::McpStdio\n        }\n    }\n\n    fn validate_before_use(&self, server_name: &str, operation: &str) -> Result<()> {","sourceCodeStart":683,"sourceCodeEnd":719,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/mcp.rs#L683-L719","documentation":"For stdio MCP servers contributed by a reviewed plugin, any configured working directory must live inside the plugin's staged root; the launch is refused when the cwd does not start with the staged-root prefix. This keeps plugin-launched processes from executing with a working directory outside the reviewed sandbox.","triggerScenarios":"A plugin manifest or server config sets cwd to a project, home, or any directory outside the stage; a relative cwd that does not lexically start with the absolute staged-root prefix; symlinks making the configured path fall outside the prefix.","commonSituations":"Plugins written for older layouts that assumed arbitrary cwd, manifest templates reusing a user workspace path, tools that need repo-relative execution but were packaged as reviewed plugins.","solutions":["Set the plugin server's cwd to a directory inside its stage root, or omit cwd entirely","If the tool genuinely needs another working directory, run it as a user-configured MCP server instead of through the plugin","Re-release the plugin with a compliant manifest and redo review/enable"],"exampleFix":"// before (plugin manifest): cwd outside the stage\n{ \"command\": \"node\", \"args\": [\"server.mjs\"], \"cwd\": \"/home/me/project\" }\n// after: omit cwd, or point it inside the staged root\n{ \"command\": \"node\", \"args\": [\"server.mjs\"] }","handlingStrategy":"validation","validationCode":"// Validate a configured cwd against the stage root before launch\nfn cwd_within(stage_root: &std::path::Path, cwd: Option<&std::path::Path>) -> bool {\n    cwd.map_or(true, |c| c.starts_with(stage_root))\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Design plugin MCP servers to be cwd-independent; resolve paths from argv or env","Never accept user absolute paths as a plugin-provided cwd","Test plugins against the stage-root layout before review","Use user-level MCP config for tools that must run outside the stage"],"tags":["plugin","mcp","security","sandbox","cwd"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}