MacCrabRave
Documentation

Submit a plugin

How to publish your own forensic plugin to the MacCrab Rave catalog

The MacCrab Rave catalog lists vetted forensic plugins that MacCrab installs and runs under Apple’s App Sandbox. If you’ve built a collector or analyzer that fits the platform, this is the path to get it listed.

Status

ChannelWhat lives hereOpen for submissions?
officialFirst-party plugins built and signed by the MacCrab team. (MacCrab also ships with built-in forensic collectors compiled into the app — those are part of the app, not catalog entries.)No
contribThird-party plugins from independent authors. Same App Sandbox, same Ed25519 signing requirements, listed in the catalog after vetting.Open — owner-reviewed

The contrib channel is open: submit a plugin and it opens an owner-reviewed vetting pull request. Nothing publishes until it passes vetting and the catalog is re-signed. The flow below is what to expect.

The submission flow

1 · Build to the platform spec

Your plugin must conform to the sandboxed plugin format:

  • A signed binary (Ed25519, your publisher key)
  • A manifest.json declaring every capability the binary uses
  • A reproducible build from public source
  • Runs to completion in a few seconds; emits structured records (NDJSON over stdout)

The fastest start is to copy the reference plugin (com.example.maccrab.login-items-lite) — a minimal, reproducible, least-privilege collector that already passes every vetting gate; swap in your own logic. The official com.maccrab.forensics.* plugins in the catalog are also good models.

Build your release with the catalog’s pinned toolchain. Stage 3 rebuilds your source on a hosted macOS runner with a fixed Xcode and compares the canonical hash to your published artifact. A binary built with a different Swift/Xcode won’t byte-match — the reproducibility gate fails even when your source is identical. Build (and cut your release) with the same Xcode the vetter pins, or your submission can’t be verified.

2 · Self-vet locally

Run the same checks the catalog runs:

# 1. Schema-validate your manifest (fetch the published schema first)
curl -o manifest-schema.json https://rave.maccrab.com/schemas/manifest.json
python3 -c "import json, jsonschema; \
  jsonschema.validate(json.load(open('manifest.json')), \
                      json.load(open('manifest-schema.json')))"

# 2. Confirm your local install + verify succeeds
maccrabctl plugin install ./dist/<your-plugin-id>

# 3. Confirm reproducible build
./scripts/build.sh    # first build
./scripts/build.sh    # second build — same canonical hash

If any of these fail locally, the catalog vetter will catch the same problem — fix before submitting.

3 · Submit through the in-site form

Submission opens with the contrib channel. When it lands, you submit through an authenticated form on this site: sign in with GitHub, and it opens a vetting pull request against the catalog on your behalf — no hand-filed issues. The form collects:

FieldWhy we ask
Plugin id (reverse-DNS, e.g. com.example.myorg.disk-walker)Must not collide with an existing entry
Source repository URLPublic GitHub repo. We clone it to verify reproducibility.
Release tag + canonical hashPins the exact bytes you’re submitting
Capability declarationsWhat TCC permissions, file paths, network endpoints your plugin needs
What it doesOne paragraph for the catalog detail page
What it readsHuman-readable list of files/databases
What it emitsContent type IDs and one-line per-type descriptions
Author identityBecomes signer_identity in the catalog entry (e.g. github:your-handle)
Security contactWhere to route disclosures
Maintenance commitmentBus-factor + response-time expectations

4 · Vetting

Every submission goes through three gates:

Automated checks

  • Manifest validates against schema v1
  • Ed25519 signature verifies against your declared publisher key
  • Publisher key not on the revocation list
  • Reproducible rebuild from declared source matches the canonical tree hash
  • Capability declarations match observed binary behaviour

Human review

  • Code-read for hidden capability bypasses (paths constructed at runtime, dynamic execve, dylib injection)
  • Sanity-check on author identity + signer_identity
  • Project-fit: is this a collector or analyzer, or does it fit some other tier we don’t have yet?

Catalog landing

  • A PR adds your plugin’s catalog entry at rave/catalog/<plugin-id>.json with pinned digests, vetting timestamp, and the policy commit it was vetted against
  • The PR is signed by the maccrab-rave project key
  • Lands in the next deploy of the catalog

A typical end-to-end window for a clean submission is 3–7 days.

What can be a plugin

MacCrab forensic plugins fall into two roles:

Collectors

Snapshot a part of the system into structured records. For example, a collector might capture:

  • every privacy-permission (TCC) grant
  • every launch agent + daemon
  • Safari history, downloads, and extensions
  • iMessage handles + threads (metadata only, no bodies)

A new collector should pick a specific data source — a file, a database, a system service — and emit one record per item found. The first-party com.maccrab.forensics.posture-pro is a worked example of a collector.

Analyzers

Cross-reference records that other plugins already collected, and surface patterns. For example, an analyzer might:

  • flag unsigned persistence + unfamiliar-team automation by correlating multiple collectors’ output

Analyzers don’t read the filesystem directly. They read other plugins’ committed artifacts in the same case.

Out of scope

Plugins that try to:

  • Modify system state (write to anywhere outside MacCrab’s case dir)
  • Make outbound network connections
  • Spawn subprocesses
  • Hold privileges the binary doesn’t declare in its manifest

…will be rejected. The App Sandbox refuses them at runtime anyway, but the catalog enforces declarative consistency at vetting time.

Capability policy

The vetting policy is canonical, but as a rough guide:

CapabilityDefault reception
Read /etc, /Library/LaunchAgents, similar system-config pathsAccepted
Read user-content paths (~/Documents, ~/Downloads)Needs explicit justification — what files specifically and why
Write anywhereHigh bar — plugins shouldn’t normally write outside MacCrab’s case dir
Outbound network (allowlisted)Accepted with an explicit allowlist; refused for wildcard
Process execHigh bar — must be a specific path with specific args
Process forkRefused outside the platform’s own sandbox spawn primitives
Mach service connectHigh bar — must be a specific service with stated purpose

A plugin that asks for the minimum needed gets vetted faster.

Channel promotion: contribofficial

contrib plugins are perfectly installable and run under the same sandbox as official plugins. The badge difference just affects sort order in the catalog browser.

To get promoted to official:

  • 90 days in contrib with no reported issues
  • An update cycle through the catalog (you’ve shipped a v0.2.x at least)
  • A second human reviewer agreeing on capability-fit
  • Adoption signal (community usage)

Namespace review

com.maccrab.* is reserved for first-party plugins and a contrib submission claiming it is hard-rejected — that rule does not change. Separately, if your plugin id’s vendor label is confusingly close to the MacCrab brand (a misspelling like com.maccreb.*, or a brand-plus-suffix like com.maccrab-tools.*), the submission is accepted and carries a soft needs_namespace_review triage flag.

This flag is not a rejection. It only force-routes the submission to manual owner review — a namespace-flagged submission is never auto-merged, regardless of diff size. From there:

  • A flagged author proceeds via owner review and appeal — if your vendor is legitimately distinct, contact the owner with the context.
  • If you are a genuinely distinct vendor, pick a clearly distinct vendor label so your id reads as your own brand rather than a lookalike of MacCrab’s.

If a submission gets rejected

You’ll get the reason in your submission’s review thread. Common ones:

  • Reproducibility fails — declared source doesn’t produce the released bytes. Fix the build to be deterministic.
  • Capabilities don’t match source — manifest declares one thing, binary tries another. Reconcile.
  • Too broad — plugin does five things; split it.
  • Capability ask too high — see the table above.

Re-submission after a fix is fine. No quota.

Help