SafetyCard Request a review

NotFair Plugin

Host-agnostic marketing plugin: 48 SEO, GEO and paid-media skills plus one remote NotFair MCP connection for ad, analytics, CMS and CRM platforms.

github.com/nowork-studio/notfair-plugin · 2026-10-04 · 1a53d4e

Defense-in-depth score

1.2 / 10

NotFair gives a coding agent one OAuth connection that can change ad budgets, campaigns, WordPress sites and CRM records across ten platforms, and almost every safeguard it ships is instruction text for the model, not code. The one write script in the repo has a confirmation step the model skips with --yes. The setup flow collects CMS API keys and passwords through chat, and the CMS scripts trust .env files from the working directory. Install it only on a host whose own approval prompts you keep on for every MCP call.

Safest setup

NotFair Plugin ships few protections of its own: it adds no approval step, sandbox or record for the ad, CMS and CRM changes it enables, and its bundled scripts run as you. The safest setup narrows the accounts it can reach, keeps your host's approval prompts on, and builds containment around it yourself.

SetupHowWhat it gives you
A narrowly scoped NotFair grantAuthorize the NotFair connection from an account that holds only the ad, analytics, CMS and CRM access the task needs, read-only where the platform allowsEach platform itself refuses anything outside that access, whatever the model asks for C1
A Search Console-only identitySign gcloud in with an account whose only access is Search Console for the sites you analyseThe bundled scripts' Google token reaches Search Console data and nothing else in your cloud C1
Host approval on every callKeep your host's approval prompt on for every NotFair MCP tool call and every Bash commandA person decides on each budget, campaign, CRM and WordPress change before it happens C2
The Strapi diff confirmationRun the Strapi push script yourself in a terminal, without --yesYou see the per-entry diff and answer the confirmation prompt yourself before anything is written C2
Upgrades you chooseSet update_check: false in ~/.toprank/config.yaml and run the upgrade skill yourself after reading the new versionNew plugin code arrives only when you decide to take it C7
A clean working directoryStart sessions from a directory with no .env, .env.local or .notfair.json file you didn't writeCMS endpoints, accounts and saved context come only from files you created C6
Keys entered outside chatType CMS API keys and application passwords into .env.local in your own editor, and make the file readable only by youLong-lived CMS keys stay out of the model's context and the host transcript C8
Its own container or VMRun the host and plugin in a container or VM that holds only the credentials this work needsAn outer boundary around the bundled scripts, which otherwise run with your home directory and cloud credentials C4

Approving with confidence

  • Read each prompt and approve calls one at a time; check the account, the amount and the target before approving a budget, bid or campaign change.
  • A session-wide approval of Bash covers every command the skill runs, so approve commands individually during /setup-cms and upgrades.

Handling data

  • The plugin keeps no record of the changes it makes; keep your host's transcript and each platform's own change history for review.
  • Saved business context and change logs in the data directory are read back as trusted input in later sessions; review them before relying on them.

Key gaps (6)

  1. The plugin's only code-level write confirmation is skipped by a model-supplied --yes flag, and all MCP mutations rely on prompt text for approval. C2 · Approval gates
  2. Bundled scripts and pre-approved Bash run unsandboxed as the user with ambient gcloud credentials and full network. C4 · Code-execution isolation
  3. Sessions combine untrusted web/CMS content, sensitive ad and CRM data, and write/egress capabilities with no plugin-enforced break (C5-WORSTCASE). C5 · Untrusted input blast radius
  4. CMS scripts auto-load .env/.env.local from the working directory and parents, letting a workspace file redirect the endpoint that receives the Bearer API key. C6 · Memory, context & configuration integrity
  5. Upgrades install unverified latest main into the plugin cache, and updated code runs as the user with full environment and OAuth reach. C7 · Third-party extensions
  6. setup-cms collects CMS API keys and WordPress application passwords through chat, sending them to the model provider. C8 · Secrets & sensitive-data protection

Criteria

C1 Identity & least privilege

0.05 / 1.00

The plugin itself holds no identity of its own: it points the host at one NotFair OAuth connection that, once authorized, can read and write across Google, Meta, X, LinkedIn, Reddit and TikTok Ads, GA4, Search Console, WordPress and GoHighLevel. Which scopes that connection carries is decided by NotFair's private server, not by anything in this repository. The bundled Search Console scripts mint the user's ambient gcloud credentials with the broad cloud-platform scope and fall back to an unscoped token. Authorization beyond that is described only in skill prose (a saved account ID is not proof of access).

C2 Approval gates

0.05 / 1.00

Every consequential action this plugin enables (budget, bid and campaign changes, CRM edits, WordPress changes, sitemap submissions) flows through NotFair's remote MCP, and the plugin's only safeguard on that path is instruction text telling the model to get explicit approval. The one write path implemented in this repo, the Strapi SEO push script, shows a real diff and asks y/N, but it refuses to prompt when not on a terminal and tells the caller to pass --yes, which the model can simply add. Two skills also pre-approve unrestricted Bash in their frontmatter, removing the host's per-command prompt while they run. Whatever the host's own approval UI does is not credited to this plugin.

C3 Tool & action scoping

0.35 / 1.00

The CMS scripts validate their configured base URL (http/https only, private and loopback addresses rejected, DNS-resolved addresses checked), and the Strapi push refuses stale writes. That validation is not a complete boundary, and the broken-link crawler fetches any URL with no internal-address block. The real tool surface, the remote MCP, is shipped fully enabled with no read-only option in the plugin.

C4 Code-execution isolation

0.00 / 1.00

The plugin ships Python and shell scripts that the host agent runs directly on the user's machine, as the user, with access to the home directory and gcloud credentials. Nothing in the plugin isolates them, and two skills pre-approve unrestricted Bash so commands they drive run without a host prompt. The upgrade skill pulls the latest main branch and copies it into the plugin cache, so newly fetched code later runs the same way.

C5 Untrusted input blast radius

0.07 / 1.00

The skills routinely have the agent read content the user did not write: competitor pages, crawled sites, CMS content, search data and MCP results. Nothing in the plugin marks that content as untrusted or separates it from instructions, and the same session holds write access to ad budgets, CRM conversations and CMS content plus open web egress. If injected text hijacks the agent, nothing in the plugin stops it leaking data or making changes; any protection comes from the host's approval prompts, which this plugin does not control.

C6 Memory, context & configuration integrity

0.10 / 1.00

Skills save business context, personas, change logs and content calendars to a local data directory and read them back in later sessions, with no validation or provenance: whatever the model writes becomes trusted context next time. A project-level .notfair.json switches which account and data directory are used. The CMS scripts also auto-load .env and .env.local from the working directory and up to five parent directories, and send the stored API key as a Bearer token to whatever STRAPI_URL those files name, so a cloned project can redirect credentials.

C7 Third-party extensions

0.13 / 1.00

The plugin wires a remote MCP server whose tools and descriptions are whatever NotFair's server returns at each connection, with nothing pinned. The upgrade skill fetches main, hard-resets the marketplace checkout and copies it into the plugin cache with no signature or hash check, and its inline flow is labelled auto-upgrade. Upgraded code and the MCP tools run with the user's full authority and OAuth grants.

C8 Secrets & sensitive-data protection

0.05 / 1.00

The setup-cms skill asks the user to paste WordPress application passwords and Strapi full-access tokens into the chat, which puts them in the model's context and the host transcript, then writes them in plaintext to .env.local without restricting permissions. There is no redaction anywhere in the scripts. The plugin ships no telemetry.

C9 Audit & traceability

0.00 / 1.00

Plugin code keeps no record of what it did: scripts print progress to stderr and nothing is persisted. The skills ask the model to write change logs and intervention records, but those are model-authored files in a user-writable directory, not an audit trail. Any transcript or server-side history belongs to the host or NotFair's private service.

C10 Limits & kill switch

0.35 / 1.00

All 20 HTTP calls in the bundled scripts carry timeouts, retries are capped at three, and the crawler stops at 50 pages by default, though the caller can raise that. Nothing in the plugin bounds the consequential path: there is no spend ceiling, rate limit or count limit on MCP mutations. Pausing or stopping is left entirely to the host.