← All posts

Application Allowlisting on Windows: Turning Off Every Executable You Never Approved

Signature scanning asks whether a file is known bad; allowlisting flips the question to whether it is known good and blocks everything else. Here is how WDAC and AppLocker actually work, why audit mode is the only sane way to deploy them, and how to confirm your machine even has an allowlisting policy in place.

Every antivirus product on earth answers the same question: is this file known bad? It compares a binary against signatures, heuristics, and reputation, and if nothing matches, the file runs. That model has a permanent, structural blind spot — the malware written this morning, the freshly compiled dropper, the legitimately signed tool an attacker is abusing for the first time. None of it is “known bad” yet, so all of it runs. Application allowlisting inverts the entire premise. Instead of maintaining an infinite blocklist of everything malicious, you declare the finite set of software that is allowed to execute, and the operating system refuses to run anything else. A payload nobody has ever seen is not on your allowlist, so it never starts. This is the same “default deny” posture the security industry has preached for firewalls for thirty years, finally applied to code execution.

Windows ships two mechanisms to do this, both free, both built in, and it is worth knowing which is which before you touch a policy.

WDAC vs. AppLocker: Which Lever To Pull

AppLocker is the older, gentler control. It lets you write rules that permit or deny executables, scripts, installers, and packaged apps based on publisher signature, file path, or file hash, scoped to users or groups. It is comparatively easy to stand up, it degrades gracefully, and it is genuinely useful — but Microsoft now treats it as a supplement rather than a security boundary, because a determined attacker with admin rights can maneuver around it.

Windows Defender Application Control (WDAC) — now branded App Control for Business — is the serious one. It enforces policy at the kernel level, applies to every user including SYSTEM, and can be locked to the point where even an administrator cannot run unapproved code. It integrates with Microsoft’s Intelligent Security Graph so you can trust files by reputation, and it can require that code be signed. The tradeoff is rigor: WDAC demands real planning, because a policy that is too tight will block a legitimate line-of-business app and a policy built carelessly will lock you out of your own machine.

Rule of thumb: reach for WDAC when you want an actual enforcement boundary, and use AppLocker to add per-user or per-group refinements on top. On a modern estate, WDAC is the strategic control and AppLocker is the tactical one.

Audit Mode First — This Is Non-Negotiable

The number one way allowlisting projects fail is the same way ASR rollouts fail: someone enables enforcement across real machines before they know what those machines actually run, and the help desk drowns. Both WDAC and AppLocker have an audit mode that solves this exactly. In audit mode the policy evaluates every launch and logs what it would have blocked — but lets it run. You deploy in audit, leave it for a week or two across a representative sample of hardware and job roles, then harvest the events to discover the real inventory: the finance add-in, the ancient vendor tool, the developer’s unsigned build output. Only then do you build the rules that permit those and flip to enforce.

The evidence lives in dedicated event logs, and reading them is the whole game:

# AppLocker: what WOULD have been blocked (audit) vs what WAS blocked (enforce).
# EXE/DLL enforcement events land in the EXE and DLL operational log:
Get-WinEvent -LogName 'Microsoft-Windows-AppLocker/EXE and DLL' |
  Where-Object { $_.Id -in 8003,8004 } |   # 8003 = would-block (audit), 8004 = blocked (enforce)
  Select-Object TimeCreated, Id, Message -First 40

# WDAC / App Control: code-integrity block + audit events:
Get-WinEvent -LogName 'Microsoft-Windows-CodeIntegrity/Operational' |
  Where-Object { $_.Id -in 3076,3077 } |   # 3076 = audit-would-block, 3077 = enforced block
  Select-Object TimeCreated, Id, Message -First 40

Event 8003 (AppLocker) and 3076 (WDAC) are your goldmine: every one is a program a policy would have stopped. If the only entries are things that have no business running, you are ready to enforce. If a legitimate app shows up, you just avoided an outage — write the rule to allow it, ideally by publisher signature rather than a brittle file path, then promote.

Prefer Signature And Publisher Rules Over Paths

The most common self-inflicted wound in allowlisting is the path rule that trusts a writable directory. If your policy allows anything under a folder that standard users can write to — a misconfigured install location, a world-writable temp path, parts of the user profile — then an attacker simply drops their payload there and it inherits your blessing. The allowlist is now decorative. Whenever possible:

A default-deny policy is only as strong as its weakest allow rule. One over-broad path exception undoes the entire boundary, which is precisely why allowlisting is a control you have to verify, not just declare.

Confirming The Policy Is Actually There

Here is the operational trap: allowlisting is a configuration, and configuration drifts. A machine that was imaged before your WDAC policy existed, a GPO scoped to the wrong OU, an AppLocker rule set whose enforcement service was never started — each leaves you believing you have default-deny when the machine is wide open. “We deployed the policy last quarter” is not the same statement as “the policy is present and enforcing on this box right now,” and only the second one stops malware. AppLocker’s enforcement even depends on the Application Identity service (AppIDSvc) running; if it is stopped, your rules are inert.

That verification is exactly what a configuration audit is for. On the machine in front of you, WinSentinel’s Group Policy Security Audit inspects the application-allowlisting configuration alongside the rest of the security-relevant policy surface — NTLM restrictions, SMB signing, audit policy, credential protection — and its process, service, and driver audits catch the unsigned and out-of-place binaries that a healthy allowlist should have refused in the first place. It reads in seconds, at full depth, free:

# Full-depth local audit, including allowlisting / Group Policy posture:
winsentinel --audit

# Capture a baseline you can diff against after the next patch or GPO change:
winsentinel --audit --format json --out allowlist-baseline.json

# Remediate the weak settings that don't belong:
winsentinel --fix-it

This closes a gap a vulnerability scanner cannot. “Is the software patched?” and “can an executable I never approved run on this machine?” are different questions, and a clean CVE report answers only the first. A fully updated machine with no allowlisting policy is exactly the machine on which tomorrow’s unsigned dropper runs without resistance.

Where It Becomes An Org Problem

On a single machine, this is complete. Every check above — whether an allowlisting policy is present, whether it is enforcing or merely auditing, whether unsigned binaries are slipping through — runs free and at full depth on the box you own; there is no “upgrade to see the real findings.” The shape of the problem changes at scale. The danger to an organization is not one workstation without a policy; it is that you cannot see which machines drifted. One imaging template built before the policy existed, one GPO scoped to the wrong OU, one enforcement service that never started after a reboot — and now an unknown subset of your fleet is running default-allow while your documentation says default-deny. From any single box, that is invisible.

That is the boundary where fleet orchestration earns its keep. WinSentinel Pro runs the same allowlisting audit — identical depth to the free single-machine scan; Pro does not unlock deeper checks — through an agent on each endpoint, reporting into a central node. What it adds is the org-level answer: a fleet rollup that says “38 of your 300 machines have no enforcing allowlist policy” in one view instead of 300 separate log pulls; drift alerts when a deployment or GPO change knocks enforcement back to audit across the fleet; and compliance evidence that your endpoints held a default-deny posture across an audit window. Single-machine hardening is free and total. The “which of my machines silently stopped enforcing the allowlist?” question, answered as one report, is the org problem Pro exists to solve.

The Takeaway

Allowlisting is the rare control that defeats the malware you have never seen, because it never asked whether the file was bad — only whether it was approved. It is free, it is built into Windows twice over, and the discipline is straightforward: choose WDAC for a real enforcement boundary with AppLocker for per-group refinement, deploy in audit mode first, mine the 8003/3076 events to learn what your machines actually run, prefer publisher and hash rules over writable paths, and then — only then — enforce. Do that and the unsigned dropper, the abused signed tool, and the payload that has no signature yet all hit a wall that a fully patched, signature-scanned machine would have let straight through.

# See whether this machine is actually running default-deny, then close the gaps:
winsentinel --audit
winsentinel --fix-it

Signatures block the bad you already know about. Allowlisting blocks everything you never approved — which is the only model that keeps working after the attacker writes something new.