1. Registry Configuration
All settings are read from a single registry key. Deploy via GPO Preferences, Intune OMA-URI, SCCM, or any registry tool.
Prefer Group Policy? Every value on this page is also available as a proper Administrative Template, with explain text, drop-down lists and range validation.
Download the ADMX / ADML templates →
HKLM\SOFTWARE\Policies\MDE-Toolkit
1.1 Background Collector
| Value Name | Type | Default | Description |
EnableBackgroundCollector | DWORD | 0 | 1 = enable, 0 = off |
CollectionIntervalMinutes | DWORD | 480 | Minutes between collections (min 5) |
CacheFolder | SZ | %ProgramData%\MDE-Toolkit\cache | Local cache folder |
MaxCacheFiles | DWORD | 48 | Rolling file count |
CacheRetentionDays | DWORD | 30 | Delete older than N days (0 = no limit) |
1.2 Upload: Function App
| Value Name | Type | Default | Description |
EnableUpload | DWORD | 0 | 1 = enable upload |
FunctionAppUrl | SZ | | e.g. https://func-mde-toolkit.azurewebsites.net/api/HealthReportIngestion |
FunctionAppAudience | SZ | | e.g. api://mde-toolkit-func |
UploadIntervalMinutes | DWORD | 480 | Upload frequency (min 5) |
UploadTimeoutSeconds | DWORD | 30 | HTTP POST timeout (5–300) |
UploadRetryCount | DWORD | 2 | Retries on failure (0–10) |
1.3 Upload: Direct Blob Storage (Alternative)
| Value Name | Type | Default | Description |
EnableBlobUpload | DWORD | 0 | 1 = enable blob upload |
BlobStorageAccountName | SZ | | Storage account name |
BlobContainerName | SZ | mde-telemetry | Container name |
BlobEndpointSuffix | SZ | | e.g. blob.core.usgovcloudapi.net |
1.4 Identity / Authentication
| Value Name | Type | Default | Description |
TenantId | SZ | (auto) | Auto-detected from PRT if blank |
PreferredAuthMethod | SZ | Default | Default (WAM broker, then non-interactive fallbacks) | WAM | DeviceCode | ManagedIdentity. Scheduled uploads never display a sign-in prompt. |
AuthClientId | SZ | (auto) | Optional, but recommended for production. App (client) ID of the public client registration used for WAM/broker sign-in. When set, it is used on its own. When blank, the app ID inside FunctionAppAudience is tried first — which is already correct for the common setup where one registration both exposes the API and acts as the client — then the built-in Azure CLI client. Leaving it blank can mean your API is reached through Microsoft's own registration, so anyone with the Azure CLI can request tokens for it and Conditional Access cannot target an app you control. Whichever registration is used needs redirect URI ms-appx-web://microsoft.aad.brokerplugin/<client-id> registered under "Mobile and desktop applications", public client flows enabled, access to the exposed scope, and — if blob upload is enabled — a delegated user_impersonation permission on Azure Storage. |
AzureEnvironment | SZ | Public | Public | USGov | China | Germany |
AuthorityHostOverride | SZ | (auto) | Custom Entra authority URI for sovereign / air-gapped clouds (e.g. https://login.microsoftonline.us/) |
1.5 Data Scope
Control which telemetry categories are collected. All DWORD, 1 = on, 0 = off.
| Value Name | Default | Description |
CollectDefenderStatus | 1 | RTP, Tamper, Signatures, engine + platform versions, scan times |
CollectDefenderPolicies | 1 | ASR, NP, CFA, Device Control |
CollectFirewallStatus | 1 | Domain/Private/Public profiles |
CollectAppControl | 1 | WDAC status + .cip policy count |
CollectDeviceGuard | 1 | VBS, HVCI, Credential Guard |
CollectIntuneEnrollment | 1 | Intune / ConfigMgr info |
1.6 Tagging / Organization
These values are written to the JSON snapshot and promoted to their own columns (DeviceTag, OrgUnit, Environment) in the Azure Table so Power BI can slice on them.
| Value Name | Type | Description |
DeviceTag | SZ | Freeform label — e.g. Finance |
OrgUnit | SZ | e.g. US-East |
Environment | SZ | Production | Staging | Dev |
1.7 UI / Feature Flags
Control the interactive WPF application (not the background collector). All DWORD, default 0.
| Value Name | Description |
DisableExportButtons | Block every export path — report PDF/HTML, triage report, scan results, ASR event CSV, Advanced Hunting CSV/XML, WDAC XML, firewall migration JSON, investigation CSV. Blocked attempts show an explanatory dialog. |
DisableRemoteTarget | Pin the toolkit to the local machine. The Target box is disabled and any non-local value is rejected, so no remote-capable service can be reached. |
ForceReadOnlyMode | Disable all write operations (remediation, policy push, ASR exclusions) |
ShowPreviewFeatures | Reveal features still marked Preview, currently Machine Investigator. Preview features are functional but may change between releases — consider a pilot group first. |
Removed in 3.3.2. Seven values were previously accepted but never acted on, so setting them had no effect:
CollectFirewallRules, CollectWfpFilters, CollectDeviceControl,
CollectNetworkInfo, CollectSecurityScore, DisableAiFeatures and
DisableAdvancedNetworking. The installer no longer writes them and the app ignores them if present —
delete them so the policy key reflects only settings that are live.
To hide the AI or Networking surfaces, use VisibilityAiAnalysisPage and
VisibilityNetworkingPage (section 1.9), which are enforced. DisableExportButtons and DisableRemoteTarget were in the same non-functional state
and are now genuinely enforced rather than removed.
1.8 ASR Exclusion Guardrails
Restrict what administrators may create from ASR Rules → Events. All values are optional; a device with none of them set behaves as before (4h / 24h / 7d / 30d plus Permanent).
| Value Name | Type | Default | Description |
AsrAllowPermanentExclusions | DWORD | 1 | 0 removes Permanent, forcing every exclusion to expire |
AsrAllowTemporaryExclusions | DWORD | 1 | 0 removes all temporary durations |
AsrExclusionMaxHours | DWORD | 0 | Hard cap in hours; 0 = uncapped. Applied last, so it cannot be widened by the list below |
AsrExclusionDurationsHours | SZ | 4,24,168,720 | Duration menu in hours, comma-separated. Unparseable entries are ignored and reported |
reg add "HKLM\SOFTWARE\Policies\MDE-Toolkit" /v AsrAllowPermanentExclusions /t REG_DWORD /d 0 /f
reg add "HKLM\SOFTWARE\Policies\MDE-Toolkit" /v AsrExclusionMaxHours /t REG_DWORD /d 4 /f
Guardrails, not a boundary. These prevent accidental long-lived exclusions and configuration drift. They do not stop a determined local administrator, who can call Add-MpPreference directly — the toolkit's audit ledger is what makes that visible. Setting ForceReadOnlyMode to 1 blocks every exclusion write, both creation and removal.
1.9 Page Visibility
Show or hide individual pages in the interactive application, per elevation level. All DWORD.
| Value | Meaning |
0 | Hidden for everyone |
1 | Visible only when the app is running elevated |
2 | Visible only to standard (non-elevated) users |
3 | Visible in both cases |
| Value Name | Default | Page |
VisibilityAsrDashboardPage | 1 | ASR Rules overview |
VisibilityAsrEventsPage | 1 | ASR Rules → Events. 3 gives standard users read-only triage; exclusion actions stay admin-gated regardless |
VisibilityMdePoliciesPage | 1 | Defender policies |
VisibilityFirewallPage | 1 | Firewall |
VisibilityWfpFiltersPage | 1 | WFP filters |
VisibilityFwMigrationPage | 1 | Firewall migration |
VisibilityDCPoliciesPage | 1 | Device Control policies |
VisibilityCiToolPage | 1 | CiTool integration |
VisibilityAppControlAdvancedHuntingPage | 1 | App Control → Advanced Hunting |
VisibilityMachineInvestigatorPage | 1 | Machine Investigator. Also requires ShowPreviewFeatures = 1 |
VisibilityNetworkingPage | 1 | Advanced networking |
VisibilityAiAnalysisPage | 0 | AI Analysis. Hidden by default because it sends configuration data to an AI endpoint you configure |
Hiding a page is a UI decision, not an access control. It removes the page from navigation; it does not prevent the underlying Windows functionality being used by other means. Pair it with ForceReadOnlyMode where the intent is to prevent change.
1.10 Logging
Local service log written by the background collector and upload loops.
| Value Name | Type | Default | Description |
LogLevel | SZ | Info | None | Error | Warning | Info | Verbose |
LogFilePath | SZ | (CacheFolder)\service.log | Custom log path |
MaxLogSizeMb | DWORD | 10 | Rotate at this size (1–500 MB) |
1.11 Example: GPO / Intune Deployment
$regPath = "HKLM:\SOFTWARE\Policies\MDE-Toolkit"
New-Item -Path $regPath -Force | Out-Null
Set-ItemProperty $regPath -Name EnableBackgroundCollector -Value 1 -Type DWord
Set-ItemProperty $regPath -Name EnableUpload -Value 1 -Type DWord
Set-ItemProperty $regPath -Name FunctionAppUrl -Value "https://func-mde-toolkit.azurewebsites.net/api/HealthReportIngestion"
Set-ItemProperty $regPath -Name FunctionAppAudience -Value "api://mde-toolkit-func"
Set-ItemProperty $regPath -Name AzureEnvironment -Value "Public"
Set-ItemProperty $regPath -Name DeviceTag -Value "Finance"
Set-ItemProperty $regPath -Name OrgUnit -Value "US-East"
Set-ItemProperty $regPath -Name CacheRetentionDays -Value 30 -Type DWord
1.12 New Table Columns (v3.2+)
Recent client + Function App updates added the following columns to each row upserted into Azure Table Storage. Existing Power BI reports do not need to change — new columns simply become available for slicing.
| Column | Source | Notes |
DeviceTag, OrgUnit, Environment | Registry (section 1.6) | Promoted from JSON body to top-level columns |
IpAddress | First non-loopback IPv4 | NetworkInterface enumeration |
LastBootTimeUtc | Environment.TickCount64 | ISO 8601 UTC |
LastQuickScanUtc, LastFullScanUtc | MSFT_MpComputerStatus age fields, registry fallback | ISO 8601 UTC |
AntivirusEngineVersion | AMEngineVersion, filesystem fallback | MpEngine.dll version |
PlatformVersion | AMProductVersion, registry & folder-name fallbacks | Defender platform version |
SignatureVersion | CIM + AVSignatureVersion registry | Definition version |
ServiceVersion | AMServiceVersion | Defender service version |
MdeOrgId | Registry Windows Advanced Threat Protection\Status\OrgId | Empty if not onboarded |
AppControlPolicyCount | C:\Windows\System32\CodeIntegrity\CIPolicies\Active\*.cip | File count, not enforcement |
AppControlStatus | KMCI + policy count | Enforced | Audit | Configured (N policies, not enforced) | NotConfigured |
PowerShellExecutionPolicy | Machine policy → per-shell → default | Restricted / RemoteSigned / AllSigned / Bypass / etc. |
SmartScreenExplorerMode | Registry Explorer\SmartScreenEnabled | Raw string (RequireAdmin, Warn, Off) |
Azure Table Storage is schemaless per row. Existing rows keep their original columns — only newly upserted rows carry the new fields.
1.13 Fields fixed in v3.3.3
These columns existed in the schema but were never populated by the collector: they were uploaded at their default value on every device. A dashboard reading them saw false or 0 and could not tell that apart from a real measurement.
| Column | Was | Now |
ExploitProtectionDepEnabled, ExploitProtectionAslrEnabled, ExploitProtectionCfgEnabled |
Always false — never read |
Decoded from MitigationOptions under Session Manager\Kernel. A read failure now sets ExploitProtectionStatus to Unknown rather than leaving false to look like a measurement. |
LocalAdminCount |
Always 0, which is impossible — every install has the built-in Administrator |
Counted via NetLocalGroupGetMembers resolved by well-known SID S-1-5-32-544, so it works on non-English installs. LocalAdminStatus now reflects the count, not just LAPS. |
AppControlEnforcementMode |
Not written at all |
Enforced | Audit | Deployed | NotConfigured. Deployed means .cip policies are present but Code Integrity is not running them. |
LastQuickScanUtc, LastFullScanUtc |
Blank when the scan ran today |
The age test was > 0; a scan that ran today has age 0, so the freshest devices reported as never scanned. Now >= 0. |
Existing rows are not backfilled. Devices must upload at least once on 3.3.3 before these columns mean anything, and rows written by older agents keep their misleading defaults. Slice on ServiceVersion to see how far the rollout has reached, and consider deleting pre-3.3.3 rows if the false zeros would skew a report.