permission-auditor 0.1.0

Audit a list of Chrome / Manifest V3 extension permissions against a curated risk database: every MV3 permission + host-access patterns + plain-English risk descriptions, summarized into a per-extension report. Powers the zovo.one extension security scanner.
Documentation
  • Coverage
  • 100%
    38 out of 38 items documented5 out of 5 items with examples
  • Size
  • Source code size: 57.18 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 817.68 kB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 3s Average build duration of successful builds.
  • all releases: 3s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Homepage
  • Repository
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • theluckystrike

permission-auditor

crates.io docs

Audit a list of Chrome / Manifest V3 extension permissions against a curated risk database and produce a structured per-extension report:

  • a risk level (Low / Medium / High / Critical) for each permission, plus a short plain-English description of what it grants,
  • recognition for host-access patterns (<all_urls>, scheme wildcards, scoped match-patterns) and broad-vs-scoped classification,
  • an overall verdict for the whole extension, with the count of each severity and escalation to Critical for the canonical spyware capability set (arbitrary host access + code injection / cookie access).

Pure Rust, zero dependencies, #![forbid(unsafe_code)], fully tested.

This is the audit engine behind the zovo.one Chrome-extension privacy & security scanner. It is a more comprehensive companion to ext-permission-risk: it covers the full MV3 permission surface, adds a Critical tier for the truly dangerous combinations, and returns a structured report rather than a single lookup.

Why audit permissions

The permission list in an extension's manifest.json is the single best signal for whether it is safe to install. Two extensions that both "just change your new tab page" can request wildly different access: one asks for storage, the other for <all_urls> + cookies + scripting. The latter can read every password you type, on every site, forever. This crate turns that signal into a labelled, countable, explainable report — the input a scanner UI renders to a user before they install.

Install

[dependencies]
permission-auditor = "0.1"

Quick start

use permission_auditor::{audit, RiskLevel};

// A canonical surveillance-set manifest.
let report = audit(&[
    "activeTab",
    "storage",
    "tabs",
    "<all_urls>",
    "scripting",
    "cookies",
]);

// activeTab + storage are Low; tabs is Medium; <all_urls> is Critical;
// scripting + cookies are High. The broad-host + code combo escalates to Critical.
assert_eq!(report.overall, RiskLevel::Critical);
assert!(report.critical_count >= 1);
assert_eq!(report.findings.len(), 6);

println!("{}", report.summary());
// "CRITICAL overall (1 critical, 2 high, 1 medium, 2 low)"

// The "what should I worry about" view.
let worry = report.findings_at_or_above(RiskLevel::High);
assert!(worry.iter().any(|f| f.token == "<all_urls>"));

A benign manifest stays Low:

use permission_auditor::{audit, RiskLevel};
let r = audit(&["activeTab", "storage", "sidePanel"]);
assert_eq!(r.overall, RiskLevel::Low);

API surface

Item Description
audit(permissions) Audit an iterable of permission tokens into an AuditReport.
audit_with_manifest_version(permissions, mv) Same, recording the manifest version on the report.
AuditReport { findings, overall, critical_count, high_count, medium_count, low_count, manifest_version }.
AuditReport::summary() One-line CRITICAL overall (1 critical, 2 high, ...) string.
AuditReport::findings_at_or_above(level) Findings at or above a severity, for a "what to worry about" view.
Finding { token, level, description, kind } — one audited permission.
FindingKind Known (in DB) / HostPattern (synthesised) / Unknown.
RiskLevel Low / Medium / High / Critical, ordered and comparable.
find_permission(token) Direct database lookup; None if unknown.
RISK_DATABASE The static &[PermissionEntry] constant (60+ MV3 tokens).
classify_host_pattern(token) Structural scope of a host pattern: All / Scheme / Scoped / Unknown.
is_host_access_pattern(token) Heuristic: does this look like a host match-pattern?

How classification works

For each token, in order:

  1. Named database hit — the entry's level + description are used directly.
  2. Host match-pattern — its [HostScope] is classified: blanket (<all_urls>, *://*/*) and scheme-wide (https://*/*, file:///*) patterns are Critical; a scoped per-site pattern (*://*.example.com/*) is Medium.
  3. Unknown token — surfaced as a Low Unknown finding with a "review manually" note. Unknown tokens are never silently escalated.

The overall report level is the highest finding's level, with one escalation rule: an extension requesting any blanket host access together with scripting, debugger, cookies, or webRequest is the canonical spyware capability set and is escalated to Critical regardless of how the individual tokens classified.

Design choices

  • Unknown ≠ Critical. A token not in the database is surfaced as unclassified (Low, "review manually"), never silently escalated. False alarms erode trust; the scanner tells you what it knows.
  • Four tiers, not three. A separate Critical tier keeps the truly dangerous grants (every site, native process, total tab control) distinct from merely "high" ones (history, bookmarks), so a UI can render them differently.
  • Combination awareness. <all_urls> alone is bad; <all_urls> + scripting + cookies is the full surveillance tool. The auditor recognises the combination and escalates accordingly.
  • Comprehensive MV3 coverage. 60+ named tokens — every permission in the Chrome Extensions reference plus the host-access pattern tokens.
  • Zero dependencies, no unsafe. #![forbid(unsafe_code)]; nothing added to the build graph.

License

MIT.

Links