Deploy on managed browsers
This is the governed way to deploy the browser extension: on a managed browser it is force-installed and pinned, so an ordinary user cannot remove or disable it, and the policy lives in an admin-only location, so undoing it takes the same privilege as removing the agent. For a browser you do not manage — a personal Mac, an unenrolled Chrome, an evaluation — see Install on an unmanaged browser instead; that path is user-removable and evaluation-only.
The extension arrives one of two ways, and both write the same browser policy, so you can mix them across a fleet:
- The agent installer. On Windows and Linux, which are preview platforms
today, the one-liner also writes the force-install
policy, and on every platform it registers the native-messaging host for
every user of the machine (on Windows, the
HKLMregistry keys). It cannot write the policy on macOS. See What the installer does, per platform. - Your own MDM / GPO / cloud management. Intune, Jamf, Workspace ONE, Group Policy or Chrome/Edge cloud management push the same force-install entry centrally. On macOS this is the only way in.
The published extension is the
Lumen Browser Collector on the Chrome Web Store.
Chrome force-installs a store-hosted extension from ExtensionInstallForcelist
on any Windows machine, managed or not, so the one-liner arms Chrome on a laptop
that is joined to nothing, such as Windows 11 Home.
Microsoft Edge does not. On a Windows machine that is not joined to an
Active Directory domain, Edge force-installs only extensions listed on Microsoft
Edge Add-ons (Microsoft's ExtensionInstallForcelist
reference),
so there the installer's entry arms Chrome and leaves Edge without the
extension. A person can still add it to Edge by hand from the store listing
(Install on an unmanaged browser); on a
domain-joined machine Edge force-installs it like Chrome.
macOS is the exception for a different reason: Chrome reads policy there only from a configuration profile.
The coordinates
Every mechanism below needs the same two values — the published extension ID and the update URL the browser fetches it from. The default is the Chrome Web Store build:
Extension ID pnbjfklmbahlondakkdjaffkmimofmni
Update URL https://clients2.google.com/service/update2/crx
Forcelist entry (Chromium) pnbjfklmbahlondakkdjaffkmimofmni;https://clients2.google.com/service/update2/crx
Every Lumen release publishes the self-hosted CRX below at once, but a store
build goes live only once Google's review of its upload passes, so the store can
lag the release. On 2026-09-28 the store served 0.1.0 while the self-hosted
CRX served 2.8.0; by 2026-09-30 the store served 2.8.0 too. A browser that swaps builds (an installer re-run on a
machine that had the self-hosted one) takes whatever the store serves; check
before you roll out:
curl -s 'https://clients2.google.com/service/update2/crx?response=updatecheck&acceptformat=crx3&prodversion=130&x=id%3Dpnbjfklmbahlondakkdjaffkmimofmni%26uc'
# the version="X.Y.Z" attribute of <updatecheck>
No access to the Chrome Web Store: the self-hosted CRX
Every release also publishes the extension as a signed CRX on Lumen's own download site, for a managed or air-gapped fleet that cannot reach the store:
Extension ID ocnmngannfenghhgdobcgiohodgafmlo
Update URL https://dl.lumen.wazuh.com/crx/update.xml
Forcelist entry (Chromium) ocnmngannfenghhgdobcgiohodgafmlo;https://dl.lumen.wazuh.com/crx/update.xml
Chrome force-installs an extension hosted outside the store on Windows and macOS
only when the machine is joined to Active Directory or Entra ID, enrolled in an
MDM, or enrolled in Chrome Browser Cloud Management (free). On any other machine
it refuses it, and chrome://extensions says it "can only automatically install
extensions hosted on the Chrome Webstore". Point the installers at it with two
environment variables:
curl -fsSL https://dl.lumen.wazuh.com/install.sh | sudo \
LUMEN_EXTENSION_ID=ocnmngannfenghhgdobcgiohodgafmlo \
LUMEN_UPDATE_URL=https://dl.lumen.wazuh.com/crx/update.xml \
sh -s -- --token=<enrollment token>
On Windows, set $env:LUMEN_EXTENSION_ID and $env:LUMEN_UPDATE_URL to the same
values before running install.ps1. The native-messaging host accepts both
builds either way, so a browser holding either one reaches the agent. The ids it
accepts come from LUMEN_NM_EXTENSION_IDS (default: both published ids, comma
separated), plus whatever LUMEN_EXTENSION_ID names.
You do not enroll the browser separately. A managed endpoint's extension reaches the local agent over Native Messaging and inherits the machine's device enrollment, tenant and policy — the browser shows up under that endpoint, not as its own. So a complete managed deployment is: force-install policy (below) + the agent installed and running (Install the agent).
By operating system
- Windows
- macOS
- Linux
Chromium browsers read ExtensionInstallForcelist from HKLM\SOFTWARE\Policies\<vendor>.
Use whichever delivery your fleet already has:
- Group Policy (ADMX). Import the Chrome / Edge administrative templates, then enable Configure the list of force-installed apps and extensions and add the forcelist entry above.
- Intune. Use the settings catalog (Extensions → Control which extensions are installed silently) or an OMA-URI that sets the same policy.
- Registry — exactly what
lumen-agent browser installwrites, if you prefer a script:
reg add "HKLM\SOFTWARE\Policies\Google\Chrome\ExtensionInstallForcelist" /v 1 /t REG_SZ ^
/d "pnbjfklmbahlondakkdjaffkmimofmni;https://clients2.google.com/service/update2/crx" /f
reg add "HKLM\SOFTWARE\Policies\Microsoft\Edge\ExtensionInstallForcelist" /v 1 /t REG_SZ ^
/d "pnbjfklmbahlondakkdjaffkmimofmni;https://clients2.google.com/service/update2/crx" /f
The registry key per browser vendor:
| Browser | Key under HKLM |
|---|---|
| Chrome | SOFTWARE\Policies\Google\Chrome\ExtensionInstallForcelist |
| Edge | SOFTWARE\Policies\Microsoft\Edge\ExtensionInstallForcelist |
| Brave | SOFTWARE\Policies\BraveSoftware\Brave\ExtensionInstallForcelist |
| Chromium | SOFTWARE\Policies\Chromium\ExtensionInstallForcelist |
The values are a numbered list, so use the next free number (1, 2, …) beside
any entry your own GPO already sets. lumen-agent browser install does that for
you, and replaces an entry for the other Lumen build rather than adding a second
one, so a machine upgraded from an installer that pinned the self-hosted CRX
ends with one Lumen extension, not two. Entries for any other extension are
never touched.
Brave accepts the same policy, but Brave is not supported yet: no native-messaging host is registered for it, so a force-installed extension there cannot reach the agent.
macOS is the one platform the agent installer cannot arm on its own: Chromium
honours ExtensionInstallForcelist on macOS only from a managed-preferences
configuration profile, and a plain defaults write on an unmanaged Mac is
ignored. Deliver a profile from your MDM (Jamf, Intune, Workspace ONE) that sets
the forcelist in the browser's preference domain.
The preference domain per browser: Chrome com.google.Chrome, Edge
com.microsoft.Edge, Brave com.brave.Browser, Chromium org.chromium.Chromium.
The payload sets one key:
<key>ExtensionInstallForcelist</key>
<array>
<string>pnbjfklmbahlondakkdjaffkmimofmni;https://clients2.google.com/service/update2/crx</string>
</array>
Scope the profile to the machines that should be governed and push it; the extension installs on the next policy refresh and cannot be removed by the user.
The profile installs the extension; it does not connect it to the agent. The
extension also needs the agent's native-messaging host. The one-liner
registers it machine-wide, in /Library/Google/Chrome/NativeMessagingHosts/
and the Edge and Chromium equivalents, so it works for every user of the Mac.
The macOS .pkg does not register it, so on a .pkg fleet run this once
per machine, as root, or the extension loads and captures nothing:
sudo lumen-agent nm install --system \
--extension pnbjfklmbahlondakkdjaffkmimofmni,ocnmngannfenghhgdobcgiohodgafmlo \
--config /etc/lumen/agent.yaml
Chromium browsers read JSON policy files from a per-vendor managed-policies
directory. lumen-agent browser install writes this for you; to deploy by hand,
drop a file such as lumen-extension.json:
{
"ExtensionInstallForcelist": [
"pnbjfklmbahlondakkdjaffkmimofmni;https://clients2.google.com/service/update2/crx"
]
}
into the browser's managed directory:
| Browser | Managed-policies directory |
|---|---|
| Chrome | /etc/opt/chrome/policies/managed/ |
| Chromium | /etc/chromium/policies/managed/ |
| Brave | /etc/brave/policies/managed/ |
| Edge | its own managed-policies directory — prefer lumen-agent browser install, which writes the file |
Files here are root-owned, so a standard user cannot remove them.
Firefox (later track)
Firefox uses enterprise policies.json with ExtensionSettings:
installation_mode: "force_installed" and a pinned install_url to a
Mozilla-signed XPI (unsigned XPIs cannot be force-installed). The shipped
build targets Chrome and Edge today, so Firefox is a later track —
there is no signed XPI to force-install yet. When it ships, lumen-agent browser install --firefox-id <id> --xpi-url <url> writes the policies.json entry, or
your MDM pushes the same.
Enforce on responses
Blocking or redacting the model's reply in the browser is off by default,
and a response rule in the Lumen policy does not turn it on by itself. The
switch is the extension's own managed configuration, the policy an
administrator sets for one extension (Chrome calls it the 3rdparty extension
policy). The extension holds back a short tail of each streamed reply, so a
matched secret or URL can be cut before it paints, only when both of these keys
are set by policy:
| Key | Type | Value |
|---|---|---|
tenant_id | string | your tenant id, shown on the console's Settings page. The extension treats itself as managed only when this key is present |
enforce_output | boolean | true to hold and enforce on replies. Default false |
Then it acts wherever the assigned policy has a response rule at Redact or Block. The cost is latency: every reply streams behind by the held tail, which is why it is opt-in.
Deliver the keys the way you deliver any extension policy:
- Windows: values under
HKLM\SOFTWARE\Policies\Google\Chrome\3rdparty\extensions\pnbjfklmbahlondakkdjaffkmimofmni\policy,tenant_idasREG_SZandenforce_outputasREG_DWORD1. Edge uses the same layout underSOFTWARE\Policies\Microsoft\Edge. - macOS: a configuration profile for the preference domain
com.google.Chrome.extensions.pnbjfklmbahlondakkdjaffkmimofmni.
The id in the key is the build you deploy: the self-hosted CRX's is
ocnmngannfenghhgdobcgiohodgafmlo.
- Chrome Browser Cloud Management: the extension's policy JSON in the Google Admin console.
chrome://policy lists the keys under the extension once they arrive. Response
capture itself is best-effort today (see the
Browser extension page), so this switch
enforces only on the replies the extension manages to reassemble.
Verify it took
On a managed endpoint, open the browser's policy page and reload:
- Chrome / Brave / Chromium:
chrome://policy→ Reload policies. TheExtensionInstallForcelistentry is listed and the extension is installed with no remove/disable control for the user. - Edge:
edge://policy.
Then check which build is installed: chrome://extensions (or edge://extensions)
shows Lumen Browser Collector with the version of the Lumen release that
published it (release v2.8.0 is extension 2.8.0). The Chrome Web Store build
shows the version the store last approved, which can be older than the release
(0.1.0 on 2026-09-28; see the caution under The coordinates).
Browsers pick up a new
release on their next extension update check, which Chrome makes every few
hours; Update on the extensions page (Developer mode) checks now. Builds from
v2.7.0 and earlier all show 0.1.0, whatever they contained: a browser still on
0.1.0 has not taken an update yet. Each interaction the extension records
carries its version too, and the console shows it on the interaction's
Collector line.
Then confirm the endpoint side: the agent is running (lumen-agent status) and its
native-messaging host is registered, so the extension has something to talk to.
The installer registers it machine-wide: a com.wazuh.lumen.json file in each
browser's system-wide native-messaging directory on macOS and Linux, and on
Windows the HKLM\Software\<vendor>\NativeMessagingHosts\com.wazuh.lumen key,
whose default value names %ProgramFiles%\Lumen\nm\com.wazuh.lumen.json. Every
location is listed under
Where the host manifest lands.
Browser activity then appears in the console under
Interactions, tagged as coming from the browser.
If you added the Windows registry key by hand for an earlier release, it has to
go: browsers read the per-user key before the machine-wide one, and the old
one names a manifest that accepts only the self-hosted build. The installer
removes it when it runs as the account that added it (an elevated prompt in that
person's own session); run as SYSTEM or by another administrator it cannot reach
that account's keys, so then delete it by hand
(reg delete "HKCU\Software\Google\Chrome\NativeMessagingHosts\com.wazuh.lumen" /f,
and the same under Microsoft\Edge if you added one there).
The store default and the machine-wide host registration are installer steps.
An agent self-upgrade, automatic or from the console, replaces the binary and
nothing else, so an endpoint upgraded that way keeps the self-hosted forcelist
entry (which an unmanaged Windows machine refuses) and, on Windows, a host no
browser can reach. Re-run install.ps1 or install.sh on it; a re-run keeps
the endpoint's config and its device credential.
Remove it
lumen-agent browser uninstall drops the policy it wrote (pass the same
--extension-id/--update-url), and the forcelist entry of the other Lumen build
with it; or remove the entry from your MDM/GPO. Either way the extension becomes
removable again and disappears on the next policy refresh. The installers'
uninstall also removes the native-messaging host (lumen-agent nm uninstall --system) and the entry installers up to v2.9.0 wrote for the self-hosted CRX.
A copy added to Edge by hand, on a Windows machine whose Edge does not take the
store entry, was never installed by a policy, so removing the policy leaves it.
lumen-agent browser uninstall says so there; remove that copy in
edge://extensions.
Per-browser × per-OS summary
| Browser | Windows | macOS | Linux |
|---|---|---|---|
| Chrome | GPO / registry / Intune (…\Google\Chrome) | MDM config profile (com.google.Chrome) | managed-policies JSON (/etc/opt/chrome/policies/managed/) |
| Edge | GPO / registry / Intune (…\Microsoft\Edge) | MDM config profile (com.microsoft.Edge) | managed-policies JSON (installer writes it) |
| Chromium | GPO / registry (…\Chromium) | MDM config profile (org.chromium.Chromium) | managed-policies JSON (/etc/chromium/…) |
| Brave (not supported yet) | GPO / registry (…\BraveSoftware\Brave) | MDM config profile (com.brave.Browser) | managed-policies JSON (/etc/brave/…) |
| Firefox | policies.json / ADMX (later track) | policies.json (later track) | /etc/firefox/policies/policies.json (later track) |
On a Windows or Linux machine that also runs the agent, the installer writes this policy for you. With the Chrome Web Store build, Chrome on Windows does not need the machine to be managed; Edge on Windows installs it only on an Active Directory domain-joined machine (see the tip at the top). macOS always needs the MDM configuration profile above.
See also
- Browser extension — what it captures and enforces
- Install on an unmanaged browser — the developer / evaluation path
- Install the agent — the agent the extension talks to