@@ -28,10 +28,13 @@ function Invoke-CIPPStandardDeployCheckChromeExtension {
2828 {"type":"textField","name":"standards.DeployCheckChromeExtension.webhookUrl","label":"Webhook URL","placeholder":"https://webhook.example.com/endpoint","required":false}
2929 {"type":"autoComplete","multiple":true,"creatable":true,"required":false,"label":"Webhook Events","name":"standards.DeployCheckChromeExtension.webhookEvents","placeholder":"e.g. pageBlocked, pageAllowed"}
3030 {"type":"autoComplete","multiple":true,"creatable":true,"required":false,"label":"URL Allowlist","name":"standards.DeployCheckChromeExtension.urlAllowlist","placeholder":"e.g. https://example.com/*"}
31+ {"type":"switch","name":"standards.DeployCheckChromeExtension.domainSquattingEnabled","label":"Enable domain squatting detection","defaultValue":true}
3132 {"type":"textField","name":"standards.DeployCheckChromeExtension.companyName","label":"Company Name","placeholder":"YOUR-COMPANY","required":false}
32- {"type":"textField","name":"standards.DeployCheckChromeExtension.companyURL","label":"Company URL","placeholder":"https://yourcompany.com","required":false}
3333 {"type":"textField","name":"standards.DeployCheckChromeExtension.productName","label":"Product Name","placeholder":"YOUR-PRODUCT-NAME","required":false}
3434 {"type":"textField","name":"standards.DeployCheckChromeExtension.supportEmail","label":"Support Email","placeholder":"support@yourcompany.com","required":false}
35+ {"type":"textField","name":"standards.DeployCheckChromeExtension.supportUrl","label":"Support URL","placeholder":"https://support.yourcompany.com","required":false}
36+ {"type":"textField","name":"standards.DeployCheckChromeExtension.privacyPolicyUrl","label":"Privacy Policy URL","placeholder":"https://yourcompany.com/privacy","required":false}
37+ {"type":"textField","name":"standards.DeployCheckChromeExtension.aboutUrl","label":"About URL","placeholder":"https://yourcompany.com/about","required":false}
3538 {"type":"textField","name":"standards.DeployCheckChromeExtension.primaryColor","label":"Primary Color","placeholder":"#F77F00","required":false}
3639 {"type":"textField","name":"standards.DeployCheckChromeExtension.logoUrl","label":"Logo URL","placeholder":"https://yourcompany.com/logo.png","required":false}
3740 {"name":"AssignTo","label":"Who should this app be assigned to?","type":"radio","options":[{"label":"Do not assign","value":"On"},{"label":"Assign to all users","value":"allLicensedUsers"},{"label":"Assign to all devices","value":"AllDevices"},{"label":"Assign to all users and devices","value":"AllDevicesAndUsers"},{"label":"Assign to Custom Group","value":"customGroup"}]}
@@ -90,10 +93,13 @@ function Invoke-CIPPStandardDeployCheckChromeExtension {
9093 $WebhookUrl = $Settings.webhookUrl ?? ' '
9194 $WebhookEvents = @ ($Settings.webhookEvents | ForEach-Object { $_.value ?? $_ } | Where-Object { $_ })
9295 $UrlAllowlist = @ ($Settings.urlAllowlist | ForEach-Object { $_.value ?? $_ } | Where-Object { $_ })
96+ $DomainSquattingEnabled = [int ][bool ]($Settings.domainSquattingEnabled ?? $true )
9397 $CompanyName = $Settings.companyName ?? ' '
94- $CompanyURL = $Settings.companyURL ?? ' '
9598 $ProductName = $Settings.productName ?? ' '
9699 $SupportEmail = $Settings.supportEmail ?? ' '
100+ $SupportUrl = $Settings.supportUrl ?? ' '
101+ $PrivacyPolicyUrl = $Settings.privacyPolicyUrl ?? ' '
102+ $AboutUrl = $Settings.aboutUrl ?? ' '
97103 $PrimaryColor = if ($Settings.primaryColor ) { $Settings.primaryColor } else { ' #F77F00' }
98104 $LogoUrl = $Settings.logoUrl ?? ' '
99105
@@ -140,13 +146,21 @@ foreach (`$b in `$browsers) {
140146 New-ItemProperty -Path `$ b.ManagedStorageKey -Name 'updateInterval' -PropertyType DWord -Value $UpdateInterval -Force | Out-Null
141147 New-ItemProperty -Path `$ b.ManagedStorageKey -Name 'enableDebugLogging' -PropertyType DWord -Value $EnableDebugLogging -Force | Out-Null
142148
149+ # Managed storage - domainSquatting subkey
150+ `$ domainSquattingKey = "`$ (`$ b.ManagedStorageKey)\domainSquatting"
151+ if (!(Test-Path `$ domainSquattingKey)) { New-Item -Path `$ domainSquattingKey -Force | Out-Null }
152+ New-ItemProperty -Path `$ domainSquattingKey -Name 'enabled' -PropertyType DWord -Value $DomainSquattingEnabled -Force | Out-Null
153+
143154 # Managed storage - customBranding subkey
144155 `$ brandingKey = "`$ (`$ b.ManagedStorageKey)\customBranding"
145156 if (!(Test-Path `$ brandingKey)) { New-Item -Path `$ brandingKey -Force | Out-Null }
146157 New-ItemProperty -Path `$ brandingKey -Name 'companyName' -PropertyType String -Value '$ ( $CompanyName -replace " '" , " ''" ) ' -Force | Out-Null
147- New-ItemProperty -Path `$ brandingKey -Name 'companyURL' -PropertyType String -Value ' $ ( $CompanyURL -replace " ' " , " '' " ) ' -Force | Out-Null
158+
148159 New-ItemProperty -Path `$ brandingKey -Name 'productName' -PropertyType String -Value '$ ( $ProductName -replace " '" , " ''" ) ' -Force | Out-Null
149- New-ItemProperty -Path `$ brandingKey -Name 'supportEmail' -PropertyType String -Value '$ ( $SupportEmail -replace " '" , " ''" ) ' -Force | Out-Null
160+ New-ItemProperty -Path `$ brandingKey -Name 'supportEmail' -PropertyType String -Value '$ ( $SupportEmail -replace " '" , " ''" ) ' -Force | Out-Null
161+ New-ItemProperty -Path `$ brandingKey -Name 'supportUrl' -PropertyType String -Value '$ ( $SupportUrl -replace " '" , " ''" ) ' -Force | Out-Null
162+ New-ItemProperty -Path `$ brandingKey -Name 'privacyPolicyUrl' -PropertyType String -Value '$ ( $PrivacyPolicyUrl -replace " '" , " ''" ) ' -Force | Out-Null
163+ New-ItemProperty -Path `$ brandingKey -Name 'aboutUrl' -PropertyType String -Value '$ ( $AboutUrl -replace " '" , " ''" ) ' -Force | Out-Null
150164 New-ItemProperty -Path `$ brandingKey -Name 'primaryColor' -PropertyType String -Value '$PrimaryColor ' -Force | Out-Null
151165 New-ItemProperty -Path `$ brandingKey -Name 'logoUrl' -PropertyType String -Value '$ ( $LogoUrl -replace " '" , " ''" ) ' -Force | Out-Null
152166
@@ -251,13 +265,21 @@ foreach (`$key in @(`$chromeKey, `$edgeKey)) {
251265 if (!(Test-RegValue `$ key 'cippTenantId' '$CippTenantId ')) { exit 1 }
252266 if (!(Test-RegValue `$ key 'customRulesUrl' '$CustomRulesUrl ')) { exit 1 }
253267
268+ # domainSquatting subkey
269+ `$ domainSquattingKey = "`$ key\domainSquatting"
270+ if (!(Test-Path `$ domainSquattingKey)) { exit 1 }
271+ if (!(Test-RegValue `$ domainSquattingKey 'enabled' $DomainSquattingEnabled )) { exit 1 }
272+
254273 # customBranding subkey
255274 `$ brandingKey = "`$ key\customBranding"
256275 if (!(Test-Path `$ brandingKey)) { exit 1 }
257276 if (!(Test-RegValue `$ brandingKey 'companyName' '$ ( $CompanyName -replace " '" , " ''" ) ')) { exit 1 }
258- if (!(Test-RegValue `$ brandingKey 'companyURL' ' $ ( $CompanyURL -replace " ' " , " '' " ) ')) { exit 1 }
277+
259278 if (!(Test-RegValue `$ brandingKey 'productName' '$ ( $ProductName -replace " '" , " ''" ) ')) { exit 1 }
260- if (!(Test-RegValue `$ brandingKey 'supportEmail' '$ ( $SupportEmail -replace " '" , " ''" ) ')) { exit 1 }
279+ if (!(Test-RegValue `$ brandingKey 'supportEmail' '$ ( $SupportEmail -replace " '" , " ''" ) ')) { exit 1 }
280+ if (!(Test-RegValue `$ brandingKey 'supportUrl' '$ ( $SupportUrl -replace " '" , " ''" ) ')) { exit 1 }
281+ if (!(Test-RegValue `$ brandingKey 'privacyPolicyUrl' '$ ( $PrivacyPolicyUrl -replace " '" , " ''" ) ')) { exit 1 }
282+ if (!(Test-RegValue `$ brandingKey 'aboutUrl' '$ ( $AboutUrl -replace " '" , " ''" ) ')) { exit 1 }
261283 if (!(Test-RegValue `$ brandingKey 'primaryColor' '$PrimaryColor ')) { exit 1 }
262284 if (!(Test-RegValue `$ brandingKey 'logoUrl' '$ ( $LogoUrl -replace " '" , " ''" ) ')) { exit 1 }
263285
@@ -312,6 +334,16 @@ Write-Output 'Check Chrome Extension is correctly configured.'
312334exit 0
313335"@
314336
337+ # #########################################################################
338+ # Compute a settings fingerprint from the install script so we can skip
339+ # redeploy when nothing has changed.
340+ # #########################################################################
341+ $Sha256 = [System.Security.Cryptography.SHA256 ]::Create()
342+ $SettingsHash = ([System.BitConverter ]::ToString(
343+ $Sha256.ComputeHash ([System.Text.Encoding ]::UTF8.GetBytes($InstallScript ))
344+ ) -replace ' -' , ' ' ).Substring(0 , 16 )
345+ $AppDescription = " Deploys and configures the Check by CyberDrain phishing protection extension for Chrome and Edge browsers. Managed by CIPP. [cfg:$SettingsHash ]"
346+
315347 # #########################################################################
316348 # Legacy OMA-URI policy cleanup
317349 # #########################################################################
@@ -325,7 +357,7 @@ exit 0
325357 # Check for existing Win32 app
326358 # #########################################################################
327359 $Baseuri = ' https://graph.microsoft.com/beta/deviceAppManagement/mobileApps'
328- $ExistingApps = New-GraphGetRequest - Uri " $Baseuri `?`$ filter=displayName eq '$AppDisplayName '&`$ select=id,displayName" - tenantid $Tenant | Where-Object {
360+ $ExistingApps = New-GraphGetRequest - Uri " $Baseuri `?`$ filter=displayName eq '$AppDisplayName '&`$ select=id,displayName,description " - tenantid $Tenant | Where-Object {
329361 $_ .' @odata.type' -eq ' #microsoft.graph.win32LobApp'
330362 }
331363 $AppExists = ($null -ne $ExistingApps -and @ ($ExistingApps ).Count -gt 0 )
@@ -358,9 +390,20 @@ exit 0
358390 }
359391
360392 if ($AppExists ) {
361- # App exists — delete and recreate to pick up any script changes
362- foreach ($ExistingApp in @ ($ExistingApps )) {
363- $null = New-GraphPostRequest - Uri " $Baseuri /$ ( $ExistingApp.id ) " - Type DELETE - tenantid $Tenant
393+ # Check if the settings hash matches — skip redeploy if nothing changed
394+ $ExistingHash = $null
395+ $ExistingApp = @ ($ExistingApps )[0 ]
396+ if ($ExistingApp.description -match ' \[cfg:([0-9A-Fa-f]{16})\]' ) {
397+ $ExistingHash = $Matches [1 ]
398+ }
399+
400+ if ($ExistingHash -eq $SettingsHash ) {
401+ Write-LogMessage - API ' Standards' - tenant $Tenant - message " $AppDisplayName settings unchanged — skipping redeploy" - sev Info
402+ return
403+ }
404+
405+ foreach ($App in @ ($ExistingApps )) {
406+ $null = New-GraphPostRequest - Uri " $Baseuri /$ ( $App.id ) " - Type DELETE - tenantid $Tenant
364407 Write-LogMessage - API ' Standards' - tenant $Tenant - message " Removed existing $AppDisplayName app to redeploy with updated settings" - sev Info
365408 }
366409 Start-Sleep - Seconds 2
@@ -369,7 +412,7 @@ exit 0
369412 # Deploy the Win32 script app
370413 $AppProperties = [PSCustomObject ]@ {
371414 displayName = $AppDisplayName
372- description = ' Deploys and configures the Check by CyberDrain phishing protection extension for Chrome and Edge browsers. Managed by CIPP. '
415+ description = $AppDescription
373416 publisher = ' CIPP'
374417 installScript = $InstallScript
375418 uninstallScript = $UninstallScript
0 commit comments