Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,113 @@

{% tabs %}
{% tab title="Intune" %}
You need to create **two custom profiles** in Intune (one for Chrome, one for Edge).\
Each profile contains **two OMA-URI settings**:

* **Installation policy** → tells the browser to force-install the extension.
* **Configuration policy** → applies your custom extension settings.
The simplest method of Intune deployment is via a win32 script. Follow the steps below to:
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The introduction sentence is incomplete: “Follow the steps below to:” ends without listing what the reader will accomplish. Consider finishing the sentence (or replacing with a short bullet list) so the section reads cleanly.

Suggested change
The simplest method of Intune deployment is via a win32 script. Follow the steps below to:
The simplest method of Intune deployment is via a win32 script. Follow the steps below to deploy Check with Intune.

Copilot uses AI. Check for mistakes.

***

#### Step 1 – Open Intune and Start a New Profile
## Setup Script

1. Download a copy of the Setup-Windows-Chrome-and-Edge.ps1 script from the Check repository on GitHub using the button below.

1. Go to Intune Admin Center.
2. Navigate to: **Devices → Configuration profiles**
3. Click on **Create → Import Policy**
4. Import the following file to deploy the extensions. This will deploy the configuration
<a href="https://raw.githubusercontent.com/CyberDrain/Check/refs/heads/main/enterprise/Setup-Windows-Chrome-and-Edge.ps1" class="button primary">Import File</a>
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The button text says “Import File”, but the link points to a raw .ps1 download. Renaming the button to something like “Download script” would better match what the action actually does.

Suggested change
<a href="https://raw.githubusercontent.com/CyberDrain/Check/refs/heads/main/enterprise/Setup-Windows-Chrome-and-Edge.ps1" class="button primary">Import File</a>
<a href="https://raw.githubusercontent.com/CyberDrain/Check/refs/heads/main/enterprise/Setup-Windows-Chrome-and-Edge.ps1" class="button primary">Download script</a>

Copilot uses AI. Check for mistakes.

<a href="https://raw.githubusercontent.com/CyberDrain/Check/refs/heads/main/docs/.gitbook/assets/Check%20Extension_%20Install%20for%20Chrome%20and%20Edge_2025-09-20T22_08_38.615Z.json" class="button primary">Import File</a>
2. Run the script locally on your computer to generate the following scripts:
1. Deploy-Windows-Chrome-and-Edge.ps1
2. Remove-Windows-Chrome-and-Edge.ps1
3. Detect-Windows-Chrome-and-Edge.ps1
3. You will be prompted during the Setup script on how you want to configure Check. Follow the script's guidance to ensure you're accurately entering values for the script. These values will be used for both the Deploy and Detect to ensure the extension is properly deployed.
4. Set the output location the script will use to generate the three new scripts.

{% hint style="info" %} You can also download the three scripts directly from the Check GitHub repo and edit the configuration settings manually. {% endhint %}

***

#### Step 2: Configuration
## Adding to Intune

### Prerequisites

- Microsoft Intune admin access
- The [Microsoft Win32 Content Prep Tool](https://github.com/microsoft/Microsoft-Win32-Content-Prep-Tool) (`IntuneWinAppUtil.exe`) to package scripts as `.intunewin` files

### Step 1: Package the Scripts

Intune Win32 apps require an `.intunewin` package. Place your three configured scripts in a folder, then run:

```powershell
.\IntuneWinAppUtil.exe -c "C:\path\to\scripts\folder" -s "Deploy-Windows-Chrome-and-Edge.ps1" -o "C:\path\to\output"
```

This creates `Deploy-Windows-Chrome-and-Edge.intunewin`.

### Step 3: Configure App Information

Comment on lines +33 to +44
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Step numbering skips from “Step 1” to “Step 3” in the Intune instructions. Renumbering to be sequential (or adding the missing Step 2) will reduce confusion when following the guide.

Copilot uses AI. Check for mistakes.
| Field | Value |
|-------|-------|
| Name | `Check by CyberDrain - Browser Extension` |
| Description | `Deploys and configures the Check by CyberDrain phishing protection extension for Chrome and Edge browsers.` |
| Publisher | Your company name or `CyberDrain` |

### Step 4: Configure Program Settings

| Field | Value |
|-------|-------|
| Install command | `powershell.exe -ExecutionPolicy Bypass -File Deploy-Windows-Chrome-and-Edge.ps1` |
| Uninstall command | `powershell.exe -ExecutionPolicy Bypass -File Remove-Windows-Chrome-and-Edge.ps1` |
| Install behavior | **System** |
| Device restart behavior | **No specific action** |

### Step 5: Configure Requirements

| Field | Value |
|-------|-------|
| Operating system architecture | **64-bit** |
| Minimum operating system | **Windows 10 1607** (or your minimum supported version) |

### Step 6: Configure Detection Rules

1. Under **Detection rules**, select **Use a custom detection script**
2. Upload `Detect-Windows-Chrome-and-Edge.ps1`
3. Set the following:

| Field | Value |
|-------|-------|
| Run script as 32-bit process on 64-bit clients | **No** |
| Enforce script signature check | **No** |
| Run script in 64-bit PowerShell host | **No** |

Comment on lines +77 to +78
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Detection rules table includes “Run script in 64-bit PowerShell host”, which (depending on the Intune Win32 app UI) may not be an available setting for custom detection scripts. Also, if a 64-bit/32-bit choice is available, this detection script reads HKLM:\SOFTWARE\Policies\... and should run in 64-bit to avoid WOW6432Node redirection. Please verify the correct Intune options here and adjust the table accordingly.

Suggested change
| Run script in 64-bit PowerShell host | **No** |
Keep **Run script as 32-bit process on 64-bit clients** set to **No** so the detection script runs in the 64-bit PowerShell/registry context on 64-bit devices. This is important because the script checks values under `HKLM:\SOFTWARE\Policies\...`; running it as 32-bit could read redirected `WOW6432Node` paths and cause detection to fail incorrectly.

Copilot uses AI. Check for mistakes.
The detection script checks that all registry keys written by the install script exist and have the correct values. It exits with code `0` when everything matches (app detected) and code `1` when any value is missing or wrong (app not detected, triggers reinstall).

### Step 7: Assign the App

1. Under **Assignments**, click **Add group** under **Required**
2. Choose your target:
- **All devices** — deploys to every Intune-managed Windows device
- **All users** — deploys to devices used by any licensed user
- **Select groups** — deploy to specific Azure AD / Entra ID groups
3. Click **Review + create** > **Create**

## Updating Settings

When you need to change extension settings (e.g., enable page blocking, update branding):

1. Re-run the setup script with new values, or manually edit the config blocks in both `Deploy-` and `Detect-` scripts
2. Re-package with `IntuneWinAppUtil.exe`
3. In Intune, either update the existing app or delete and recreate it with the new package

Because the detection script body changes when settings change, Intune will detect the app as "not installed" on endpoints and automatically redeploy with the updated configuration.

## Uninstalling

To remove the extension from managed devices:

- **Option A:** In Intune, change the app assignment from **Required** to **Uninstall**. Intune will run the `Remove-Windows-Chrome-and-Edge.ps1` script on targeted devices.
- **Option B:** Delete the app from Intune entirely. Note that this stops management but does not actively remove the registry keys from devices that already have them.

## Troubleshooting

Documentation to follow
- **Extension not appearing after deployment:** Check that the install script ran as System (not User). Verify registry keys exist under `HKLM:\SOFTWARE\Policies\Google\Chrome\ExtensionSettings\` and `HKLM:\SOFTWARE\Policies\Microsoft\Edge\ExtensionSettings\`.
- **Intune keeps reinstalling the app:** The detection script values don't match what the install script wrote. Ensure both scripts have identical configuration values.
- **Detection script shows as failed:** Run the detection script manually on a test device as Administrator to see which check fails (it will exit at the first mismatch).
{% endtab %}

{% tab title="Group Policy" %}
Expand Down
170 changes: 170 additions & 0 deletions enterprise/Detect-Windows-Chrome-and-Edge.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
# Check Extension - Intune Detection Script
# This script verifies that the Check by CyberDrain extension is correctly configured
# in the registry for both Chrome and Edge browsers.
#
# IMPORTANT: The settings below MUST match the values in your Deploy-Windows-Chrome-and-Edge.ps1.
# If any value differs, Intune will detect the app as "not installed" and trigger a reinstall.
#
# Exit codes: 0 = compliant (extension correctly configured), 1 = non-compliant (drift detected)

# Define extension details
# Chrome
$chromeExtensionId = "benimdeioplgkhanklclahllklceahbe"
$chromeUpdateUrl = "https://clients2.google.com/service/update2/crx"
$chromeManagedStorageKey = "HKLM:\SOFTWARE\Policies\Google\Chrome\3rdparty\extensions\$chromeExtensionId\policy"
$chromeExtensionSettingsKey = "HKLM:\SOFTWARE\Policies\Google\Chrome\ExtensionSettings\$chromeExtensionId"

#Edge
$edgeExtensionId = "knepjpocdagponkonnbggpcnhnaikajg"
$edgeUpdateUrl = "https://edge.microsoft.com/extensionwebstorebase/v1/crx"
$edgeManagedStorageKey = "HKLM:\SOFTWARE\Policies\Microsoft\Edge\3rdparty\extensions\$edgeExtensionId\policy"
$edgeExtensionSettingsKey = "HKLM:\SOFTWARE\Policies\Microsoft\Edge\ExtensionSettings\$edgeExtensionId"

# Extension Configuration Settings
$showNotifications = 1 # 0 = Unchecked, 1 = Checked (Enabled); default is 1; This will set the "Show Notifications" option in the extension settings.
$enableValidPageBadge = 0 # 0 = Unchecked, 1 = Checked (Enabled); default is 0; This will set the "Show Valid Page Badge" option in the extension settings.
$enablePageBlocking = 1 # 0 = Unchecked, 1 = Checked (Enabled); default is 1; This will set the "Enable Page Blocking" option in the extension settings.
$forceToolbarPin = 1 # 0 = Not pinned, 1 = Force pinned to toolbar; default is 1
$enableCippReporting = 0 # 0 = Unchecked, 1 = Checked (Enabled); default is 0; This will set the "Enable CIPP Reporting" option in the extension settings.
$cippServerUrl = "" # This will set the "CIPP Server URL" option in the extension settings; default is blank; if you set $enableCippReporting to 1, you must set this to a valid URL including the protocol (e.g., https://cipp.cyberdrain.com). Can be vanity URL or the default azurestaticapps.net domain.
$cippTenantId = "" # This will set the "Tenant ID/Domain" option in the extension settings; default is blank; if you set $enableCippReporting to 1, you must set this to a valid Tenant ID.
$customRulesUrl = "" # This will set the "Config URL" option in the Detection Configuration settings; default is blank.
$updateInterval = 24 # This will set the "Update Interval" option in the Detection Configuration settings; default is 24 (hours). Range: 1-168 hours (1 hour to 1 week).
$urlAllowlist = @() # This will set the "URL Allowlist" option in the Detection Configuration settings; default is blank; if you want to add multiple URLs, add them as a comma-separated list within the brackets (e.g., @("https://example1.com", "https://example2.com")). Supports simple URLs with * wildcard (e.g., https://*.example.com) or advanced regex patterns (e.g., ^https:\/\/(www\.)?example\.com\/.*$).
$domainSquattingEnabled = 1 # 0 = Disabled, 1 = Enabled; default is 1; controls domain squatting detection from managed policy/config.
$enableDebugLogging = 0 # 0 = Unchecked, 1 = Checked (Enabled); default is 0; This will set the "Enable Debug Logging" option in the Activity Log settings.

# Generic Webhook Settings
$enableGenericWebhook = 0 # 0 = Disabled, 1 = Enabled; default is 0; This will enable the generic webhook for sending detection events to a custom endpoint.
$webhookUrl = "" # This will set the "Webhook URL" option; default is blank; if you set $enableGenericWebhook to 1, you must set this to a valid URL including the protocol (e.g., https://webhook.example.com/endpoint).
$webhookEvents = @() # This will set the "Event Types" to send to the webhook; default is blank; if you set $enableGenericWebhook to 1, you can specify which events to send. Available events: "detection_alert", "false_positive_report", "page_blocked", "rogue_app_detected", "threat_detected", "validation_event". Example: @("detection_alert", "page_blocked", "threat_detected").

# Custom Branding Settings
$companyName = "CyberDrain" # This will set the "Company Name" option in the Custom Branding settings; default is "CyberDrain".
$productName = "Check - Phishing Protection" # This will set the "Product Name" option in the Custom Branding settings; default is "Check - Phishing Protection".
$supportEmail = "" # This will set the "Support Email" option in the Custom Branding settings; default is blank.
$supportUrl = "" # This will set the "Support URL" option in the Custom Branding settings; default is blank.
$privacyPolicyUrl = "" # This will set the "Privacy URL" option in the Custom Branding settings; default is blank.
$aboutUrl = "" # This will set the "About URL" option in the Custom Branding settings; default is blank.
$primaryColor = "#F77F00" # This will set the "Primary Color" option in the Custom Branding settings; default is "#F77F00"; must be a valid hex color code (e.g., #FFFFFF).
$logoUrl = "" # This will set the "Logo URL" option in the Custom Branding settings; default is blank. Must be a valid URL including the protocol (e.g., https://example.com/logo.png); protocol must be https; recommended size is 48x48 pixels with a maximum of 128x128.

# Extension Settings
$installationMode = "force_installed"

# Helper to check a registry value matches expected
function Test-RegValue {
param (
[string]$Path,
[string]$Name,
$Expected
)
$val = (Get-ItemProperty -Path $Path -Name $Name -ErrorAction SilentlyContinue).$Name
return ($null -ne $val -and $val -eq $Expected)
}

# Define browser configurations for detection
$browsers = @(
@{
Name = 'Chrome'
ExtensionId = $chromeExtensionId
UpdateUrl = $chromeUpdateUrl
ManagedStorageKey = $chromeManagedStorageKey
ExtensionSettingsKey = $chromeExtensionSettingsKey
ToolbarProp = 'toolbar_pin'
ToolbarValue = 'force_pinned'
},
@{
Name = 'Edge'
ExtensionId = $edgeExtensionId
UpdateUrl = $edgeUpdateUrl
ManagedStorageKey = $edgeManagedStorageKey
ExtensionSettingsKey = $edgeExtensionSettingsKey
ToolbarProp = 'toolbar_state'
ToolbarValue = 'force_shown'
}
)

foreach ($browser in $browsers) {
# Verify managed storage key exists
if (!(Test-Path $browser.ManagedStorageKey)) { exit 1 }

$policyKey = $browser.ManagedStorageKey

# Core DWord settings
if (!(Test-RegValue $policyKey 'showNotifications' $showNotifications)) { exit 1 }
if (!(Test-RegValue $policyKey 'enableValidPageBadge' $enableValidPageBadge)) { exit 1 }
if (!(Test-RegValue $policyKey 'enablePageBlocking' $enablePageBlocking)) { exit 1 }
if (!(Test-RegValue $policyKey 'enableCippReporting' $enableCippReporting)) { exit 1 }
if (!(Test-RegValue $policyKey 'updateInterval' $updateInterval)) { exit 1 }
if (!(Test-RegValue $policyKey 'enableDebugLogging' $enableDebugLogging)) { exit 1 }

# Core String settings
if (!(Test-RegValue $policyKey 'cippServerUrl' $cippServerUrl)) { exit 1 }
if (!(Test-RegValue $policyKey 'cippTenantId' $cippTenantId)) { exit 1 }
if (!(Test-RegValue $policyKey 'customRulesUrl' $customRulesUrl)) { exit 1 }

# domainSquatting subkey
$domainSquattingKey = "$policyKey\domainSquatting"
if (!(Test-Path $domainSquattingKey)) { exit 1 }
if (!(Test-RegValue $domainSquattingKey 'enabled' $domainSquattingEnabled)) { exit 1 }

# customBranding subkey
$brandingKey = "$policyKey\customBranding"
if (!(Test-Path $brandingKey)) { exit 1 }
Comment on lines +88 to +114
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This script exits 1 on the first mismatch but doesn’t emit any details about what key/value failed. The updated docs recommend running it manually to see which check fails, but without output that’s hard to diagnose. Consider printing a short message (browser + key + expected/actual) before each failure, or refactoring to accumulate failures and output a summary before exiting 1.

Suggested change
foreach ($browser in $browsers) {
# Verify managed storage key exists
if (!(Test-Path $browser.ManagedStorageKey)) { exit 1 }
$policyKey = $browser.ManagedStorageKey
# Core DWord settings
if (!(Test-RegValue $policyKey 'showNotifications' $showNotifications)) { exit 1 }
if (!(Test-RegValue $policyKey 'enableValidPageBadge' $enableValidPageBadge)) { exit 1 }
if (!(Test-RegValue $policyKey 'enablePageBlocking' $enablePageBlocking)) { exit 1 }
if (!(Test-RegValue $policyKey 'enableCippReporting' $enableCippReporting)) { exit 1 }
if (!(Test-RegValue $policyKey 'updateInterval' $updateInterval)) { exit 1 }
if (!(Test-RegValue $policyKey 'enableDebugLogging' $enableDebugLogging)) { exit 1 }
# Core String settings
if (!(Test-RegValue $policyKey 'cippServerUrl' $cippServerUrl)) { exit 1 }
if (!(Test-RegValue $policyKey 'cippTenantId' $cippTenantId)) { exit 1 }
if (!(Test-RegValue $policyKey 'customRulesUrl' $customRulesUrl)) { exit 1 }
# domainSquatting subkey
$domainSquattingKey = "$policyKey\domainSquatting"
if (!(Test-Path $domainSquattingKey)) { exit 1 }
if (!(Test-RegValue $domainSquattingKey 'enabled' $domainSquattingEnabled)) { exit 1 }
# customBranding subkey
$brandingKey = "$policyKey\customBranding"
if (!(Test-Path $brandingKey)) { exit 1 }
function Write-DetectionFailure {
param(
[string]$BrowserName,
[string]$KeyPath,
[string]$ValueName,
[object]$ExpectedValue,
[object]$ActualValue
)
if ([string]::IsNullOrEmpty($ValueName)) {
Write-Output "$BrowserName detection failed: missing registry key '$KeyPath'."
return
}
Write-Output "$BrowserName detection failed for '$ValueName' at '$KeyPath': expected '$ExpectedValue', actual '$ActualValue'."
}
function Test-RegValueWithDetails {
param(
[string]$BrowserName,
[string]$KeyPath,
[string]$ValueName,
[object]$ExpectedValue
)
$matches = Test-RegValue $KeyPath $ValueName $ExpectedValue
if ($matches) {
return $true
}
$actualValue = '<missing>'
if (Test-Path $KeyPath) {
try {
$property = Get-ItemProperty -Path $KeyPath -Name $ValueName -ErrorAction Stop
$actualValue = $property.$ValueName
}
catch {
$actualValue = '<missing>'
}
}
Write-DetectionFailure -BrowserName $BrowserName -KeyPath $KeyPath -ValueName $ValueName -ExpectedValue $ExpectedValue -ActualValue $actualValue
return $false
}
foreach ($browser in $browsers) {
# Verify managed storage key exists
if (!(Test-Path $browser.ManagedStorageKey)) {
Write-DetectionFailure -BrowserName $browser.Name -KeyPath $browser.ManagedStorageKey -ValueName $null -ExpectedValue $null -ActualValue $null
exit 1
}
$policyKey = $browser.ManagedStorageKey
# Core DWord settings
if (!(Test-RegValueWithDetails $browser.Name $policyKey 'showNotifications' $showNotifications)) { exit 1 }
if (!(Test-RegValueWithDetails $browser.Name $policyKey 'enableValidPageBadge' $enableValidPageBadge)) { exit 1 }
if (!(Test-RegValueWithDetails $browser.Name $policyKey 'enablePageBlocking' $enablePageBlocking)) { exit 1 }
if (!(Test-RegValueWithDetails $browser.Name $policyKey 'enableCippReporting' $enableCippReporting)) { exit 1 }
if (!(Test-RegValueWithDetails $browser.Name $policyKey 'updateInterval' $updateInterval)) { exit 1 }
if (!(Test-RegValueWithDetails $browser.Name $policyKey 'enableDebugLogging' $enableDebugLogging)) { exit 1 }
# Core String settings
if (!(Test-RegValueWithDetails $browser.Name $policyKey 'cippServerUrl' $cippServerUrl)) { exit 1 }
if (!(Test-RegValueWithDetails $browser.Name $policyKey 'cippTenantId' $cippTenantId)) { exit 1 }
if (!(Test-RegValueWithDetails $browser.Name $policyKey 'customRulesUrl' $customRulesUrl)) { exit 1 }
# domainSquatting subkey
$domainSquattingKey = "$policyKey\domainSquatting"
if (!(Test-Path $domainSquattingKey)) {
Write-DetectionFailure -BrowserName $browser.Name -KeyPath $domainSquattingKey -ValueName $null -ExpectedValue $null -ActualValue $null
exit 1
}
if (!(Test-RegValueWithDetails $browser.Name $domainSquattingKey 'enabled' $domainSquattingEnabled)) { exit 1 }
# customBranding subkey
$brandingKey = "$policyKey\customBranding"
if (!(Test-Path $brandingKey)) {
Write-DetectionFailure -BrowserName $browser.Name -KeyPath $brandingKey -ValueName $null -ExpectedValue $null -ActualValue $null
exit 1
}

Copilot uses AI. Check for mistakes.
if (!(Test-RegValue $brandingKey 'companyName' $companyName)) { exit 1 }
if (!(Test-RegValue $brandingKey 'productName' $productName)) { exit 1 }
if (!(Test-RegValue $brandingKey 'supportEmail' $supportEmail)) { exit 1 }
if (!(Test-RegValue $brandingKey 'supportUrl' $supportUrl)) { exit 1 }
if (!(Test-RegValue $brandingKey 'privacyPolicyUrl' $privacyPolicyUrl)) { exit 1 }
if (!(Test-RegValue $brandingKey 'aboutUrl' $aboutUrl)) { exit 1 }
if (!(Test-RegValue $brandingKey 'primaryColor' $primaryColor)) { exit 1 }
if (!(Test-RegValue $brandingKey 'logoUrl' $logoUrl)) { exit 1 }

# genericWebhook subkey
$webhookKey = "$policyKey\genericWebhook"
if (!(Test-Path $webhookKey)) { exit 1 }
if (!(Test-RegValue $webhookKey 'enabled' $enableGenericWebhook)) { exit 1 }
if (!(Test-RegValue $webhookKey 'url' $webhookUrl)) { exit 1 }

# genericWebhook\events subkey — verify exact count and values
$eventsKey = "$webhookKey\events"
if (!(Test-Path $eventsKey)) { exit 1 }
if ($webhookEvents.Count -gt 0) {
$eventsCount = (Get-Item $eventsKey).Property.Count
if ($eventsCount -ne $webhookEvents.Count) { exit 1 }
for ($i = 0; $i -lt $webhookEvents.Count; $i++) {
if (!(Test-RegValue $eventsKey ($i + 1).ToString() $webhookEvents[$i])) { exit 1 }
}
} else {
$existingEvents = (Get-Item $eventsKey).Property
if ($null -ne $existingEvents -and $existingEvents.Count -gt 0) { exit 1 }
}

# urlAllowlist subkey — verify exact count and values
$allowlistKey = "$policyKey\urlAllowlist"
if (!(Test-Path $allowlistKey)) { exit 1 }
if ($urlAllowlist.Count -gt 0) {
$allowlistCount = (Get-Item $allowlistKey).Property.Count
if ($allowlistCount -ne $urlAllowlist.Count) { exit 1 }
for ($i = 0; $i -lt $urlAllowlist.Count; $i++) {
if (!(Test-RegValue $allowlistKey ($i + 1).ToString() $urlAllowlist[$i])) { exit 1 }
}
} else {
$existingAllowlist = (Get-Item $allowlistKey).Property
if ($null -ne $existingAllowlist -and $existingAllowlist.Count -gt 0) { exit 1 }
}

# ExtensionSettings key
if (!(Test-Path $browser.ExtensionSettingsKey)) { exit 1 }
if (!(Test-RegValue $browser.ExtensionSettingsKey 'installation_mode' $installationMode)) { exit 1 }
if (!(Test-RegValue $browser.ExtensionSettingsKey 'update_url' $browser.UpdateUrl)) { exit 1 }

# Toolbar pin — only checked when enabled (upstream install script does not write this property when disabled)
if ($forceToolbarPin -eq 1) {
if (!(Test-RegValue $browser.ExtensionSettingsKey $browser.ToolbarProp $browser.ToolbarValue)) { exit 1 }
Comment on lines +163 to +165
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When $forceToolbarPin is set to 0, the detection script does not verify that the browser-specific toolbar policy value is absent. If a device was previously deployed with pinning enabled, the stale toolbar_pin/toolbar_state value can remain and this script will still report compliant, so Intune won’t remediate the change. Consider explicitly failing when the toolbar property exists while $forceToolbarPin -eq 0 (and ensure the deploy script removes the property in that case to avoid a reinstall loop).

Suggested change
# Toolbar pin — only checked when enabled (upstream install script does not write this property when disabled)
if ($forceToolbarPin -eq 1) {
if (!(Test-RegValue $browser.ExtensionSettingsKey $browser.ToolbarProp $browser.ToolbarValue)) { exit 1 }
# Toolbar pin — when enabled, require the expected value; when disabled, require the property to be absent
if ($forceToolbarPin -eq 1) {
if (!(Test-RegValue $browser.ExtensionSettingsKey $browser.ToolbarProp $browser.ToolbarValue)) { exit 1 }
} else {
$extensionSettingsProps = (Get-Item $browser.ExtensionSettingsKey).Property
if ($null -ne $extensionSettingsProps -and $extensionSettingsProps -contains $browser.ToolbarProp) { exit 1 }

Copilot uses AI. Check for mistakes.
}
}

Write-Output "Check extension is correctly configured for Chrome and Edge."
exit 0
Loading
Loading