{"record":{"id":"b16e5b66fac3c333","repo":"zed-industries/zed","slug":"capability-for-process-exec-desired-command-des-b16e5b","errorCode":null,"errorMessage":"capability for process:exec {desired_command} {desired_args:?} is not granted by the extension host","messagePattern":"capability for process:exec (.+?) (.+?) is not granted by the extension host","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/extension_host/src/capability_granter.rs","lineNumber":41,"sourceCode":"    pub fn grant_exec(\n        &self,\n        desired_command: &str,\n        desired_args: &[impl AsRef<str> + std::fmt::Debug],\n    ) -> Result<()> {\n        self.manifest.allow_exec(desired_command, desired_args)?;\n\n        let is_allowed = self\n            .granted_capabilities\n            .iter()\n            .any(|capability| match capability {\n                ExtensionCapability::ProcessExec(capability) => {\n                    capability.allows(desired_command, desired_args)\n                }\n                _ => false,\n            });\n\n        if !is_allowed {\n            bail!(\n                \"capability for process:exec {desired_command} {desired_args:?} is not granted by the extension host\",\n            );\n        }\n\n        Ok(())\n    }\n\n    pub fn grant_download_file(&self, desired_url: &Url) -> Result<()> {\n        let is_allowed = self\n            .granted_capabilities\n            .iter()\n            .any(|capability| match capability {\n                ExtensionCapability::DownloadFile(capability) => capability.allows(desired_url),\n                _ => false,\n            });\n\n        if !is_allowed {\n            bail!(","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/extension_host/src/capability_granter.rs#L23-L59","documentation":"The extension host mediates every process a WASM extension wants to spawn through CapabilityGranter::grant_process_exec. It only allows the call if some `process:exec` capability declared in the extension manifest matches the exact desired command and arguments (per ProcessExecCapability::allows: command must match exactly or be `*`; args must match element-wise, where `*` is a single-arg wildcard and a trailing `**` permits any remaining args). Otherwise it bails with the requested command and args.","triggerScenarios":"Extension code invokes a subprocess (e.g. exec of `git status`) while extension.toml has no [[capabilities]] entry with kind = \"process:exec\", or the declared args no longer match because the code now passes different flags or more arguments than the manifest allows.","commonSituations":"Adding a new subprocess call or an extra flag to an existing one without updating the manifest allowlist; switching from exact args to variadic args without a trailing \"**\"; re-publishing an old extension against a host that started enforcing capabilities.","solutions":["Add a matching entry to extension.toml: [[capabilities]] kind = \"process:exec\" with the exact command and args shown in the error message.","Use \"*\" for one wildcard argument and a trailing \"**\" only when the command legitimately takes arbitrary trailing arguments.","Rebuild and reinstall/re-test the extension (`zed extension test`) so the updated manifest is loaded."],"exampleFix":"# before: extension.toml has no capabilities section\n\n# after\n[[capabilities]]\nkind = \"process:exec\"\ncommand = \"git\"\nargs = [\"status\", \"**\"]","handlingStrategy":"validation","validationCode":"fn process_exec_allowed(\n    manifest: &ExtensionManifest,\n    desired_command: &str,\n    desired_args: &[&str],\n) -> bool {\n    manifest.capabilities.iter().any(|capability| match capability {\n        ExtensionCapability::ProcessExec(capability) => {\n            capability.allows(desired_command, desired_args)\n        }\n        _ => false,\n    })\n}\n\n// before spawning from extension code\nassert!(process_exec_allowed(&manifest, \"git\", &[\"status\", \"-s\"]),\n    \"add a process:exec capability to extension.toml first\");","typeGuard":"fn is_process_exec_capable(capability: &ExtensionCapability) -> bool {\n    matches!(capability, ExtensionCapability::ProcessExec(_))\n}","tryCatchPattern":null,"preventionTips":["Declare the narrowest args pattern that works; add a trailing \"**\" only for truly variadic commands.","Re-run `zed extension test` after every change to subprocess calls or the capabilities list.","Keep a test that exercises each subprocess call so a manifest regression fails in CI, not in production."],"tags":["security","capability","extension","process-exec","manifest"],"backgroundTag":"permission-denied-capability","analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}