Skip to content

ext-permission-risk

How risky is that browser extension, really? A Chrome extension's manifest.json requests a list of permissionstabs, cookies, <all_urls>, and dozens more. Each one is a small contract: what is the extension allowed to see and do? Two extensions that both claim to "customize your new tab page" can request wildly different access. The permission string is the single best signal for whether an extension is safe to install.

ext-permission-risk is a pure-Rust, zero-dependency crate that maps every common Manifest V3 permission string to a risk levelLow, Medium, or High — together with a short, plain-English explanation of what that permission actually grants. It is the permission-classification table behind the zovo.one Chrome-extension privacy & security scanner, which audits the permissions of any installed extension and flags the ones that can read your data across every site.

The three risk tiers

Level Meaning Examples
LOW No persistent broad access. Scoped to an explicit user gesture or confined to the extension's own sandbox. activeTab, storage, alarms, notifications
MEDIUM Sensitive. Grants meaningful read/write access — history, downloads, per-site host permissions, the clipboard — but is not a blanket global grant. tabs, history, bookmarks, clipboardRead, scoped host patterns
HIGH Broad, persistent, cross-origin or sensitive-system access. Treat any extension requesting these as needing careful review. <all_urls>, cookies, webRequest, debugger, nativeMessaging, scripting

Why a curated table

Permissions evolve with each Chrome release, and the risk of a given token depends on what it grants combined with the extension's host access. activeTab + storage is a safe, common pairing; cookies + <all_urls> + webRequest lets an extension read every password you type on every site, forever. This crate encodes those distinctions so a scanner doesn't have to re-derive them — and so the same classification logic is available to any Rust tool that wants it.

Install

[dependencies]
ext-permission-risk = "0.1"

Quick start

use ext_permission_risk::{risk_of, highest_risk, RiskLevel};

// Named token lookup.
let cookies = risk_of("cookies").unwrap();
assert_eq!(cookies.level, RiskLevel::High);

// activeTab is the least-privileged tab-access alternative.
assert_eq!(risk_of("activeTab").unwrap().level, RiskLevel::Low);

// The single highest risk across a whole manifest.
let overall = highest_risk(&["activeTab", "storage", "cookies", "tabs"]);
assert_eq!(overall, Some(RiskLevel::High));

See the API Reference for the full function list, the Risk Table for every curated permission, and Examples for end-to-end manifest-scanning patterns.

Design choices

  • Unknown ≠ High. A token not in the table is surfaced as unclassified, never silently escalated to High. False alarms erode trust.
  • Host patterns are Medium, <all_urls> is High. A scoped *://*.example.com/* grants access to one domain family and is meaningfully less broad than blanket access to the entire web.
  • unsafe_code is forbidden. The crate compiles with #![forbid(unsafe_code)] — no unsafe anywhere in the dependency tree.