extension_host: Load granted extension capabilities from settings (#39472)

This PR adds the ability to control the capabilities granted to
extensions by the extension host via the new
`granted_extension_capabilities` setting.

This setting is a list of the capabilities granted to any extension
running in Zed.

The currently available capabilities are:

- `process:exec` - Grants extensions the ability to invoke commands
using
[`zed_extension_api::process::Command`](https://docs.rs/zed_extension_api/latest/zed_extension_api/process/struct.Command.html)
- `download_file` - Grants extensions the ability to download files
using
[`zed_extension_api::download_file`](https://docs.rs/zed_extension_api/latest/zed_extension_api/fn.download_file.html)
- `npm:install` - Grants extensions the ability to install npm packages
using
[`zed_extension_api::npm_install_package`](https://docs.rs/zed_extension_api/latest/zed_extension_api/fn.npm_install_package.html)

Each of these capabilities has parameters that can be used to customize
the permissions.

For instance, to only allow downloads from GitHub, the `download_file`
capability can specify an allowed `host`:

```json
[
  { "kind": "download_file", "host": "github.com", "path": ["**"] }
]
```

The same capability can also be granted multiple times with different
parameters to build up an allowlist:

```json
[
  { "kind": "download_file", "host": "github.com", "path": ["**"] },
  { "kind": "download_file", "host": "gitlab.com", "path": ["**"] }
]
```

When an extension is not granted a capability, the associated extension
APIs protected by that capability will fail.

For instance, trying to use `zed_extension_api::download_file` when the
`download_file` capability is not granted will result in an error that
will be surfaced by the extension:

```
Language server phpactor:

from extension "PHP" version 0.4.3: failed to download file: capability for download_file https://github.com/phpactor/phpactor/releases/download/2025.07.25.0/phpactor.phar is not granted by the extension host
```

Release Notes:

- Added a `granted_extension_capabilities` setting to control the
capabilities granted to extensions.
This commit is contained in:
Marshall Bowers
2025-10-03 15:55:01 +00:00
committed by GitHub
parent 456ba32ea7
commit 3bf71c690f
6 changed files with 110 additions and 33 deletions
+2 -15
View File
@@ -1,5 +1,6 @@
mod agent;
mod editor;
mod extension;
mod language;
mod language_model;
mod project;
@@ -9,6 +10,7 @@ mod workspace;
pub use agent::*;
pub use editor::*;
pub use extension::*;
pub use language::*;
pub use language_model::*;
pub use project::*;
@@ -433,21 +435,6 @@ pub struct CallSettingsContent {
pub share_on_join: Option<bool>,
}
#[skip_serializing_none]
#[derive(Deserialize, Serialize, PartialEq, Debug, Default, Clone, JsonSchema, MergeFrom)]
pub struct ExtensionSettingsContent {
/// The extensions that should be automatically installed by Zed.
///
/// This is used to make functionality provided by extensions (e.g., language support)
/// available out-of-the-box.
///
/// Default: { "html": true }
#[serde(default)]
pub auto_install_extensions: HashMap<Arc<str>, bool>,
#[serde(default)]
pub auto_update_extensions: HashMap<Arc<str>, bool>,
}
#[skip_serializing_none]
#[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]
pub struct GitPanelSettingsContent {
@@ -0,0 +1,59 @@
use std::sync::Arc;
use collections::HashMap;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_with::skip_serializing_none;
use settings_macros::MergeFrom;
#[skip_serializing_none]
#[derive(Debug, PartialEq, Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
pub struct ExtensionSettingsContent {
/// The extensions that should be automatically installed by Zed.
///
/// This is used to make functionality provided by extensions (e.g., language support)
/// available out-of-the-box.
///
/// Default: { "html": true }
#[serde(default)]
pub auto_install_extensions: HashMap<Arc<str>, bool>,
#[serde(default)]
pub auto_update_extensions: HashMap<Arc<str>, bool>,
/// The capabilities granted to extensions.
#[serde(default)]
pub granted_extension_capabilities: Option<Vec<ExtensionCapabilityContent>>,
}
/// A capability for an extension.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum ExtensionCapabilityContent {
#[serde(rename = "process:exec")]
ProcessExec(ProcessExecCapabilityContent),
DownloadFile(DownloadFileCapabilityContent),
#[serde(rename = "npm:install")]
NpmInstallPackage(NpmInstallPackageCapabilityContent),
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct ProcessExecCapabilityContent {
/// The command to execute.
pub command: String,
/// The arguments to pass to the command. Use `*` for a single wildcard argument.
/// If the last element is `**`, then any trailing arguments are allowed.
pub args: Vec<String>,
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct DownloadFileCapabilityContent {
pub host: String,
pub path: Vec<String>,
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct NpmInstallPackageCapabilityContent {
pub package: String,
}