Skip to content

API Reference

ext-permission-risk exposes one enum, one struct, a curated static table, and a handful of free functions. All inputs are &str; outputs borrow into the static table where possible. No traits, no features, no macros to enable.

RiskLevel

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum RiskLevel {
    Low,
    Medium,
    High,
}

The three-tier classification used by the zovo.one scanner. Ordered Low < Medium < High, so it can be compared and used with max when an extension requests several permissions.

use ext_permission_risk::RiskLevel;

assert!(RiskLevel::Low < RiskLevel::Medium);
assert!(RiskLevel::Medium < RiskLevel::High);

// `.label()` returns an uppercase string for badges / UI chips.
assert_eq!(RiskLevel::High.label(), "HIGH");

RiskLevel::label

pub fn label(self) -> &'static str

A short uppercase label — "LOW", "MEDIUM", "HIGH".

PermissionRisk

pub struct PermissionRisk {
    pub permission: &'static str,
    pub level: RiskLevel,
    pub description: &'static str,
}

One row of the curated table: the manifest permission token exactly as it appears in permissions / host_permissions, its risk level, and a concise plain-English explanation of what it grants.

PERMISSION_TABLE

pub const PERMISSION_TABLE: &[PermissionRisk];

The full static table. See the Risk Table page for the rendered contents.

risk_of

pub fn risk_of(permission: &str) -> Option<&'static PermissionRisk>;

Look up a single named permission string. Returns None for tokens not in the curated table — unknown permissions are reported as unknown, never silently classified as High.

use ext_permission_risk::{risk_of, RiskLevel};

let tabs = risk_of("tabs").unwrap();
assert_eq!(tabs.level, RiskLevel::Medium);

let all = risk_of("<all_urls>").unwrap();
assert_eq!(all.level, RiskLevel::High);

assert!(risk_of("not-a-real-permission").is_none());

risk_of_or_pattern

pub fn risk_of_or_pattern(token: &str) -> PermissionRisk;

Classify a single manifest entry, recognising host match-patterns in addition to named tokens.

  • Known named tokens → looked up directly (same as risk_of).
  • A *://..., https://..., or file://... match pattern → classified as Medium (site-scoped host access).
  • Anything else → Low with an "unclassified, review manually" description.
use ext_permission_risk::{risk_of_or_pattern, RiskLevel};

let cookies = risk_of_or_pattern("cookies");
assert_eq!(cookies.level, RiskLevel::High);

let scoped = risk_of_or_pattern("https://*.example.com/*");
assert_eq!(scoped.level, RiskLevel::Medium);

is_host_pattern

pub fn is_host_pattern(token: &str) -> bool;

Heuristic: does token look like a Manifest V3 host match-pattern (scheme://...) rather than a named permission token?

use ext_permission_risk::is_host_pattern;

assert!(is_host_pattern("https://*.example.com/*"));
assert!(is_host_pattern("*://*/*"));
assert!(is_host_pattern("file:///*"));
assert!(!is_host_pattern("tabs"));
assert!(!is_host_pattern("<all_urls>")); // named token, not a pattern

highest_risk

pub fn highest_risk<I, S>(permissions: I) -> Option<RiskLevel>
where
    I: IntoIterator<Item = S>,
    S: AsRef<str>;

The single highest risk level among a list of manifest permission tokens. Accepts any iterable of string-like items (&[&str], Vec<&str>, an array). Unknown tokens are ignored; returns None if nothing is recognised.

use ext_permission_risk::{highest_risk, RiskLevel};

assert_eq!(highest_risk(&["activeTab", "storage", "cookies"]), Some(RiskLevel::High));
assert_eq!(highest_risk(&["activeTab", "storage"]), Some(RiskLevel::Low));
assert_eq!(highest_risk(&["???"]), None);

all_permissions

pub fn all_permissions() -> &'static [PermissionRisk];

Borrowed slice over the full curated table — useful for rendering a complete reference page or auditing every known permission.

use ext_permission_risk::all_permissions;

let table = all_permissions();
assert!(table.iter().any(|p| p.permission == "tabs"));
assert!(table.iter().any(|p| p.permission == "cookies"));