This blog post is about creating a custom compliance policy in Intune to check the ZScaler status. A customer of mine uses ZScaler for all their Windows endpoints. They want to ensure ZScaler is running because we want to protect those endpoints. I thought of the custom compliance feature in Microsoft Intune.
The customer already used a compliance policy. So, I copied the production policy and added the custom compliance configuration to check ZScaler.
The custom compliance configuration checks whether the ZScaler application/service is running. Furthermore, it checks whether your Internet connection runs through the ZScaler Internet Service.
Configuration
Firstly, let’s explain how you can check whether your internet connection runs through ZScaler. A colleague of mine already had a script that you can use. This is the script:
$url = Invoke-WebRequest http://ip.zscaler.com/ $checkzscaler = ($URL.ParsedHtml.getElementsByTagName('div') | Where-Object{ $_.className -eq 'headline' }).innertext
This is the result when your internet connection does not run through ZScaler:

And this is the result when your internet connection does run through ZScaler:

So, how do we make Intune check for the ZScaler? Unfortunately, we can’t just add the script to Intune and make the compliance check whether there is a 0 or 1 exit code. (This would make this a bit easier)
We need to create a detection script (Powershell) that outputs a JSON value and compares that to a JSON file with the same values.
This is the detection script that outputs the JSON value:
$url = Invoke-WebRequest http://ip.zscaler.com/ $checkzscaler = ($URL.ParsedHtml.getElementsByTagName('div') | Where-Object{ $_.className -eq 'headline' }).innertext $ZScalerStatus = @{"ZScalerStatus" = $checkzscaler} return $ZScalerStatus | ConvertTo-Json -Compress
Output: (This was run on a PC that doesn’t run ZScaler)

This is the JSON file for comparison:
{ "Rules":[ { "SettingName":"ZScalerStatus", "Operator":"NotEquals", "DataType":"String", "Operand":"The request received from you didn't come from a Zscaler IP therefore you are not going through the Zscaler proxy service.", "MoreInfoUrl":"https://help.zscaler.com/client-connector/using-zscaler-client-connector", "RemediationStrings":[ { "Language":"en_US", "Title":"ZScaler Internet Access must be running.", "Description": "Please make sure that the ZScaler Internet Access is running." } ] } ] }
As you can see, I do a reverse check. When the ZScaler status is not equal to the “Operand” value, you are compliant.
This is the information that the JSON file must hold (Copied from Peter van der Woude):
- SettingName – The name of the custom compliance setting, as returned by the PowerShell script
- Operator – The operator (IsEquals, NotEquals, GreaterThan, GreaterEquals, LessThan, LessEquals) that specifies the action that is used for the compliance rule
- DataType – The type of data (Boolean, Int64, Double, String, DateTime, Version) that specifies the data, as returned by the PowerShell script
- Operand – The operand represents the values that the operator works on
- MoreInfoURL – The URL that provides more information about the custom compliance setting
- RemediationStrings – The information that provides information about the non-compliance
Intune Custom Compliance Policy
Lastly, we add the configuration to the Intune compliance policy. Login to Microsoft Intune, go to the compliance blade, and click on scripts:

After that, add the detection script:

Name the policy and click on next:

Paste the detection script in the script area and leave the rest as-is:

Click on create in the review and create section.
Next, go to the compliance policy where you want to add the ZScaler check and edit the compliance settings. After that edit the custom compliance area, and fill in all the variables:

That makes your custom compliance policy check the ZScaler status in Intune! This is the result:

References
Custom Compliance by Peter van der Woude
Other posts:
Windows Autopatch: Notes from the field
Use Winget with Intune
Hello, thx for the info.
Is it working if we have computers in French AND in English? In case the output is in French. Is there a way to adapt the json file.
To handle all languages we have in our company with only one custom compliance policy.
Hi Francois,
That’s an interesting usecase. If you only have french and English, is it an option to create seperate compliance policies and assign them based on a dynamic group which populates on the operating system language?
Thanks,
Niels
Hi Francois,
Great post and exactly what I am looking for. However when I ran the detection script on a cleanly installed machine. I get the following response
Invoke-WebRequest : The response content cannot be parsed because the Internet Explorer engine is
not available, or Internet Explorer’s first-launch configuration is not complete. Specify the
UseBasicParsing parameter and try again.
So I updated the script to use $url = Invoke-WebRequest -UseBasicParsing http://ip.zscaler.com/
However the ParsedHtml is then blank. My understanding of this is very limited and would love some help. As I htin that with the removal of IE this will not work on most devices in our environment, as they are all newly deployed with AutoPilot and Edge as default browser.
Hi Tom,
Thanks for your message. On what client do you run the script? W11 22H2? Do you block Internet Explorer or?
Did you never use the browser with the account that you run the script as? Can you check this blog:
https://wahlnetwork.com/2015/11/17/solving-the-first-launch-configuration-error-with-powershells-invoke-webrequest-cmdlet/
Thanks,
Niels
Thank you for this script. I have created this script as you described but on my test machines I am getting “Not Applicable”. Any thoughts?
Hi Kevin,
Did you filter them out? That would make them non applicable.
Thanks,
Niels
Hey, I’ve had this same issue and managed to resolve the issue for our client :
1. When I ran the invoke-webrequest on my targeted SOE device, an error was spat: “The response content cannot be parsed because the Internet Explorer engine is not available, or Internet Explorer’s first-launch configuration is not complete. Specify the UseBasicParsing parameter and try again.” However, using the -UseBasicParsing parameter returned a $NULL value. To resolve the error, we added this registry key/value: HKLM:\SOFTWARE\Policies\Microsoft\Internet Explorer\Main\DisableFirstRunCustomize and set to ‘1’.
2. When I tried to access ip.zscaler.com from the target device, it was found this url is blocked by Zscaler. In our very locked down environment, we had to whitelist each business url and Zscaler urls/fqdns are no exception. To resolve, I had to manually whitelist the URL in ZIA.
I hope this helps with your troubleshooting. Good luck!
Thanks for your contribution!