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
# permission-auditor

[![crates.io](https://img.shields.io/crates/v/permission-auditor.svg)](https://crates.io/crates/permission-auditor)
[![docs](https://docs.rs/permission-auditor/badge.svg)](https://docs.rs/permission-auditor)

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**](https://zovo.one/)
Chrome-extension privacy &amp; security scanner. It is a more comprehensive
companion to [`ext-permission-risk`](https://crates.io/crates/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

```toml
[dependencies]
permission-auditor = "0.1"
```

## Quick start

```rust
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:

```rust
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

- **zovo.one** — the Chrome-extension privacy &amp; security scanner powered
  by this engine: <https://zovo.one/>
- Source (zovo monorepo): <https://github.com/theluckystrike/zovo>
- Full API docs: <https://docs.rs/permission-auditor>