Deploying the CrowdStrike AIDR Browser Extension via Falcon for IT
Using Falcon for IT to deploy the CrowdStrike AIDR browser collector across Edge, Chrome, and Firefox Developer Edition — writing browser policies directly on endpoints via the Falcon sensor without standing up a parallel MDM deployment.
Background
CrowdStrike AIDR (AI-powered Detection and Response) includes a browser collector extension that provides visibility into browser-based activity. Unlike the DLP and IDP extensions, which can be deployed directly via a Falcon sensor policy, the AIDR extension currently has no native sensor policy deployment option. With broader rollout on the roadmap, we needed a way to test the extension across our environment before that capability becomes available.
Rather than standing up a parallel MDM deployment just for this, we leveraged Falcon for IT — using its PowerShell and Zsh script execution capabilities to write the necessary browser policies directly on endpoints where the Falcon sensor was already running.
The Approach
Each browser has its own policy mechanism for force-installing and pre-configuring extensions. The goal for each was the same: silently install the AIDR extension and pre-populate its managed storage with the configuration values it needs to register with the AIDR service — without any user interaction.
The four values written to each browser’s managed storage are:
| Key | Value |
|---|---|
registrationIdentity |
Encrypted token used to register the browser with AIDR |
urlTemplate |
AIDR service endpoint |
userId |
The logged-in username |
userFullName |
COMPUTERNAME\username |
Microsoft Edge
Edge was the most straightforward of the three. It uses Chromium’s ExtensionSettings registry key under HKLM:\SOFTWARE\Policies\Microsoft\Edge\ to both force-install extensions and configure their managed storage.
A single PowerShell script handles both steps:
- Write the
installation_mode: force_installedandupdate_urlvalues under theExtensionSettingskey for the extension ID - Write the four managed storage values under the
3rdparty\extensions\<ID>\policyregistry path
The script runs as SYSTEM in a 64-bit PowerShell host via Falcon for IT, and the extension appears in Edge as a managed extension after the browser restarts.
1# Edge AIDR Extension - Full Deployment Script
2# Run as: SYSTEM, 64-bit PowerShell
3$ErrorActionPreference = "Stop"
4
5try {
6 # ─────────────────────────────────────────────
7 # PART 1: Force-install the extension via policy
8 # ─────────────────────────────────────────────
9 $extensionID = "folndgmoekgkipoolphnkclopeopkecc"
10 $policyPath = "HKLM:\SOFTWARE\Policies\Microsoft\Edge\ExtensionSettings\$extensionID"
11
12 if (-not (Test-Path $policyPath)) {
13 New-Item -Path $policyPath -Force | Out-Null
14 }
15
16 New-ItemProperty -Path $policyPath -Name "installation_mode" -Value "force_installed" -PropertyType String -Force | Out-Null
17 New-ItemProperty -Path $policyPath -Name "update_url" -Value "https://edge.microsoft.com/extensionwebstorebase/v1/crx" -PropertyType String -Force | Out-Null
18
19 Write-Output "Part 1 complete: Extension policy set"
20
21 # ─────────────────────────────────────────────
22 # PART 2: Configure managed storage
23 # ─────────────────────────────────────────────
24 $storagePath = "HKLM:\Software\Policies\Microsoft\Edge\3rdparty\extensions\$extensionID\policy"
25
26 if (-not (Test-Path $storagePath)) {
27 New-Item -Path $storagePath -Force | Out-Null
28 }
29
30 Set-ItemProperty -Path $storagePath -Name "registrationIdentity" `
31 -Value "<Your registrationIdentity here>" `
32 -Type String -Force
33
34 Set-ItemProperty -Path $storagePath -Name "urlTemplate" `
35 -Value "https://api.crowdstrike.com/aidr/aiguard" `
36 -Type String -Force
37
38 New-ItemProperty -Path $storagePath -Name "userId" `
39 -Value "%USERNAME%" -PropertyType ExpandString -Force | Out-Null
40
41 New-ItemProperty -Path $storagePath -Name "userFullName" `
42 -Value "%COMPUTERNAME%\%USERNAME%" -PropertyType ExpandString -Force | Out-Null
43
44 # ─────────────────────────────────────────────
45 # PART 3: Verify
46 # ─────────────────────────────────────────────
47 $policy = Get-ItemProperty -Path $policyPath
48 $storage = Get-ItemProperty -Path $storagePath
49
50 Write-Output "Part 2 complete: Managed storage configured"
51 Write-Output ""
52 Write-Output "=== Verification ==="
53 Write-Output "Extension ID: $extensionID"
54 Write-Output "Installation mode: $($policy.installation_mode)"
55 Write-Output "Update URL: $($policy.update_url)"
56 Write-Output "urlTemplate: $($storage.urlTemplate)"
57 Write-Output "userId: $($storage.userId)"
58 Write-Output "userFullName: $($storage.userFullName)"
59 Write-Output "registrationIdentity: Set"
60 Write-Output ""
61 Write-Output "Deployment complete. Restart Edge for changes to take effect."
62
63 Exit 0
64
65} catch {
66 Write-Error "Deployment failed: $($_.Exception.Message)"
67 Exit 1
68}
Verification: edge://extensions and edge://policy
Google Chrome
Chrome’s deployment is nearly identical to Edge, with two differences:
- Registry paths use
Google\Chromeinstead ofMicrosoft\Edge - The force-install mechanism uses Chrome’s numbered
ExtensionInstallForcelistformat (integer-indexed values:1,2,3…) rather than theExtensionSettingskey
The script detects the next available index in the forcelist automatically, so it won’t overwrite any existing force-installed extensions.
One issue we hit early on was curly/typographic quote characters (" ") in the PowerShell Write-Output lines causing a script parsing exception in Falcon for IT. PowerShell only recognizes straight ASCII quotes (") as string delimiters — something to watch for when copying scripts from a browser or document editor.
1# Chrome AIDR Extension - Full Deployment Script
2# Run as: SYSTEM, 64-bit PowerShell
3$ErrorActionPreference = "Stop"
4
5try {
6 # ─────────────────────────────────────────────
7 # PART 1: Force-install the extension via policy
8 # ─────────────────────────────────────────────
9 $extensionID = "folndgmoekgkipoolphnkclopeopkecc"
10 $policyPath = "HKLM:\SOFTWARE\Policies\Google\Chrome\ExtensionInstallForcelist"
11
12 if (-not (Test-Path $policyPath)) {
13 New-Item -Path $policyPath -Force | Out-Null
14 }
15
16 # Find the next available numbered value
17 $existing = Get-ItemProperty -Path $policyPath -ErrorAction SilentlyContinue
18 $nextIndex = 1
19 while ($existing.PSObject.Properties.Name -contains "$nextIndex") {
20 $nextIndex++
21 }
22
23 New-ItemProperty -Path $policyPath -Name "$nextIndex" `
24 -Value "$extensionID;https://clients2.google.com/service/update2/crx" `
25 -PropertyType String -Force | Out-Null
26
27 Write-Output "Part 1 complete: Extension force-install policy set (index $nextIndex)"
28
29 # ─────────────────────────────────────────────
30 # PART 2: Configure managed storage
31 # ─────────────────────────────────────────────
32 $storagePath = "HKLM:\Software\Policies\Google\Chrome\3rdparty\extensions\$extensionID\policy"
33
34 if (-not (Test-Path $storagePath)) {
35 New-Item -Path $storagePath -Force | Out-Null
36 }
37
38 Set-ItemProperty -Path $storagePath -Name "registrationIdentity" `
39 -Value "<Your registrationIdentity here>" `
40 -Type String -Force
41
42 Set-ItemProperty -Path $storagePath -Name "urlTemplate" `
43 -Value "https://api.crowdstrike.com/aidr/aiguard" `
44 -Type String -Force
45
46 New-ItemProperty -Path $storagePath -Name "userId" `
47 -Value "%USERNAME%" -PropertyType ExpandString -Force | Out-Null
48
49 New-ItemProperty -Path $storagePath -Name "userFullName" `
50 -Value "%COMPUTERNAME%\%USERNAME%" -PropertyType ExpandString -Force | Out-Null
51
52 # ─────────────────────────────────────────────
53 # PART 3: Verify
54 # ─────────────────────────────────────────────
55 $storage = Get-ItemProperty -Path $storagePath
56
57 Write-Output "Part 2 complete: Managed storage configured"
58 Write-Output ""
59 Write-Output "=== Verification ==="
60 Write-Output "Extension ID: $extensionID"
61 Write-Output "Force-install index: $nextIndex"
62 Write-Output "urlTemplate: $($storage.urlTemplate)"
63 Write-Output "userId: $($storage.userId)"
64 Write-Output "userFullName: $($storage.userFullName)"
65 Write-Output "registrationIdentity: Set"
66 Write-Output ""
67 Write-Output "Deployment complete. Restart Chrome for changes to take effect."
68
69 Exit 0
70
71} catch {
72 Write-Error "Deployment failed: $($_.Exception.Message)"
73 Exit 1
74}
Verification: chrome://extensions and chrome://policy
Firefox Developer Edition
Firefox was the most involved of the three, for a few reasons.
Policy Delivery
Firefox doesn’t use the Windows registry for extension force-installation in the same way Chrome and Edge do. Instead, it reads from a policies.json file placed in a distribution folder inside the Firefox install directory. For Developer Edition specifically, we write this file to:
C:\Program Files\Firefox Developer Edition\distribution\policies.json
The ExtensionSettings JSON inside that file tells Firefox to force-install the extension from a remote XPI URL.
Managed storage is still handled via the registry at HKLM:\Software\Policies\Mozilla\Firefox\3rdparty\Extensions\<ID>\, which works the same as standard Firefox.
The XPI Download Problem
After getting the policies in place, the extension still wasn’t installing. Checking about:policies confirmed the policy was being read correctly, which pointed to the download itself failing. Testing the XPI URL directly in Firefox produced a connection failure — but the same URL worked fine in Edge on the same machine.
The root cause: our proxy was performing SSL inspection, and Firefox — unlike Edge — does not automatically trust the Windows certificate store, so it was aborting the TLS connection when it saw the proxy’s inspection certificate instead of the expected certificate from pangea.cloud.
The fix was adding ImportEnterpriseRoots: true to the policies.json, which instructs Firefox to trust the Windows certificate store (and by extension, the proxy’s inspection certificate):
1{
2 "policies": {
3 "ImportEnterpriseRoots": true,
4 "ExtensionSettings": {
5 "[email protected]": {
6 "installation_mode": "force_installed",
7 "install_url": "https://pangea.cloud/firefox-aidr-extension/aidr-extension-latest.xpi"
8 }
9 }
10 }
11}
The BOM Problem
The next issue was a JSON parse error in Firefox: SyntaxError: JSON.parse: unexpected character at line 1 column 1. This was caused by PowerShell’s Set-Content -Encoding UTF8 writing a UTF-8 BOM (byte order mark) at the start of the file — a character Firefox’s JSON parser doesn’t tolerate.
The fix was switching to .NET’s UTF8Encoding class with the BOM explicitly disabled:
1[System.IO.File]::WriteAllText(
2 "$distributionDir\policies.json",
3 $policiesJson,
4 [System.Text.UTF8Encoding]::new($false)
5)
After both fixes, the extension installed successfully on restart. Here is the final working script:
1# Firefox Developer Edition AIDR Extension - Full Deployment Script
2# Run as: SYSTEM, 64-bit PowerShell
3$ErrorActionPreference = "Stop"
4
5try {
6 $extensionID = "[email protected]"
7 $installURL = "https://pangea.cloud/firefox-aidr-extension/aidr-extension-latest.xpi"
8
9 # ─────────────────────────────────────────────
10 # PART 1: Force-install via policies.json
11 # ─────────────────────────────────────────────
12 Write-Output "Part 1: Writing policies.json..."
13
14 $devEditionPaths = @(
15 "$env:ProgramFiles\Firefox Developer Edition",
16 "${env:ProgramFiles(x86)}\Firefox Developer Edition"
17 )
18
19 $installDir = $null
20 foreach ($path in $devEditionPaths) {
21 if (Test-Path $path) {
22 $installDir = $path
23 break
24 }
25 }
26
27 if (-not $installDir) {
28 throw "Firefox Developer Edition install directory not found. Is it installed?"
29 }
30
31 Write-Output " Found Dev Edition at: $installDir"
32
33 $distributionDir = Join-Path $installDir "distribution"
34 if (-not (Test-Path $distributionDir)) {
35 New-Item -Path $distributionDir -ItemType Directory -Force | Out-Null
36 }
37
38 $policiesJson = @"
39{
40 "policies": {
41 "ImportEnterpriseRoots": true,
42 "ExtensionSettings": {
43 "$extensionID": {
44 "installation_mode": "force_installed",
45 "install_url": "$installURL"
46 }
47 }
48 }
49}
50"@
51
52 # Write BOM-free UTF-8 — Firefox JSON parser rejects files with a BOM
53 [System.IO.File]::WriteAllText("$distributionDir\policies.json", $policiesJson, [System.Text.UTF8Encoding]::new($false))
54 Write-Output " Written: $distributionDir\policies.json"
55 Write-Output "Part 1 complete."
56
57 # ─────────────────────────────────────────────
58 # PART 2: Configure managed storage via registry
59 # ─────────────────────────────────────────────
60 Write-Output ""
61 Write-Output "Part 2: Configuring managed storage..."
62
63 $storagePath = "HKLM:\Software\Policies\Mozilla\Firefox\3rdparty\Extensions\$extensionID"
64
65 if (-not (Test-Path $storagePath)) {
66 New-Item -Path $storagePath -Force | Out-Null
67 }
68
69 Set-ItemProperty -Path $storagePath -Name "registrationIdentity" `
70 -Value "<Your registrationIdentity here>" `
71 -Type String -Force
72
73 Set-ItemProperty -Path $storagePath -Name "urlTemplate" `
74 -Value "https://api.crowdstrike.com/aidr/aiguard" `
75 -Type String -Force
76
77 New-ItemProperty -Path $storagePath -Name "userId" `
78 -Value "%USERNAME%" -PropertyType ExpandString -Force | Out-Null
79
80 New-ItemProperty -Path $storagePath -Name "userFullName" `
81 -Value "%COMPUTERNAME%\%USERNAME%" -PropertyType ExpandString -Force | Out-Null
82
83 Write-Output "Part 2 complete."
84
85 # ─────────────────────────────────────────────
86 # PART 3: Verify
87 # ─────────────────────────────────────────────
88 $storage = Get-ItemProperty -Path $storagePath
89 $policiesContent = Get-Content "$distributionDir\policies.json" -Raw
90
91 Write-Output ""
92 Write-Output "=== Verification ==="
93 Write-Output "Install directory: $installDir"
94 Write-Output "policies.json: $distributionDir\policies.json"
95 Write-Output "urlTemplate: $($storage.urlTemplate)"
96 Write-Output "userId: $($storage.userId)"
97 Write-Output "userFullName: $($storage.userFullName)"
98 Write-Output "registrationIdentity: Set"
99 Write-Output ""
100 Write-Output "policies.json contents:"
101 Write-Output $policiesContent
102 Write-Output ""
103 Write-Output "Deployment complete. Restart Firefox Developer Edition for changes to take effect."
104
105 Exit 0
106
107} catch {
108 Write-Error "Deployment failed: $($_.Exception.Message)"
109 Exit 1
110}
Verification: about:addons and about:policies
macOS — What We Tried
We also attempted to deploy the Chrome extension on managed Macs using Falcon for IT’s Zsh script execution. On macOS, Chrome policy is delivered via plist files written to /Library/Managed Preferences/ — one for the force-install list (com.google.Chrome.plist) and one for the extension’s managed storage (com.google.Chrome.extensions.<ID>.plist).
The scripts ran successfully as root and the plist files were written correctly to disk, but chrome://policy remained empty. The reason: the Mac endpoints are MDM-enrolled, and Chrome on MDM-enrolled Macs only trusts policies delivered through the MDM profile channel. Flat plist files written directly to disk — regardless of ownership or permissions — are ignored.
For macOS, the correct deployment path is through the MDM (in our case, Jamf), which delivers signed configuration profiles that Chrome trusts. Falcon for IT is well suited for the Windows side of this deployment; Jamf handles Mac.
Summary
| Browser | Platform | Method | Notes |
|---|---|---|---|
| Microsoft Edge | Windows | Registry (ExtensionSettings) |
Straightforward, single script |
| Google Chrome | Windows | Registry (ExtensionInstallForcelist) |
Watch for quote encoding issues |
| Firefox Dev Edition | Windows | policies.json + Registry |
Needed ImportEnterpriseRoots and BOM-free UTF-8 |
| Google Chrome | macOS | Attempted via plist | MDM-enrolled Macs require Jamf profile delivery |
This approach gave us a working AIDR browser extension deployment across our Windows fleet using infrastructure we already had, without waiting for native sensor policy support to arrive. When that capability does land in Falcon, migrating will be straightforward — the configuration values are already known and tested.