Browser Extension Deployment
This guide is for admins rolling out the Control Zero browser extension to a team of developer or employee machines.
Enterprise MDM force-install (Chrome Enterprise policy, Jamf, Intune, Google Workspace, Kandji) is temporarily unavailable and will return. For now, distribute the extension manually: users self-install from the Chrome Web Store, or a Teams admin downloads the pre-configured bundle below and shares it.
If you are a developer just trying to install the extension to see it work, skip to the sign-up flow and install from the Chrome Web Store instead.
What the extension does, briefly
The Control Zero browser extension scans text typed or pasted into AI chat composers on supported sites (Claude.ai, ChatGPT, Gemini, Perplexity) against your org's data-loss-prevention rules. Matches are logged to your org's audit feed. When a rule is configured to mask or block, the extension rewrites the text inline or cancels the paste.
What the extension captures:
- The matched text span (e.g., a specific SSN that tripped a rule)
- 40 characters of context before and after the match
- The host the user was on (e.g.,
claude.ai) - A device ID unique to this browser profile
- Hostname, user agent, extension version
- Optionally, the user's work email (opt-in)
What the extension does NOT capture:
- The full contents of the composer when no rule fires
- Keystrokes when the extension is paused (10-minute user override)
- Any content on non-AI-chat surfaces (search bars, password fields, etc.)
- Any content on sites outside the explicit allowlist
Network-level guard (v0.2.1)
Starting in extension version 0.2.1, the extension installs a second line of defense alongside the DOM-level overlay: a network-level guard that observes every outgoing AI request and can block it before it leaves the browser.
The guard requires three additional Chrome permissions in the manifest:
webRequest-- used in observer-only mode. Manifest V3 forbids blockingwebRequestlisteners, so the listener only reads the request body, scans it against the org's DLP rules, and emits an audit entry on a hit.declarativeNetRequest-- the only MV3-supported way to actually block a request. The extension synchronizes a dynamic ruleset against any DLP rule scoped tobrowser_ext_networkwithaction=block. The browser evaluates these rules in the network stack, which means a block still works even if the page disabled JavaScript or rewrote the textarea around the DOM overlay.declarativeNetRequestFeedback-- lets the extension log which dynamic rule fired, so the audit entry can name the policy that blocked the call.
Why both: the DOM-level overlay is the user-facing UX (Grammarly-style underlines and tooltips). The network guard is the safety net for when the overlay is bypassed. Together they cover composer typing and XHR-level egress.
The new DLP rule scope browser_ext_network is distinct from the existing browser_ext (DOM-only). Admins can scope a rule to either, both, or neither -- the editor in the dashboard accepts both scopes.
What declarativeNetRequest cannot do
- It does not inspect request bodies. The dynamic ruleset matches on URL only, so the network-level block is a hammer ("block all browser AI calls that match a DLP block rule"), not a scalpel. Body-aware decisions still come from the DOM overlay.
- The 30,000 dynamic rule cap (and 5,000 regex rule cap) is shared across all extensions in the profile. The extension only writes one rule per supported AI surface, so this is not a concern in practice.
- Rules are evaluated at the network stack, not in the page, so a successful block surfaces to the page as a network error, not a friendly message. The audit entry is the source of truth for what happened.
Cross-browser caveats
- Chrome / Edge / Brave / other Chromium: full support, this is the target.
- Firefox: Firefox still supports blocking
webRequestlisteners under MV2 semantics, and itsdeclarativeNetRequestimplementation is partial. A Firefox port of the extension would use blockingwebRequestdirectly and skip the DNR sync entirely. Themanifest.jsonshipped here is Chromium-MV3-only. - Safari: Safari Web Extensions support
declarativeNetRequestbut notdeclarativeNetRequestFeedback. A Safari port would drop that permission and lose the per-rule attribution in audit entries.
Enterprise bundle download (Teams tier)
Teams-tier admins can download a pre-configured extension bundle from the dashboard or via API. The bundle is a ZIP containing the full extension source with an embedded config.json that pre-populates the org ID, API key, and backend URL. This eliminates the need for users to manually configure the extension.
Dashboard
- Navigate to Integrations > Browser Extension in the dashboard.
- Select the target platform (Chrome or Firefox).
- Click Download Bundle. A ZIP file downloads with the extension source and embedded configuration.
- Share the ZIP with your team (internal download link, shared drive, or an unlisted store listing) so each user can install it.
API
# Download the Chrome bundle
curl -H "Cookie: cz_session=<your dashboard session cookie>" \
-o controlzero-extension-chrome.zip \
"https://api.controlzero.ai/api/orgs/<ORG_ID>/browser-extension/bundle?platform=chrome"
# Download the Firefox bundle
curl -H "Cookie: cz_session=<your dashboard session cookie>" \
-o controlzero-extension-firefox.zip \
"https://api.controlzero.ai/api/orgs/<ORG_ID>/browser-extension/bundle?platform=firefox"
The ZIP contains a config.json with the structure:
{
"api_url": "https://api.controlzero.ai",
"org_id": "<ORG_ID>",
"api_key": "cz_extension_ext_<generated>"
}
Each bundle download generates a fresh extension-scoped API key (scoped to browser_ext:report and browser_ext:config). Revoke unused bundle keys from the dashboard or API.
Bulk key generation (Teams tier)
For large fleet deployments where each device needs a unique key, use the bulk key generation API.
Generate keys
curl -X POST \
-H "Cookie: cz_session=<your dashboard session cookie>" \
-H "Content-Type: application/json" \
-d '{"count": 50, "prefix": "fleet", "expiry_days": 365}' \
"https://api.controlzero.ai/api/orgs/<ORG_ID>/browser-extension/keys"
Response:
{
"keys": [
{
"id": "uuid",
"key_prefix": "cz_extension_fleet_abcd1234",
"secret": "cz_extension_fleet_<full_secret>",
"scopes": ["browser_ext:report", "browser_ext:config"],
"expires_at": "2027-04-11T00:00:00Z",
"created_at": "2026-04-11T00:00:00Z"
}
],
"count": 50
}
Parameters:
count(required): number of keys to generate, 1-100prefix(optional): key name prefix, default "ext"expiry_days(optional): days until expiry, default 365
List keys
curl -H "Cookie: cz_session=<your dashboard session cookie>" \
"https://api.controlzero.ai/api/orgs/<ORG_ID>/browser-extension/keys"
Returns all extension keys for the org (prefix only, never the full secret).
Revoke a key
curl -X DELETE \
-H "Cookie: cz_session=<your dashboard session cookie>" \
"https://api.controlzero.ai/api/orgs/<ORG_ID>/browser-extension/keys/<KEY_ID>"
Key rotation procedure
- Generate a new batch of keys via the bulk endpoint.
- Re-issue the updated bundle (or distribute the new keys) to your team.
- Monitor the audit feed for 24 hours to confirm devices are reporting with the new keys.
- Revoke the old keys.
Deployment modes
During the pilot the extension is distributed manually via self-install:
Optional self-install
Users visit the Chrome Web Store and install the extension themselves, then paste their org ID and a cz_live_* API key into the options page. Best for teams experimenting with Control Zero before a company-wide rollout.
Compliance checklist (pre-rollout)
Do not deploy this extension to employee devices without completing this checklist. Monitoring software, even cooperative DLP, has legal implications in many jurisdictions.
EU (GDPR, ePrivacy, codetermination law)
- Works council approval (Germany, Austria, France, Italy) — codetermination law requires Betriebsrat / Conseil Social / RSU approval before deploying any system that can log employee activity. Have a signed minutes entry approving the rollout.
- Data Processing Addendum (DPA) updated — your DPA with employees (or union agreement) must name keystroke scanning in AI chat composers as a processing activity.
- Privacy notice updated — add a section to your employee privacy notice describing what the extension captures, retention, and employee rights.
- Data residency verified — if EU employees' audit entries cross a border (e.g., US-hosted backend), ensure SCCs are in place or use an EU-hosted backend instance.
- DPO (Data Protection Officer) sign-off — document that the DPO has reviewed the deployment.
US (CCPA, BIPA, state-specific monitoring laws)
- California employees — CCPA requires disclosure of data collection at or before collection. The extension's first-run tutorial serves as this disclosure, but add it to your employee handbook too.
- Illinois employees — BIPA covers biometric data, not keystrokes directly, but the Illinois Electronic Monitoring Act (2022) requires written notice of electronic monitoring. Signed acknowledgment from the employee is recommended.
- Connecticut employees — similar notice requirements under C.G.S. § 31-48d.
- New York employees — NY Labor Law § 52-c requires prior written notice of electronic monitoring.
Universal
- User disclosure banner — the extension's options page shows a monitoring notice. Verify it is present and accurate for your org.
- First-run tutorial reviewed — the extension opens the options page on first install and shows a tutorial. Comms / enablement team should approve the copy.
- Rule review — no rule has a pattern matching >1% of a sample-content corpus (the backend enforces an 8-char minimum pattern length, but you should still review manually for overly-broad rules).
- Ignore list policy — decide which rule categories users are allowed to ignore. Default: only
customandipignorable;secretandpiialways enforced. - Audit retention — set a retention cap on the audit log. Default and maximum: 90 days.
- Heartbeat alert runbook — assign an on-call rotation to respond to "browser extension silenced" alerts from the backend.
- Panic delete procedure documented — when an employee typos a password into a chat composer and a rule captures it, what's the process to remove that audit entry? Document the SOP.
Troubleshooting
"Heartbeat alerts are firing but the user is still using Claude.ai"
Check whether the extension is in paused state (user has hit the "Pause 10 min" button in the popup). Paused extensions continue posting heartbeats so this should not happen, but it's worth verifying. Also check the device clock — if it is more than 15 minutes skewed, the backend may see the heartbeats as stale.
What's NOT in v0.2
- LLM-assisted rewrite — "scrub this for me" button that uses the org's gateway to rewrite captured content. Deferred to v0.3.
- Safari support — Apple's extension model requires a different build and distribution path. Planned for v1.0.
- Mobile browser support — iOS / Android extensions are a different platform. Planned for v1.0.
- Per-employee identity via SSO/SCIM — current v0.2 identifies devices, not users. SSO-claimed identity comes in v1.0.
- Admin-controlled continuous-scan toggle — v0.2 always enables continuous scan on the 4 supported surfaces when the extension is configured. v0.3 adds a managed-storage flag to disable it for orgs that want paste-only mode.
Operational defaults
| Setting | Default | Override |
|---|---|---|
| Heartbeat interval | 5 minutes | Hardcoded |
| Heartbeat-missing alert threshold | 15 minutes | Backend config |
| Rule cache refresh | 5 minutes | Hardcoded |
| Scan debounce | 150 ms | Hardcoded |
| Scan performance budget | 16 ms per pass | Hardcoded |
| Circuit breaker | 3 consecutive scans > 50 ms | Hardcoded |
| Session activity buffer cap | 10 entries | Hardcoded |
| Audit entry context window | 40 chars before + 40 after | Hardcoded |
| Default audit retention | 90 days | Backend config |