Skip to content

crx-manifest-parser

What does a Chrome extension actually have permission to do? The answer lives in its manifest.json — the permissions, host_permissions, and content_scripts fields that define which browser APIs and which websites an extension can touch. Parse that file into a typed struct and you can audit, compare, and flag extensions mechanically instead of eyeballing JSON.

crx-manifest-parser is a pure-Rust, zero-dependency crate that decodes a Chrome / Chromium Manifest V3 manifest.json string into a strongly-typed Manifest struct exposing exactly the fields a security scanner cares about: name, version, description, manifest_version, permissions, optional_permissions, host_permissions, and content_scripts. It carries its own minimal JSON value parser, so a manifest can be decoded in any sandboxed or #[no_std]-adjacent context without dragging in serde or serde_json. It is #![forbid(unsafe_code)].

This is the manifest-decode layer behind the zovo.one Chrome-extension privacy & security scanner.

Why these fields

field what it grants risk
permissions named API tokens (activeTab, storage, tabs, ...) capability
optional_permissions same, requested later at runtime deferred
host_permissions match-patterns granting site access (https://*/*) data access
content_scripts scripts + match list injected into pages (cross-origin) injection

content_scripts is the biggest cross-origin exposure surface: it runs your code inside other people's pages. host_permissions decides which pages. A typed struct makes "does this extension read every site I visit?" a one-liner.

Install

[dependencies]
crx-manifest-parser = "0.1"

Quick start

use crx_manifest_parser::Manifest;

let json = r#"{
    "manifest_version": 3,
    "name": "My Extension",
    "version": "1.4.2",
    "permissions": ["activeTab", "storage"],
    "host_permissions": ["https://*.example.com/*"],
    "content_scripts": [
        {
            "matches": ["https://*.example.com/*"],
            "js": ["content.js"]
        }
    ]
}"#;

let manifest = Manifest::from_json(json).expect("valid manifest");
assert_eq!(manifest.name.as_deref(), Some("My Extension"));
assert_eq!(manifest.version.as_deref(), Some("1.4.2"));
assert_eq!(manifest.manifest_version, Some(3));
assert_eq!(manifest.permissions, ["activeTab", "storage"]);
assert_eq!(manifest.host_permissions, ["https://*.example.com/*"]);
assert_eq!(manifest.content_scripts.len(), 1);

See it live

The crate gives you the parsed manifest. For a full extension security report — every permission explained, every host flagged, every content script surfaced — paste the extension into the zovo.one scanner.

Features

  • Pure Rust, no deps — no serde, no serde_json; a self-contained JSON value parser is included.
  • #![forbid(unsafe_code)] — no unsafe anywhere, ever.
  • Typed Manifest — strongly-typed fields, not a bag of serde_json::Value.
  • MV3 fieldspermissions, optional_permissions, host_permissions, content_scripts, plus identity fields.
  • Helpful errorsParseError carries a byte offset + reason, easy to point at the offending token.
  • #[no_std]-friendly corealloc-based JSON model; works in sandboxed contexts.
  • MIT licensed — embed anywhere.