How to Build an App Control for Business Policy in Audit Mode
Building a current App Control for Business policy from a reference system, deploying it in audit mode, reviewing evidence, and enforcing it in rings.
App Control for Business is Microsoft’s current name for the technology formerly called Windows Defender Application Control (WDAC). It changes code trust from “run unless another control detects a reason to stop it” to “run only when an App Control policy authorizes it.” That can cover kernel drivers, user-mode executables, scripts, and installers, but only when the corresponding policy options and rules are present. A safe rollout therefore starts in audit mode, uses representative devices, and treats policy maintenance as an operational lifecycle.
Step 1: define the circle of trust and recovery path
List the Windows versions, device roles, software distribution channels, line-of-business applications, scripts, plug-ins, drivers, updaters, and emergency tools that must work. Separate fixed-workload systems from user workstations: scanning one “golden” server can be appropriate for a tightly controlled role, while a diverse desktop fleet usually needs managed-installer, reputation, publisher, or supplemental-policy design rather than one enormous snapshot.
Before deployment, document how to return a policy to audit mode or remove it, who holds signing keys, how offline recovery works, and which deployment rings can be stopped. Signed policies resist administrator-level tampering and can deliberately cause boot failure when altered; do not sign the first experimental policy merely because signing sounds more secure.
Step 2: use a clean reference system and Windows PowerShell
Microsoft’s ConfigCI cmdlets are easiest to use from elevated Windows PowerShell 5.1. Patch and inventory the reference machine, remove unapproved software, and preserve the scan warning log. The following example creates a multiple-policy-format audit policy for a fixed workload:
$PolicyDir = "$env:USERPROFILE\Desktop\AppControl"
$PolicyName = "FixedWorkload_Audit"
$PolicyXml = Join-Path $PolicyDir "$PolicyName.xml"
$WindowsAudit = "$env:windir\schemas\CodeIntegrity\ExamplePolicies\DefaultWindows_Audit.xml"
New-Item -ItemType Directory -Path $PolicyDir -Force | Out-Null
New-CIPolicy `
-FilePath $PolicyXml `
-Level SignedVersion `
-Fallback FilePublisher,FileName,Hash `
-ScanPath C:\ `
-UserPEs `
-MultiplePolicyFormat `
-OmitPaths C:\Windows,'C:\Program Files\WindowsApps\',C:\Windows.old\,C:\Users\ `
3> (Join-Path $PolicyDir "scan-warnings.txt")
-UserPEs is material: it adds the user-mode code-integrity option. Without it, a policy can contain only kernel-mode rules and fail to control ordinary applications in the way its operator expects. Publisher-oriented rules reduce maintenance compared with exact hashes, while fallbacks cover files that lack the preferred metadata; each broader rule also expands what is trusted, so review the result rather than treating generation as approval.
Step 3: merge the Windows baseline and identify the policy
The reference scan alone should not be the only source of rules needed for Windows to boot and operate. Merge it with Microsoft’s audit template, then set a stable name and version:
Merge-CIPolicy `
-OutputFilePath $PolicyXml `
-PolicyPaths $PolicyXml,$WindowsAudit
Set-CIPolicyIdInfo `
-FilePath $PolicyXml `
-PolicyName $PolicyName
Set-CIPolicyVersion `
-FilePath $PolicyXml `
-Version "1.0.0.0"
Review the XML and the scan warnings with the App Control Policy Wizard or a schema-aware diff. Confirm that expected Windows, Store, driver, application, script, and installer cases are represented and that broad path or signer rules do not authorize locations writable by ordinary users. The old Get-CIPolicy -FilePath ... example sometimes copied into runbooks is not a valid review step.
Step 4: make audit and recovery options explicit
Policy rule option 3 is Enabled:Audit Mode. Option 9 exposes advanced boot options and option 10 allows boot-audit-on-failure; Microsoft recommends recovery-oriented options when moving early rings toward enforcement.
Set-RuleOption -FilePath $PolicyXml -Option 3
Set-RuleOption -FilePath $PolicyXml -Option 6
Set-RuleOption -FilePath $PolicyXml -Option 9
Set-RuleOption -FilePath $PolicyXml -Option 10
Option 6 permits an unsigned policy, which is appropriate while the design and recovery workflow are being proven. Signing is a separate hardening phase with stricter update and removal requirements, Secure Boot dependencies, protected keys, and mandatory recovery testing.
Step 5: convert using the PolicyID as the binary filename
Multiple-policy-format binaries must be named with the policy GUID, not an arbitrary friendly filename:
[xml]$Policy = Get-Content -Path $PolicyXml
$PolicyId = $Policy.SiPolicy.PolicyID
$PolicyBinary = Join-Path $PolicyDir "$PolicyId.cip"
ConvertFrom-CIPolicy `
-XmlFilePath $PolicyXml `
-BinaryFilePath $PolicyBinary
Keep the reviewed XML, binary hash, version, policy ID, scan log, source-device inventory, and approval record together in source control or another access-controlled system. The binary alone cannot explain why a rule exists.
Step 6: deploy audit mode through a supported channel
Microsoft documents Intune/MDM, Configuration Manager, script, and Group Policy deployment paths, but Group Policy only supports the older single-policy format and is not the recommended path for modern Windows multiple-policy deployments. For Windows 11 22H2 and later, a controlled script can use the inbox CiTool:
CiTool --update-policy $PolicyBinary --json
CiTool --list-policies --json
Use the organization’s managed deployment channel rather than running that command manually across a fleet. Start with a lab, then a small representative ring, then broader audit rings. New signed base policies on affected older Windows 11 builds with memory integrity require special reboot-based activation guidance; follow Microsoft’s current deployment page for the exact target build instead of generalizing one procedure to every policy type.
Step 7: collect both code-integrity and script/installer audit events
App Control audit events for binaries appear under:
Applications and Services Logs
Microsoft
Windows
CodeIntegrity
Operational
Scripts and MSI activity is also recorded in the AppLocker MSI and Script log. Centralize events through Defender for Endpoint advanced hunting or Windows event forwarding, retain device/policy/version context, and exercise real workloads: boot, sign-in, VPN, Office, browsers, software updates, drivers, plug-ins, support tools, scheduled tasks, deployment agents, recovery, and uninstall paths.
An audit event is not automatically an allow-rule request. Determine whether the file is necessary, approved, correctly signed, from a trusted distribution path, and resistant to user-writable substitution. Generate supplemental rules from reviewed evidence, not from every event produced by an uncontrolled workstation.
Step 8: enforce by updating the audited policy, not rebuilding from memory
Copy the approved XML, increment its version, preserve its policy ID when it is intended to replace the deployed audit policy, and delete option 3:
$EnforcedXml = Join-Path $PolicyDir "FixedWorkload_Enforced.xml"
Copy-Item $PolicyXml $EnforcedXml
Set-RuleOption -FilePath $EnforcedXml -Option 9
Set-RuleOption -FilePath $EnforcedXml -Option 10
Set-RuleOption -FilePath $EnforcedXml -Option 3 -Delete
Set-CIPolicyVersion -FilePath $EnforcedXml -Version "1.1.0.0"
[xml]$Enforced = Get-Content $EnforcedXml
$EnforcedBinary = Join-Path $PolicyDir "$($Enforced.SiPolicy.PolicyID).cip"
ConvertFrom-CIPolicy $EnforcedXml $EnforcedBinary
Re-run the same acceptance suite in a tiny enforcement ring before expanding. Prove that unapproved code is blocked, approved workflows still function, events reach monitoring, and rollback works. Do not remove recovery options or sign the policy until those controls have been exercised under the organization’s actual boot and servicing conditions.
How App Control differs from AppLocker and antivirus
AppLocker and App Control for Business are distinct Windows application-control technologies. App Control can enforce kernel-mode driver trust and, with user-mode code integrity enabled, applications and scripts; AppLocker operates at a different layer and remains useful in some scenarios. Microsoft’s current product guidance lists both rather than treating the names as interchangeable.
Antivirus and EDR are also not simple deny lists: modern products use reputation, behavior, content inspection, cloud intelligence, and response signals. App Control complements them by imposing an explicit code-trust boundary; it does not replace malware scanning, behavior detection, credential protection, patching, or incident response.
Treat the policy as a maintained production control
New software, certificates, drivers, update mechanisms, and business requirements continuously change the circle of trust. Assign ownership, review audit and block telemetry, expire exceptions, test servicing and recovery, version every policy change, and repeat audit-first deployment for material updates. A policy that cannot be explained, updated, or rolled back safely is not a mature allow-list—it is a future outage.
Related:
- How to Replace Microsoft Defender Application Guard After Its Removal
- How to Deploy Software with Group Policy
Sources: