
Intune Security Baselines vs CIS Benchmarks: A Decision Guide
Compare Intune security baselines against CIS benchmarks using a PowerShell export-and-diff workflow. Includes ASR deployment, deviation tracking, and a decision framework.
Try BaselineForge: If you'd rather do this interactively than in PowerShell, BaselineForge is the companion tool for this post. Load your Intune config, compare it against Microsoft's baseline, NCSC guidance, and our curated recommendations, then export deployable Intune policies. Everything runs in your browser. Your security configuration never leaves your machine.
Microsoft's Intune security baselines are one of those features that sound like the answer to a question nobody asked properly. "We need to secure our endpoints." "Great, deploy the baseline." Three months later, you're troubleshooting why a line-of-business application crashes on launch, a printer driver refuses to install, and a team of developers can't run unsigned scripts. Nobody can explain which settings caused which problems, because nobody reviewed what the baseline actually contains before deploying it.
The alternative isn't to ignore baselines. It's to understand what they are, what they're not, and how to make an informed decision about whether to adopt them wholesale, cherry-pick settings, or build your own from a framework like CIS. That decision should be deliberate and documented.
This post provides the methodology for a structured security baseline comparison. We'll export Microsoft's baselines, compare them against CIS benchmarks, identify the deviations that matter, and build a decision framework your team can apply consistently. If you're already running a Configuration as Code practice, these profiles slot directly into your pipeline. If you're not, the standardisation post covers why you should be.
Prerequisites: Scripts use the Microsoft Graph PowerShell SDK v2.x with PowerShell 7+. For Graph API patterns, see Graph API for Architects.
What Microsoft's Security Baselines Actually Are
A security baseline in Intune is a pre-configured set of Windows settings that Microsoft considers a reasonable security posture for enterprise devices. It's published as an Intune profile template that you can deploy as-is or customise before deployment. Together, these templates form Microsoft's layered approach to endpoint hardening in Intune.
There are several baseline types:
| Baseline | Scope | Update Cadence |
|---|---|---|
| Windows Security Baseline | OS hardening (BitLocker, Defender AV, credential guard, audit policy, user rights) | Updated periodically alongside Windows releases |
| Microsoft Defender for Endpoint Baseline | EDR-specific settings (cloud protection, sample submission, ASR rules, network protection) | Updated with Defender feature releases |
| Microsoft Edge Baseline | Browser security (SmartScreen, extensions, site isolation) | Updated periodically with Edge releases |
| Microsoft 365 Apps Baseline | Office application security (macro policy, ActiveX, add-in management) | Updated with M365 Apps releases |
The Windows Security Baseline is the one that gets the most attention and causes the most trouble.
What They Get Right
Microsoft's baselines aren't bad. They represent a genuine security engineering effort, and they have several real advantages:
They exist. For organisations starting from nothing, a curated set of endpoint hardening settings is better than the Windows defaults. The difference between "we deployed the baseline" and "we have no endpoint hardening" is enormous.
They're tested against the Windows ecosystem. Microsoft tests these settings against their own application compatibility matrix. A CIS benchmark author doesn't have access to the same compatibility data that Microsoft's internal teams do.
They version alongside the OS. When a new Windows release changes a security default or adds a new capability, the baseline updates to reflect it. You don't have to track those changes yourself.
They deploy through Intune natively. No custom OMA-URI settings, no ADMX ingestion, no Settings Catalog spelunking. The baseline template surfaces the settings with descriptions and recommended values in a single profile.
Where They Fall Short
They're opaque about rationale. The baseline tells you what to set, not why. When PreventInstallationOfMatchingDeviceIDs is enabled, is that protecting against BadUSB attacks, preventing users from installing unauthorised peripherals, or both? Without rationale, you can't make an informed decision about whether to keep, modify, or remove a setting for your environment.
They bundle too many settings together. The Windows Security Baseline contains over 300 individual settings. Deploying all 300 as a single profile means you can't isolate which setting caused a problem. When something breaks, you're left binary-searching through hundreds of settings to find the culprit.
They don't align to a published framework. The baselines are "Microsoft's opinion." That's not a criticism of their quality, but it's a problem for organisations that need to demonstrate compliance against a specific framework like the Centre for Internet Security (CIS) benchmarks, NIST 800-53, or DISA STIG. An auditor asking "show me your CIS Level 1 compliance" won't accept "we deployed Microsoft's baseline" as evidence without a mapping exercise.
They can conflict with other profiles. If you deploy the security baseline and separately configure Defender AV settings through an endpoint security policy, the overlapping settings create a conflict. Intune marks conflicting settings with a "Conflict" status in the device report, and neither value is applied until the conflict is resolved. The device is left in its current or default state for those settings. The portal can still show both profiles as "applied" at the profile level, which masks the fact that individual settings within them are not being enforced.
Version upgrades aren't incremental. When Microsoft releases a new baseline version, you can't upgrade your existing deployment. You have to create a new profile from the new template, compare it to your customised version of the old one, and deploy the new one alongside (or replacing) the old. Any customisations you made to the previous version must be manually re-applied.
What CIS Benchmarks Offer Instead
The Centre for Internet Security (CIS) publishes detailed benchmarks for Windows, covering the same ground as Microsoft's baselines but with critical differences in approach.
Structure
CIS benchmarks are organised into two levels:
- Level 1: Settings that improve security without significant functionality impact. Intended for all systems.
- Level 2: Additional hardening for environments where security takes priority over usability. Expect application compatibility issues.
Each setting in a CIS benchmark includes:
| Field | What It Contains |
|---|---|
| Description | What the setting does |
| Rationale | Why it matters, what attack it mitigates |
| Impact | What breaks if you enable it |
| Audit | How to verify it's applied (registry key, PowerShell command) |
| Remediation | How to set it (Group Policy path, registry path, and increasingly Intune CSP paths in newer benchmark versions) |
| CIS Controls mapping | Which CIS Control (v8) the setting satisfies |
| Default value | What Windows ships with by default |
This is the documentation that Microsoft's baselines lack. When a setting causes a problem, the CIS impact statement tells you what to expect. When an auditor asks why a setting is configured, the rationale provides the answer.
The Trade-Off
CIS benchmarks are more work to implement. You can't deploy them as a single Intune template. Each setting must be configured individually through the Settings Catalog, endpoint security profiles, or custom OMA-URI policies. For an organisation without automation, implementing CIS Level 1 (over 400 recommendations for Windows 11) is a significant manual effort.
This is where Configuration as Code pays for itself. If your security profiles are defined in code and deployed through a pipeline, the effort to implement CIS is the same as implementing Microsoft's baseline: define the settings, test them, deploy them. The ongoing maintenance burden is actually lower because CIS provides version-to-version changelogs that tell you exactly what changed.
How to Compare Intune Baselines Against CIS Benchmarks
The question isn't "Microsoft or CIS?" in the abstract. It's "where do they agree, where do they differ, and do the differences matter for my environment?" Here's the methodology I use to answer that.
Step 1: Export the Microsoft Baseline
The most reliable way to export baseline settings is from a deployed baseline instance (an "intent" in Graph API terms), not from the template definition. Deploy the baseline to a test group first, then export its configured settings.
Note: Microsoft has been migrating security baselines from the legacy "intents" format to the Settings Catalog format. Baselines created from templates released after November 2023 use Settings Catalog and won't appear via the
/intentsendpoint below. For those newer baselines, use/beta/deviceManagement/configurationPolicies?$filter=templateReference/templateFamily eq 'baseline'instead. The companion repo handles both formats.
Connect-MgGraph -Scopes "DeviceManagementConfiguration.Read.All"
# Get all security baseline templates
$templates = Invoke-MgGraphRequest -Method GET `
-Uri "https://graph.microsoft.com/beta/deviceManagement/templates?`$filter=templateType eq 'securityBaseline'"
$templates.value | Select-Object id, displayName, publishedDateTime |
Format-Table -AutoSize
# Get deployed baseline instances (intents)
$intents = Invoke-MgGraphRequest -Method GET `
-Uri "https://graph.microsoft.com/beta/deviceManagement/intents"
# Find the Windows Security Baseline intent
$baselineIntent = $intents.value | Where-Object {
$_.displayName -like "*Windows*Security*"
} | Select-Object -First 1
# Export settings from the deployed instance
$categories = Invoke-MgGraphRequest -Method GET `
-Uri "https://graph.microsoft.com/beta/deviceManagement/intents/$($baselineIntent.id)/categories"
$allSettings = foreach ($category in $categories.value) {
$settings = Invoke-MgGraphRequest -Method GET `
-Uri "https://graph.microsoft.com/beta/deviceManagement/intents/$($baselineIntent.id)/categories/$($category.id)/settings"
foreach ($setting in $settings.value) {
[PSCustomObject]@{
Category = $category.displayName
SettingName = $setting.displayName
DefinitionId = $setting.definitionId
ConfiguredValue = $setting.value
}
}
}
$allSettings | Export-Csv "$env:TEMP\MSBaseline_Export.csv" -NoTypeInformation
Write-Host "Exported $($allSettings.Count) baseline settings"Step 2: Map CIS Recommendations
A note on CIS copyright: CIS benchmark content (recommendation titles, descriptions, and values) is copyrighted by the Centre for Internet Security. We can't redistribute it, which is why the companion repo includes a blank mapping template rather than a pre-populated one. The methodology in this post works with any CIS data you supply. You'll need to obtain your own copy of the benchmark (free PDF or SecureSuite Excel) and populate the mapping yourself. The scripts and comparison logic are yours to use; the CIS data is not ours to give.
CIS benchmarks are published as PDF and Excel. The Excel version (available to CIS SecureSuite members) is what you want for comparison. If you don't have SecureSuite access, the free PDF works but requires manual extraction. (Hint: give the PDF to Copilot or Claude and tell it to extract the recommendations for you.)
The mapping key is the Windows CSP (Configuration Service Provider) path. Both Microsoft's baseline and CIS reference the same underlying CSP settings, but they use different naming conventions. A lookup table bridges the gap:
# Build a mapping between CIS recommendations and Intune CSP paths
# This is a simplified example showing the mapping format
# The companion repo has a blank template (mappings/cis-mapping-template.csv)
# Populate it from your CIS SecureSuite export or manual PDF extraction
$cisMapping = @(
@{
CISId = "1.1.1"
CISTitle = "Password history requirement (24+)"
CISLevel = 1
DefinitionId = "deviceConfiguration--windows10GeneralConfiguration_passwordPreviousPasswordBlockCount"
CISValue = "24"
CISRationale = "Prevents password reuse across 24 changes"
},
@{
CISId = "2.3.1.1"
CISTitle = "Block Microsoft account sign-in"
CISLevel = 1
DefinitionId = "deviceConfiguration--windows10GeneralConfiguration_localSecurityOptionsBlockMicrosoftAccounts"
CISValue = "true"
CISRationale = "Prevents users from adding Microsoft accounts for application auth"
}
# Populate from your CIS SecureSuite export using the template
# in the companion repo (mappings/cis-mapping-template.csv)
)
$cisMapping | ForEach-Object { [PSCustomObject]$_ } |
Export-Csv "$env:TEMP\CISMapping.csv" -NoTypeInformationStep 3: Diff the Two
This is where the value lives. Comparing the Microsoft baseline against CIS reveals three categories of settings:
param(
[string]$MSBaselinePath = "$env:TEMP\MSBaseline_Export.csv",
[string]$CISMappingPath = "$env:TEMP\CISMapping.csv"
)
$msBaseline = Import-Csv $MSBaselinePath
$cisMapping = Import-Csv $CISMappingPath
# Use explicit definitionId matching for reliability
# The companion repo includes a complete mapping table
$comparison = foreach ($cis in $cisMapping) {
$msMatch = $msBaseline | Where-Object {
$_.DefinitionId -eq $cis.DefinitionId
}
$status = if (-not $msMatch) {
"CIS Only"
} elseif ($msMatch.ConfiguredValue -eq $cis.CISValue) {
"Aligned"
} else {
"Differs"
}
[PSCustomObject]@{
CISId = $cis.CISId
CISTitle = $cis.CISTitle
CISLevel = $cis.CISLevel
CISValue = $cis.CISValue
MSValue = $msMatch.ConfiguredValue
Status = $status
Rationale = $cis.CISRationale
}
}
$comparison | Group-Object Status |
ForEach-Object { Write-Host "$($_.Name): $($_.Count) settings" }
# Export deviations for review
$comparison | Where-Object { $_.Status -ne "Aligned" } |
Export-Csv "$env:TEMP\BaselineDeviations.csv" -NoTypeInformation
Write-Host "`nDeviations exported to $env:TEMP\BaselineDeviations.csv"The output falls into three buckets:
Aligned: Both Microsoft and CIS recommend the same value. Deploy these with confidence. In practice, 60-70% of settings fall into this category.
Differs: Microsoft and CIS recommend different values for the same setting. These require a decision. Document whether you follow Microsoft's recommendation, CIS's recommendation, or your own value, and why.
CIS Only: CIS recommends a setting that Microsoft's baseline doesn't include. These are typically more aggressive hardening measures. Evaluate each one against your application compatibility requirements.
Step 4: Document Your Deviations
This is the step most organisations skip, and it's the most important one. Every deviation from either baseline needs a documented justification:
# Deviation tracker template
$deviationTracker = @(
@{
CISId = "18.9.27.1"
Setting = "Configure Attack Surface Reduction rules"
CISRecommends = "Block all Office applications from creating child processes"
MSRecommends = "Audit mode"
OurValue = "Audit mode (Phase 1), Block (Phase 2 after 90 days)"
Justification = "Finance team uses Excel macros that spawn helper processes. Audit mode first to identify impact, block after remediation."
Owner = "Security Team"
ReviewDate = "2026-06-24"
TicketRef = "SEC-1234"
}
)
$deviationTracker | ForEach-Object { [PSCustomObject]$_ } |
Export-Csv "$env:TEMP\DeviationTracker.csv" -NoTypeInformationThe deviation tracker is your audit evidence. When a compliance assessor asks "why is this CIS Level 1 setting not enforced?", the answer is a documented, reviewed, time-bound decision with an owner and a review date. That's fundamentally different from "we didn't know about it."
Automate This With BaselineForge
The methodology above works, but it involves a lot of PowerShell, CSV manipulation, and manual comparison. If you want to do this interactively, BaselineForge is the companion tool for this post. It automates the export-compare-decide-export workflow entirely in your browser.
What it does:
- Loads your Intune configuration (CSV or JSON from the export script above) and compares it against multiple baselines simultaneously
- Ships a curated "BaselineForge Recommended" baseline with independent rationale for every setting, covering the same ground as CIS Level 1
- Compares against Microsoft's baseline so you can see where Microsoft and the recommendations agree and where they differ
- Maps NCSC Device Security Guidance principles to your settings, showing compliance at the principle level
- Accepts your CIS Excel (SecureSuite format) as an optional overlay for formal CIS compliance mapping
- Lets you document deviations inline with justification, owner, review date, and ticket reference
- Exports deployable Intune JSON grouped by category, ready for
Invoke-MgGraphRequest
Everything runs client-side. Your security configuration never leaves your browser. There is no server, no account, no telemetry. The tool processes your data in JavaScript on your machine and nowhere else.
If you don't have an Intune export to hand, you can also use BaselineForge to browse the recommended settings by category, read the rationale for each one, and build a baseline from scratch.
Microsoft Baseline vs CIS: Which Should You Use?
With the comparison data in hand, use this framework to decide your approach. The right answer depends on your compliance requirements, team maturity, and application estate.
Option 1: Deploy Microsoft's Baseline As-Is
When this works:
- You have no specific compliance framework requirement (no CIS, NIST, or DISA STIG mandate)
- Your application estate is predominantly Microsoft-native (M365 Apps, Edge, modern web apps)
- You're starting from zero endpoint hardening and need to improve your posture quickly
- You have limited security engineering capacity
When this doesn't work:
- You need to demonstrate CIS or NIST compliance to auditors
- You have legacy applications with known compatibility sensitivities
- You're already managing endpoint security through other profiles and need to avoid conflicts
How to deploy it safely:
- Create the baseline profile from the latest template
- Assign it to a pilot group (not "All Devices")
- Monitor for 30 days: application crashes, driver issues, user complaints
- Document any settings you customise and why
- Expand to broader deployment rings
The biggest risk with this option isn't the initial deployment. It's the version upgrade. When Microsoft releases a new baseline, you'll need to compare your customised old version against the new template, identify what changed, and decide whether the new recommendations are appropriate for your environment. Without automation, this is tedious and error-prone.
Option 2: Use CIS as Your Primary Framework
When this works:
- You have a compliance requirement that maps to CIS Controls
- Your security team has the capacity to implement and maintain 400+ individual settings
- You're running a Configuration as Code pipeline that can manage profile-as-code
- You want documented rationale for every security setting
When this doesn't work:
- You don't have SecureSuite membership (the free PDF is workable but slow)
- Your team lacks the Intune Settings Catalog expertise to translate CIS recommendations into profiles
- You need a quick win and can't invest in the mapping exercise upfront
How to implement it:
- Start with CIS Level 1 only. Level 2 is for high-security environments and will cause compatibility issues
- Group settings by category (account policies, audit policies, user rights, security options, Defender, ASR)
- Create one Intune profile per category, not one profile for everything
- Deploy to a pilot ring and test for 30 days per category
- Track deviations from the benchmark with justification
Option 3: Hybrid (My Recommendation for Most Organisations)
Start with Microsoft's baseline as the foundation. It covers the core endpoint hardening settings, deploys cleanly through Intune, and gives you immediate value.
Layer CIS-only settings on top as separate profiles. These are the settings CIS recommends but Microsoft's baseline doesn't include. Deploy them incrementally, category by category, with testing between each deployment.
Document every deviation from both baselines. The deviation tracker becomes your living compliance document.
This approach gives you:
- Fast initial value (Microsoft baseline in week 1)
- Compliance mapping (CIS alignment over weeks 2-8)
- Documented posture (deviation tracker from day 1)
- Manageable maintenance (Microsoft baseline updates handled separately from CIS supplementary profiles)
Attack Surface Reduction: Intune's Most Underdeployed Security Feature
ASR rules deserve special attention because they're simultaneously the most impactful and least deployed security feature in Intune. They're included in Microsoft's Defender for Endpoint baseline, partially covered by CIS, and routinely left in audit mode or not deployed at all.
ASR rules are available with Defender Antivirus (included in Windows) but deliver their full value with Defender for Endpoint Plan 2, which provides the reporting, exclusion management, and advanced hunting capabilities you need to operate them at scale. If you're evaluating whether your organisation needs MDE P2, the E3 vs E5 decision framework covers the licensing analysis. If you're not sure how many MDE P2 or E5 licences you currently have deployed, the M365 licensing audit covers extracting that from Graph API.
Intune ASR Rules: Priority Order for Deployment
Not all ASR rules carry equal weight. Some are high-impact with low compatibility risk. Others will break legitimate workflows if deployed without testing. Here's the prioritisation I use:
Deploy first (low compatibility risk, high security value):
| Rule | GUID | What It Does |
|---|---|---|
| Block executable content from email client and webmail | BE9BA2D9-53EA-4CDC-84E5-9B1EEEE46550 | Prevents execution of .exe, .dll, .scr from Outlook and webmail |
| Block all Office applications from creating child processes | D4F940AB-401B-4EFC-AADC-AD5F3C50688A | Stops Office apps from launching PowerShell, cmd, mshta |
| Block Office applications from creating executable content | 3B576869-A4EC-4529-8536-B80A7769E899 | Prevents Office from writing .exe or .dll files to disk |
| Block JavaScript or VBScript from launching downloaded executable content | D3E037E1-3EB8-44C8-A917-57927947596D | Stops script engines from launching downloaded executables |
| Block execution of potentially obfuscated scripts | 5BEB7EFE-FD9A-4556-801D-275E5FFC04CC | Detects and blocks obfuscated scripts (PowerShell, VBScript, JavaScript) |
Deploy second (moderate compatibility risk, test thoroughly):
| Rule | GUID | What It Does |
|---|---|---|
| Block credential stealing from the Windows local security authority subsystem (lsass.exe) | 9E6C4E1F-7D60-472F-BA1A-A39EF669E4B2 | Prevents credential dumping from LSASS |
| Block process creations originating from PSExec and WMI commands | D1E49AAC-8F56-4280-B9BA-993A6D77406C | Blocks remote process creation via PSExec/WMI |
| Block persistence through WMI event subscription | E6DB77E5-3DF2-4CF1-B95A-636979351E5B | Prevents WMI-based persistence mechanisms |
| Use advanced protection against ransomware | C1DB55AB-C21A-4637-BB3F-A12568109D35 | Cloud-based heuristic for ransomware detection |
Deploy last (high compatibility risk, requires significant testing):
| Rule | GUID | What It Does |
|---|---|---|
| Block Win32 API calls from Office macros | 92E97FA1-2EDF-4476-BDD6-9DD0B4DDDC7B | Blocks any VBA macro using Win32 API Declare statements. Very high compatibility risk: affects corporate Excel workbooks extensively. Test thoroughly before enabling. |
| Block untrusted and unsigned processes that run from USB | B2B3F03D-6A65-4F7B-A9C7-1C7EF74A9BA4 | Blocks unsigned executables from removable media |
The Phased Rollout
ASR rules support three modes: Disabled, Audit, and Block. The correct deployment sequence is:
- Enable all rules in Audit mode across your pilot ring. This logs what would have been blocked without actually blocking it.
- Run audit mode for 30 days minimum. Without MDE P2, collect events locally via
Get-WinEvent -LogName "Microsoft-Windows-Windows Defender/Operational"(Event ID 1121 for block, 1122 for audit). With MDE P2, use advanced hunting for centralised visibility across your estate. - Review audit data. Identify legitimate processes that trigger rules. Create per-rule exclusions for those processes.
- Switch low-risk rules to Block mode in the pilot ring. Monitor for 14 days.
- Expand to broader rings following your standard deployment ring model.
If you have MDE P2 or M365 E5, advanced hunting gives you centralised ASR event data across all enrolled devices:
# Query ASR audit events via Defender for Endpoint advanced hunting
# Requires MDE P2 or M365 E5
$query = @"
DeviceEvents
| where ActionType startswith "Asr"
| where Timestamp > ago(30d)
| summarize
AuditCount = countif(ActionType endswith "Audited"),
BlockCount = countif(ActionType endswith "Blocked")
by RuleId = tostring(AdditionalFields.RuleId),
FileName,
FolderPath,
InitiatingProcessFileName
| sort by AuditCount desc
| take 50
"@
# Run via Microsoft Graph Security API
# Requires an app registration with ThreatHunting.Read.All application permission
# This is an app-only permission and cannot be used with interactive Connect-MgGraph
$huntBody = @{ Query = $query } | ConvertTo-Json
$results = Invoke-MgGraphRequest -Method POST `
-Uri "https://graph.microsoft.com/v1.0/security/runHuntingQuery" `
-Body $huntBody -ContentType "application/json"
$results.results | Format-Table -AutoSizeThe audit data tells you exactly which applications trigger which rules on which devices. Without this data, you're guessing at exclusions. With it, you can make precise, documented decisions about what to exclude and what to block.
Handling Baseline Conflicts in Intune
Profile conflicts are the silent killer of endpoint security configuration. When two profiles configure the same setting with different values, Intune doesn't silently pick one. It marks the setting as "Conflict" in the device's configuration report, and neither value is applied. The device keeps its current or default state for that setting. The dangerous part: at the profile level, both profiles can still show as "applied", masking the fact that individual settings within them aren't being enforced.
Common Conflict Scenarios
Microsoft baseline + Endpoint security profile. The security baseline configures Defender AV settings. You also have a separate endpoint security Antivirus profile that configures some of the same settings. Both deploy to the same devices.
Microsoft baseline + Settings Catalog profile. You deployed the baseline for quick wins, then started building CIS-aligned profiles through the Settings Catalog. The CIS profiles overlap with baseline settings.
Multiple Settings Catalog profiles. Two profiles created by different team members both configure BitLocker settings with different values.
Detection
Connect-MgGraph -Scopes "DeviceManagementConfiguration.Read.All"
# Get all configuration policies
$policies = Invoke-MgGraphRequest -Method GET `
-Uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies"
# Fetch settings for each policy (requires separate call per policy)
$settingMap = @{}
foreach ($policy in $policies.value) {
$settings = Invoke-MgGraphRequest -Method GET `
-Uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies/$($policy.id)/settings"
foreach ($setting in $settings.value) {
$defId = $setting.settingInstance.settingDefinitionId
if (-not $defId) { continue }
if ($settingMap.ContainsKey($defId)) {
$settingMap[$defId] += @($policy.name)
} else {
$settingMap[$defId] = @($policy.name)
}
}
}
# Find conflicts (same setting in multiple profiles)
$conflicts = $settingMap.GetEnumerator() | Where-Object { $_.Value.Count -gt 1 }
Write-Host "Settings configured in multiple profiles: $($conflicts.Count)"
$conflicts | ForEach-Object {
Write-Host "`n Setting: $($_.Key)"
$_.Value | ForEach-Object { Write-Host " Profile: $_" }
}Resolution
The resolution is architectural, not technical. Choose one of two patterns:
Pattern A: Baseline + Supplements. Deploy the Microsoft baseline as your foundation. Any additional settings (from CIS or your own requirements) go into supplementary profiles that explicitly avoid overlapping with baseline settings. This means reviewing every CIS recommendation against the baseline export before creating supplementary profiles.
Pattern B: Settings Catalog Only. Don't use the Microsoft baseline template at all. Implement everything through the Settings Catalog (or endpoint security profiles for Defender/Firewall/ASR). This gives you full control and eliminates the conflict risk, but requires more upfront work.
I recommend Pattern B for mature organisations with a CaC pipeline. Pattern A is pragmatic for teams that need quick wins and will mature their approach over time.
Implementing CIS Benchmarks in Intune: Building Settings Catalog Profiles
Whether you choose Option 2 or 3, you'll need to create Intune profiles from the comparison output. Here's the pattern for translating settings into Settings Catalog profiles via Graph API.
Create a Settings Catalog Profile
Connect-MgGraph -Scopes "DeviceManagementConfiguration.ReadWrite.All"
# Create a profile for account policies (CIS Section 1)
$profileBody = @{
name = "SEC - Account Policies (CIS L1)"
description = "CIS Windows 11 Level 1 - Account Policies. Deviations documented in deviation tracker."
platforms = "windows10"
technologies = "mdm"
settings = @(
@{
settingInstance = @{
"@odata.type" = "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance"
settingDefinitionId = "device_vendor_msft_policy_config_devicelock_devicepasswordhistory"
simpleSettingValue = @{
"@odata.type" = "#microsoft.graph.deviceManagementConfigurationIntegerSettingValue"
value = 24
}
}
},
@{
settingInstance = @{
"@odata.type" = "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance"
settingDefinitionId = "device_vendor_msft_policy_config_localpoliciessecurityoptions_accounts_blockmicrosoftaccounts"
choiceSettingValue = @{
"@odata.type" = "#microsoft.graph.deviceManagementConfigurationChoiceSettingValue"
value = "device_vendor_msft_policy_config_localpoliciessecurityoptions_accounts_blockmicrosoftaccounts_3"
children = @()
}
}
}
# Additional settings from CIS mapping...
)
} | ConvertTo-Json -Depth 10
$profile = Invoke-MgGraphRequest -Method POST `
-Uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies" `
-Body $profileBody -ContentType "application/json"
Write-Host "Created profile: $($profile.name) (ID: $($profile.id))"Profile Naming Convention
Use a naming convention that tells you where a setting came from and why:
SEC - {Category} ({Source} {Level})
Examples:
SEC - Account Policies (CIS L1)- CIS Level 1 account policy settingsSEC - ASR Rules (MS Baseline + CIS L1)- merged settings from both sourcesSEC - Credential Guard (CIS L2)- CIS Level 2, deployed only to high-security devicesSEC - Defender AV (MS Baseline)- Microsoft baseline Defender settings, no CIS additions
This convention makes the policy list self-documenting. Anyone looking at Intune can see the source and scope of each profile without opening it.
Maintaining Your Baseline Over Time
Deploying a baseline is 20% of the work. Maintaining it is the other 80%.
Quarterly Review Cycle
Every quarter, review your security profiles against three inputs:
- New Microsoft baseline versions. Did Microsoft release an updated baseline? What changed? Do the changes affect your environment?
- CIS benchmark updates. CIS publishes updates less frequently (typically annually), but when they do, the changelog tells you exactly which recommendations changed and why.
- Your deviation tracker. Are the deviations you documented still valid? Has the business context changed? Have the applications that caused compatibility issues been updated or retired?
# Check for new baseline template versions
$templates = Invoke-MgGraphRequest -Method GET `
-Uri "https://graph.microsoft.com/beta/deviceManagement/templates?`$filter=templateType eq 'securityBaseline'"
$templates.value |
Select-Object displayName, publishedDateTime, versionInfo |
Sort-Object publishedDateTime -Descending |
Format-Table -AutoSizeDrift Detection
If you're running Configuration as Code, drift detection is built into your pipeline. If you're not, periodically export your deployed profiles and compare them against your intended state:
# Export current deployed profile settings
$policySettings = Invoke-MgGraphRequest -Method GET `
-Uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$profileId')/settings"
$currentSettings = $policySettings.value | ForEach-Object {
[PSCustomObject]@{
SettingId = $_.settingInstance.settingDefinitionId
Value = ($_.settingInstance | ConvertTo-Json -Depth 5)
}
}
# Compare against your source-of-truth (e.g. exported JSON from your repo)
$intendedSettings = Get-Content "profiles/sec-account-policies.json" -Raw |
ConvertFrom-Json
# Diff logic here - full implementation in companion repo
Write-Host "Deployed settings: $($currentSettings.Count)"
Write-Host "Intended settings: $($intendedSettings.settings.Count)"The Configuration as Code post covers the broader drift detection and remediation pattern, and if you're exploring AI-assisted tooling for this, the AI endpoint management post covers automated drift detection with Copilot. For security profiles specifically, drift isn't just a hygiene problem. It's a security incident waiting to happen. A setting that was configured to "Block" and has drifted to "Not configured" is a gap in your defences that nobody's aware of.
Intune Security Baseline Implementation Timeline
Here's the recommended implementation sequence, assuming you're starting from scratch or replacing an ad-hoc set of profiles with a structured approach.
Start with the comparison and decision (weeks 1-2), then move into piloting and progressive rollout. The key is to resist the urge to deploy everything at once. Each phase validates the previous one.
Week 1: Export the current Microsoft baseline template, map it against CIS Level 1, and produce the deviation report.
Week 2: Review the deviation report with your security team. Choose Option 1, 2, or 3 from the decision framework. Document your choice and the rationale.
Weeks 3-4: Create your profiles (baseline, supplementary, or custom). Deploy to a pilot ring of 20-50 devices. Enable ASR rules in audit mode.
Weeks 5-8: Review application compatibility issues from the pilot. Document deviations for settings that need adjusting. Expand deployment ring by ring. Promote ASR rules from audit to block (low-risk rules first).
Week 9 onwards: Full deployment across managed devices. Deviation tracker complete. ASR rules in block mode (low and medium risk). Quarterly review cycle begins.
Next Steps: Conditional Access, ASR, and Your Security Stack
Security baselines are one layer of your endpoint hardening posture. They harden the OS configuration but don't address the full attack surface. The next layer is the endpoint security stack itself: Defender Antivirus configuration, Defender for Endpoint capabilities, and the ASR rules we covered in this post deserve their own deep dive on operational practices rather than just deployment.
If you haven't already established your Conditional Access baseline, do that first. Identity security is the foundation. Endpoint hardening builds on top of it.
If you're still on E3 and wondering whether MDE P2 is worth the investment for ASR reporting and advanced hunting, the E3 vs E5 decision framework works through that calculation. And if your broader endpoint management practice needs structure, the standardisation post covers the principles that make all of this sustainable.
If you want to skip the spreadsheet work and do this interactively, BaselineForge automates the comparison, deviation tracking, and policy export workflow from this post. Load your config, see the gaps, export what's missing.
Your security baseline isn't a one-time deployment. It's a living document that evolves with your threat landscape, your application estate, and the frameworks you're measured against. Treat it with the same rigour as your code, because that's exactly what it is.
Stay in the loop
New articles on M365 architecture, security baselines, and automation. No spam, just practical engineering content.