Classify plugin permission risk

This commit is contained in:
2026-05-07 22:38:19 -04:00
parent cb3ac30b89
commit 9e6cd216b0
3 changed files with 61 additions and 3 deletions
+2 -2
View File
@@ -21,8 +21,8 @@ pub use error::DomainError;
pub use history::HistoryEntry;
pub use identifiers::{DownloadId, ProfileId, SpaceId, SplitId, TabId, WebViewId};
pub use plugin::{
PluginContributionPoint, PluginId, PluginManifest, PluginPermission, PluginSignature,
PluginSignatureAlgorithm,
PluginContributionPoint, PluginId, PluginManifest, PluginPermission, PluginPermissionRisk,
PluginSignature, PluginSignatureAlgorithm,
};
pub use profile::{Profile, ProfileKind};
pub use space::{ArchivePolicy, Space};
+44
View File
@@ -50,6 +50,12 @@ pub enum PluginPermission {
UiContextMenu,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum PluginPermissionRisk {
Standard,
High,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum PluginContributionPoint {
CommandBarCommand,
@@ -166,6 +172,10 @@ impl PluginManifest {
&self.permissions
}
pub fn high_risk_permissions(&self) -> impl Iterator<Item = &PluginPermission> {
self.permissions.iter().filter(|permission| permission.requires_separate_confirmation())
}
#[must_use]
pub fn contributes(&self) -> &[PluginContributionPoint] {
&self.contributes
@@ -245,6 +255,40 @@ impl PluginPermission {
Self::UiContextMenu => "ui:context_menu",
}
}
#[must_use]
pub fn risk(&self) -> PluginPermissionRisk {
match self {
Self::TabsRead
| Self::SpacesRead
| Self::PageMetadata
| Self::SettingsRead
| Self::UiPanel
| Self::UiCommand
| Self::UiContextMenu => PluginPermissionRisk::Standard,
Self::TabsWrite
| Self::SpacesWrite
| Self::BookmarksRead
| Self::BookmarksWrite
| Self::HistoryRead
| Self::DownloadsRead
| Self::DownloadsWrite
| Self::PageScreenshot
| Self::PageScript
| Self::ClipboardRead
| Self::ClipboardWrite
| Self::FilesystemRead
| Self::FilesystemWrite
| Self::NetworkFetch
| Self::SettingsWrite
| Self::SyncPlugin => PluginPermissionRisk::High,
}
}
#[must_use]
pub fn requires_separate_confirmation(&self) -> bool {
self.risk() == PluginPermissionRisk::High
}
}
impl PluginContributionPoint {
+15 -1
View File
@@ -1,7 +1,7 @@
use std::{error::Error, io};
use ely_domain::{
DomainError, PluginContributionPoint, PluginManifest, PluginPermission,
DomainError, PluginContributionPoint, PluginManifest, PluginPermission, PluginPermissionRisk,
PluginSignatureAlgorithm,
};
@@ -33,6 +33,20 @@ fn parses_signed_plugin_manifest() -> Result<(), Box<dyn Error>> {
Ok(())
}
#[test]
fn classifies_plugin_permission_risk_for_separate_confirmation() -> Result<(), Box<dyn Error>> {
let manifest = PluginManifest::from_toml(valid_manifest().as_str())?;
let high_risk_permissions = manifest.high_risk_permissions().collect::<Vec<_>>();
assert!(high_risk_permissions.is_empty());
assert_eq!(PluginPermission::PageMetadata.risk(), PluginPermissionRisk::Standard);
assert_eq!(PluginPermission::UiCommand.risk(), PluginPermissionRisk::Standard);
assert_eq!(PluginPermission::HistoryRead.risk(), PluginPermissionRisk::High);
assert!(PluginPermission::PageScript.requires_separate_confirmation());
assert!(PluginPermission::FilesystemWrite.requires_separate_confirmation());
Ok(())
}
#[test]
fn rejects_unknown_plugin_permission() -> Result<(), Box<dyn Error>> {
let manifest = valid_manifest().replace("page:metadata", "tabs:admin");