<?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: threat-modeling</title><description>Posts tagged threat-modeling.</description><link>https://paragmali.com/</link><language>en-US</language><lastBuildDate>Sun, 07 Jun 2026 04:13:12 GMT</lastBuildDate><atom:link href="https://paragmali.com/tags/threat-modeling/rss.xml" rel="self" type="application/rss+xml"/><item><title>Two Months Without Code: The Windows Security Wars Part 1 (1995-2001)</title><link>https://paragmali.com/blog/two-months-without-code-the-windows-security-wars-part-1-199/</link><guid isPermaLink="true">https://paragmali.com/blog/two-months-without-code-the-windows-security-wars-part-1-199/</guid><description>In 1995-2001 the worms won. The Trustworthy Computing memo and the ten-week Windows Security Push that followed taught the industry how to ship secure software.</description><pubDate>Sat, 30 May 2026 00:00:00 GMT</pubDate><content:encoded>
Between 1995 and 2001, Microsoft shipped the most-used operating system on Earth into an Internet it was not architecturally prepared for. Concept, Melissa, ILOVEYOU, Code Red, Nimda, and Slammer demonstrated that reactive patching could not win the speed race with weaponized exploits. On Tuesday, January 15, 2002 at 5:22 PM Pacific, Bill Gates sent the roughly 1,500-word &quot;Trustworthy computing&quot; memo. On February 11, 2002, approximately 8,500 Windows engineers stopped writing features and spent about ten weeks and one hundred million dollars on threat modeling, banned-API review, fuzzing, and the first mandatory Final Security Review gate. The result was the Microsoft Security Development Lifecycle (SDL), and every secure-development framework the industry has standardized since (BSIMM, OWASP SAMM, ISO/IEC 27034, NIST SSDF, SLSA, CISA Secure by Design) traces back to it.
&lt;h2&gt;1. Two Months Without Code&lt;/h2&gt;
&lt;p&gt;On Monday, February 11, 2002, in Building 26 of Microsoft&apos;s Redmond campus, Brian Valentine -- Senior Vice President of the Windows Division -- told roughly 8,500 Windows engineers to stop writing features [@howard-lipner-push-2003] [@washtech-microsoft-100m] [@msft-news-valentine-mms-2002]. For the next ten weeks they would sit through mandatory secure-coding training, threat-model every component they owned, audit their code against a published banned-API list, and gate-review every change through a Final Security Review checkpoint that had not existed three weeks earlier [@howard-lipner-push-2003] [@lipner-acsac-2004]. The cost: about one hundred million dollars in foregone feature work [@washtech-microsoft-100m]. The order traced, precisely, to a 1,500-word email Bill Gates had sent twenty-seven days earlier at 5:22 PM Pacific [@gates-memo-wired] [@helpwithwindows-billg].&lt;/p&gt;
&lt;p&gt;Stop and notice what that means. An operating-system vendor whose product ran on most business desktops on the planet ordered its largest engineering organization to &lt;em&gt;stop shipping the product&lt;/em&gt; for two months. The lost revenue is the easy number. The hard number is the implicit admission: a company halts an engineering org of that size only when the cost of &lt;em&gt;not&lt;/em&gt; halting is bigger.&lt;/p&gt;
&lt;p&gt;What does a company have to lose before its CEO writes that order?&lt;/p&gt;
&lt;p&gt;This article is the answer. It traces the seven-year run-up that made halting development the proportionate response, the memo that called the halt, the ten-week operation that followed, and the discipline that pattern became -- the discipline every secure-development framework on the industry shelf in 2026 traces back to.&lt;/p&gt;
&lt;p&gt;It is also a quarrel with one sentence. The literal version of the article&apos;s working claim is this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&quot;Microsoft did not have a security team until January 15, 2002.&quot;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That sentence is wrong in exactly the way every popular retelling of this era is wrong. Microsoft did have a security team. It had the Microsoft Security Response Center (MSRC), founded in 1998 and reachable from MS98-001 onward [@msrc-org] [@howard-lipner-push-2003]. It had the Secure Windows Initiative (SWI), a small in-house secure-development team running since around 2000 under Michael Howard [@howard-lipner-push-2003]. It had STRIDE, a categorized threat list written internally on April 1, 1999 by Loren Kohnfelder and Praerit Garg [@shostack-tm-book]. It had Howard and David LeBlanc&apos;s &lt;em&gt;Writing Secure Code&lt;/em&gt;, published by Microsoft Press in November 2001 and reportedly required reading for every Microsoft engineer [@howard-leblanc-wsc]. The methodology, the books, the team, and the published threat list were all in the building.&lt;/p&gt;
&lt;p&gt;By section 5, this article earns a stronger -- and defensible -- version of the literal claim. Hold the literal sentence loosely; the corrected one is worth more.&lt;/p&gt;
&lt;p&gt;The story turns on six names you will meet in sections 3 and 4: &lt;strong&gt;Concept&lt;/strong&gt; (July 1995), &lt;strong&gt;Melissa&lt;/strong&gt; (March 1999), &lt;strong&gt;ILOVEYOU&lt;/strong&gt; (May 2000), &lt;strong&gt;Code Red&lt;/strong&gt; (mid-July 2001), &lt;strong&gt;Nimda&lt;/strong&gt; (September 2001), and &lt;strong&gt;SQL Slammer&lt;/strong&gt; (January 2003) [@fsecure-concept] [@cert-ca-1999-04-melissa] [@cert-ca-2000-04-iloveyou] [@caida-codered] [@cert-ca-2001-26-nimda] [@caida-slammer]. Each name is also a generation of attack. Each generation broke an assumption the previous defenses had quietly depended on. By the end of 2001, the cumulative effect was a vendor whose customers no longer believed it could keep them safe.&lt;/p&gt;
&lt;p&gt;That is what a company loses before its CEO halts development. How it got there takes seven years to tell. Begin at the architectural starting line.&lt;/p&gt;
&lt;h2&gt;2. Two Windowses, Two Security Stories&lt;/h2&gt;
&lt;p&gt;The first surprise of the era is structural. There were two Windowses, and only one of them had a security model at all.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;NT line&lt;/strong&gt; -- Windows NT 3.1 in July 1993, NT 3.5, NT 4.0 in 1996, Windows 2000 in February 2000 -- was the work of David Cutler&apos;s team, hired by Microsoft in August 1988 with about twenty colleagues from Digital Equipment Corporation [@zachary-showstopper] [@msft-lifecycle-products]. Cutler had led the VMS operating-system project at DEC, and he carried VMS&apos;s engineering discipline into NT: a formal kernel/executive separation, an &lt;a href=&quot;https://paragmali.com/blog/the-object-manager-namespace/&quot; rel=&quot;noopener&quot;&gt;object manager&lt;/a&gt; that treated every kernel-allocated thing as a named object with a security descriptor attached, and a small kernel component called the &lt;strong&gt;Security Reference Monitor&lt;/strong&gt; whose only job was to consult that descriptor on every access attempt [@russinovich-solomon-iw2k] [@msft-access-control].NT was &lt;em&gt;patterned on VMS&lt;/em&gt;, not literally inherited from it. DEC threatened legal action against Microsoft over the engineering similarities and Cutler&apos;s role; the parties resolved the dispute through the 1995 DEC-Microsoft alliance, in which Microsoft paid roughly $105 million (including $75 million to bolster DEC&apos;s NT service-and-support operation) and committed to keeping Windows NT supported on DEC&apos;s Alpha processor [@techmonitor-dec-microsoft-alliance] [@zachary-showstopper].&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;Win9x line&lt;/strong&gt; -- Windows 95 in August 1995, Windows 98 in June 1998, Windows Me in September 2000 -- shared a name and a Start menu with NT and almost nothing else [@msft-lifecycle-products]. Underneath, Win9x was a 32-bit graphical shell wrapped around the 16-bit DOS kernel. It had no SIDs, no per-object access control lists, no kernel-mediated access check, no concept of process identity at all. Every process ran with effective access to every file on disk, every key in the registry, and every other process&apos;s address space [@russinovich-solomon-iw2k].&lt;/p&gt;

The kernel component of Windows NT (and every NT-line OS since: 2000, XP, Vista, 7, 8, 10, 11) that performs the access check on a securable object. When a thread asks to open a file, the I/O manager hands the request to the object manager, which calls the SRM. The SRM compares the access token attached to the thread (which carries the user&apos;s SID and the SIDs of every group the user belongs to) against the security descriptor on the object (which carries the DACL listing who is allowed which access rights). If the DACL grants the requested rights, the open succeeds; otherwise it fails with `STATUS_ACCESS_DENIED`.

Every securable Windows kernel object carries a security descriptor with two access control lists. The **DACL** (Discretionary Access Control List) is an ordered list of ACEs (Access Control Entries) that grant or deny specific rights to specific principals. The **SACL** (System Access Control List) is the audit list; it tells the kernel which access attempts to log to the Security event log. The owner of an object can edit its DACL; only an administrator with the `SeSecurityPrivilege` right can edit its SACL.

A variable-length binary identifier that names a principal -- a user, a group, a computer, a service. SIDs have a defined structure (revision, identifier authority, sub-authorities) and are unique within their authority. Windows uses SIDs internally because they are stable across renames and translatable across trust boundaries; human-readable names like `DOMAIN\jdoe` are convenience labels that get resolved to SIDs before any access check runs.
&lt;p&gt;When a thread on NT asks to open a file, the path through the kernel looks like this:&lt;/p&gt;

flowchart TD
    A[User thread requests open] --&amp;gt; B[I/O Manager builds IRP]
    B --&amp;gt; C[Object Manager looks up named object]
    C --&amp;gt; D[Security Reference Monitor]
    D --&amp;gt; E[Compare access token SIDs against DACL ACEs]
    E --&amp;gt; F{&quot;Granted rights ≥ desired access?&quot;}
    F --&amp;gt;|Yes| G[Return handle with granted access mask]
    F --&amp;gt;|No| H[Return STATUS_ACCESS_DENIED]
&lt;p&gt;That pipeline is what made NT, in principle, a hardened operating system from its first release in 1993. It is the same pipeline every NT-line Windows has executed for thirty-three years; Microsoft&apos;s current public reference still describes the same primitives [@msft-access-control].&lt;/p&gt;
&lt;p&gt;So why was NT not, in practice, the hardened operating system the architecture promised?&lt;/p&gt;
&lt;p&gt;The answer is the load-bearing observation of the era&apos;s first half: &lt;strong&gt;the primitives existed; the defaults rendered them inert.&lt;/strong&gt; Through NT 3.1, NT 3.5, NT 4.0, and well into Windows 2000, the default DACL on huge swaths of the filesystem and registry was &lt;code&gt;Everyone: Full Control&lt;/code&gt;. The &lt;code&gt;Everyone&lt;/code&gt; SID matches every authenticated user and, depending on configuration, often the anonymous logon as well. A DACL that grants &lt;code&gt;Everyone: Full Control&lt;/code&gt; is a permission check that always succeeds. Microsoft&apos;s documentation of the era is matter-of-fact about this: the defaults were preserved to maintain application-compatibility expectations carried over from the Win9x world, where applications had been written assuming no permission check at all [@russinovich-solomon-iw2k].&lt;/p&gt;

On a clean Windows NT 4.0 install, the per-directory ACL table that Microsoft Knowledge Base article Q148437 (&quot;Default NTFS Permissions in Windows NT&quot;) preserved verbatim made the gap operationally concrete [@kb-q148437-wayback]. Two directories illustrate the pattern. **`%SystemRoot%\repair`** -- the destination of `rdisk /s`, where the SAM, SECURITY, SOFTWARE, SYSTEM, and DEFAULT registry hives get backed up -- shipped with **`Everyone: Full Control`** [@kb-q148437-wayback]. Any unprivileged interactive user could read or replace the SAM-hive backup. **`%SystemRoot%\system32`** -- the directory the LSA, user-mode subsystems, and print spooler load DLLs from -- shipped with **`Everyone: Change`** (RWXD), so an unprivileged user could write into the system DLL search path [@kb-q148437-wayback]. The same table records two more `Everyone: Full Control` directories in the default install: `%SystemRoot%\system32\spool\drivers\w32x86\1` (print drivers) and `%SystemRoot%\system32\wins` (the WINS service) [@kb-q148437-wayback]. Three of the era&apos;s most-exploited primitives -- SAM-hive theft, DLL hijack, print-spooler abuse -- mapped directly to defaults the OS shipped with. Windows 2000 tightened many of these; XP and Server 2003 tightened more; the cleanup was not nominally complete until Vista&apos;s UAC redesign in 2006. The architecture did not change. The defaults did.
&lt;p&gt;The Win9x side has no such defense-of-the-defaults story to tell, because Win9x had no access check to default. On a Win98 box, the file &lt;code&gt;c:\windows\system\kernel32.dll&lt;/code&gt; was simply &lt;em&gt;a file&lt;/em&gt;. Any program could open it, read it, write it, or rename it. The phrase &quot;least privilege&quot; did not apply, because there was no privilege to constrain.&lt;/p&gt;
&lt;p&gt;This is the architectural starting line of the era. Two Windowses, two stories, one shared problem: the strongest version had a security model that defaults defeated, and the weakest had no security model to defeat in the first place. Both, in the tens of millions, were about to be connected to a public Internet that did not yet exist when either had been designed.&lt;/p&gt;
&lt;p&gt;What happens when you connect that pair of architectures to that network is the next two sections.&lt;/p&gt;
&lt;h2&gt;3. The Attack Class That Cracked Office (1995-2000)&lt;/h2&gt;
&lt;p&gt;Open with a small artifact. Sometime in mid-1995, copies of a Microsoft CD-ROM shipped to customers carrying, by accident, the first widely distributed Word macro virus. It was called &lt;strong&gt;Concept&lt;/strong&gt;. Its only payload was a benign dialog and a comment in the macro source that read &lt;code&gt;REM That&apos;s enough to prove my point&lt;/code&gt; [@fsecure-concept] [@virusencyclopedia-concept].&lt;/p&gt;
&lt;p&gt;That was the joke. Then the rest of the industry stopped laughing.&lt;/p&gt;

A program that infects documents (rather than executables) by hijacking the document format&apos;s embedded scripting language. Word&apos;s WordBasic in 1995 and VBA in 1997 could read and write files, manipulate the host application, and -- critically -- run automatically on document open via `AutoOpen` and on document save via `FileSaveAs`. A macro virus is the same shape as a classical file-infector virus, except its host file is `.doc` instead of `.exe` and its execution surface is the application that opens the document, not the operating system that runs the binary.

**VBScript** is a Microsoft scripting language, syntactically a subset of Visual Basic, designed for embedding in web pages (in Internet Explorer) and standalone scripts (run by WSH). **Windows Script Host** is the Windows component that executes scripts written in VBScript, JScript, or other registered languages, via the executables `wscript.exe` (windowed) and `cscript.exe` (console). WSH was first shipped with Windows 98 and was available as an optional add-on for NT 4.0 and Windows 95. It was on by default; a `.vbs` file double-clicked in Explorer ran in `wscript.exe` without further confirmation.
&lt;p&gt;The era&apos;s three Office-style artifacts each carried a lesson the next one had to escalate past.&lt;/p&gt;
&lt;h3&gt;Concept (July 1995)&lt;/h3&gt;
&lt;p&gt;Concept was a WordBasic macro virus written for Microsoft Word 6.x. On document open it ran an &lt;code&gt;AutoOpen&lt;/code&gt; macro that copied itself into Word&apos;s global template &lt;code&gt;NORMAL.DOT&lt;/code&gt;. Every document Word saved from that point on inherited the infection, because every &lt;code&gt;FileSaveAs&lt;/code&gt; operation now ran through the infected template&apos;s hook [@fsecure-concept].First-in-the-wild detection of Concept is canonically dated to &lt;strong&gt;July 1995&lt;/strong&gt;, per the Microsoft Defender Threat Encyclopedia and the Virus Encyclopedia [@defender-concept-encyclopedia] [@virusencyclopedia-concept]. The &quot;September 1995&quot; date often cited in retellings refers to CIAC Notes 95-12, the bulletin, not the first detection [@ciac-i-023-macro].&lt;/p&gt;
&lt;p&gt;Concept was cross-platform: it infected Word for Windows 6.x/7.x and Word for Macintosh 6.x, because WordBasic was portable [@fsecure-concept]. By the time it was named and tracked, copies had shipped on at least one Microsoft CD-ROM and on training materials from at least one other software vendor [@ciac-i-023-macro].&lt;/p&gt;
&lt;p&gt;The lesson hidden in Concept is bigger than the virus. Any application that ships with a Turing-complete macro language, an auto-execute hook, and a write-enabled global template ships an execution surface. The user did not have to &quot;run a program&quot;; opening a document &lt;em&gt;was&lt;/em&gt; running a program, because the document carried the program inside it. That was the first time the popular distinction between &quot;data&quot; and &quot;executable&quot; failed at consumer scale.&lt;/p&gt;
&lt;h3&gt;Melissa (March 26, 1999)&lt;/h3&gt;
&lt;p&gt;Four years later, that lesson met email.&lt;/p&gt;
&lt;p&gt;CERT/CC&apos;s advisory CA-1999-04 records the moment: &quot;At approximately 2:00 PM GMT-5 on Friday March 26 1999 we began receiving reports of a Microsoft Word 97 and Word 2000 macro virus&quot; [@cert-ca-1999-04-melissa]. The virus was written in VBA (the successor to WordBasic that Office 97 introduced) by a New Jersey programmer named David L. Smith.&lt;/p&gt;
&lt;p&gt;It carried the now-standard &lt;code&gt;AutoOpen&lt;/code&gt; infection of &lt;code&gt;NORMAL.DOT&lt;/code&gt;, but it added something Concept could not have done in 1995: it opened Microsoft Outlook through the MAPI interface, walked the first fifty entries of every address book it could read, and emailed the infected document to each one [@cert-ca-1999-04-melissa]. For good measure, it lowered Office&apos;s macro security settings on each infected machine, so the next infected document would run its macro without a prompt [@cert-ca-1999-04-melissa].&lt;/p&gt;
&lt;p&gt;The propagation pattern is worth a diagram of its own:&lt;/p&gt;

sequenceDiagram
    participant U as User
    participant W as Word
    participant N as NORMAL.DOT
    participant O as Outlook MAPI
    participant R as 50 recipients
    U-&amp;gt;&amp;gt;W: Open list.doc attachment
    W-&amp;gt;&amp;gt;W: Fire AutoOpen macro
    W-&amp;gt;&amp;gt;N: Infect NORMAL.DOT
    W-&amp;gt;&amp;gt;O: Read first address book
    O--&amp;gt;&amp;gt;W: Return 50 entries
    W-&amp;gt;&amp;gt;R: Send list.doc to each
    R-&amp;gt;&amp;gt;U: Recipients open list.doc
    Note over W,N: Loop repeats per recipient
&lt;p&gt;The math of the loop is uncomfortable. If each infected user has at least one populated fifty-entry address book and a non-trivial fraction of recipients open the attachment, the early growth is geometric in fan-out. No spam filter of the era could outrun it, because the senders were not spammers -- they were the recipient&apos;s actual colleagues, sending a document they had actually edited, from a real email address with a real return path. Address-book amplification by trusted senders is, by definition, a self-amplifying email feedback loop.&lt;/p&gt;
&lt;p&gt;Melissa&apos;s payload was deliberately benign (it inserted a Simpsons quote into the open document on certain dates), but its propagation forced corporate email shutdowns at a long list of Fortune 500 sites within seventy-two hours [@cert-ca-1999-04-melissa].Contemporaneous trade press reported shutdowns at Lockheed Martin, Lucent, Microsoft, and others. The CERT advisory itself describes a &quot;widespread attack affecting a variety of sites&quot; without naming specific companies. Smith was arrested April 1, 1999.&lt;/p&gt;
&lt;p&gt;The lesson the industry should have read off Melissa: &lt;em&gt;a macro that can read the address book is not an Office decision; it is a platform decision&lt;/em&gt;. Office let macros call Outlook because the COM-automation model invited it; Outlook let other applications read the address book because that was the entire point of MAPI. The trust boundary the user &lt;em&gt;thought&lt;/em&gt; was around their inbox was, in API terms, around every other application running as the same user.&lt;/p&gt;
&lt;h3&gt;ILOVEYOU (May 4-5, 2000)&lt;/h3&gt;
&lt;p&gt;Thirteen months later, the lesson generalized off the Office platform.&lt;/p&gt;
&lt;p&gt;CERT/CC&apos;s advisory CA-2000-04 names the attachment: &lt;code&gt;LOVE-LETTER-FOR-YOU.TXT.vbs&lt;/code&gt;, with a &quot;Love Letter&quot; subject line and a body asking the recipient to &quot;kindly check the attached LOVELETTER&quot; [@cert-ca-2000-04-iloveyou]. The &lt;code&gt;.vbs&lt;/code&gt; extension matters. ILOVEYOU was not a Word macro virus.Popular retellings group Concept, Melissa, and ILOVEYOU as one continuous Office-macro story. They are not. ILOVEYOU was a &lt;strong&gt;VBScript / Windows Script Host email worm&lt;/strong&gt;, executed by &lt;code&gt;wscript.exe&lt;/code&gt; when the user double-clicked the attachment in Outlook [@cert-ca-2000-04-iloveyou]. The execution surface is WSH, not Office.&lt;/p&gt;
&lt;p&gt;It was a VBScript file -- a script in plain text, executed by &lt;code&gt;wscript.exe&lt;/code&gt;. Windows Explorer&apos;s default setting, &quot;hide extensions for known file types,&quot; hid the &lt;code&gt;.vbs&lt;/code&gt; suffix from the filename column. The user saw &lt;code&gt;LOVE-LETTER-FOR-YOU.TXT&lt;/code&gt;, an apparently inert text file, and double-clicked it. Explorer handed the file to its registered handler, which was &lt;code&gt;wscript.exe&lt;/code&gt;, which ran it.&lt;/p&gt;
&lt;p&gt;Once running, the script copied itself into the Windows system directory, registered itself to run at every boot, overwrote files with selected extensions (&lt;code&gt;.jpg&lt;/code&gt;, &lt;code&gt;.mp3&lt;/code&gt;, &lt;code&gt;.vbs&lt;/code&gt;), and -- like Melissa -- mailed itself to every address it could reach through Outlook. BBC News, datelined Thursday May 4, 2000 19:28 GMT, recorded the outbreak appearing first in Hong Kong, sweeping the US State Department, CIA, FBI, Pentagon, White House, and Congress, and the UK House of Commons, the Danish parliament, the Swiss federal government, and banks across Europe within hours, with reports pointing to a Philippine origin [@bbc-love-bug-2000-05-04] [@cert-ca-2000-04-iloveyou]. Trade-press damage estimates of &quot;tens of millions&quot; of infected machines and &quot;billions of dollars&quot; in cleanup were folk-knowledge of the era; the underlying classification as a VBScript / WSH email worm is what survives in the primary record [@cert-ca-2000-04-iloveyou].&lt;/p&gt;
&lt;p&gt;The lesson ILOVEYOU should have forced: Windows Script Host was on by default, hidden extensions concealed the executable surface, and Outlook&apos;s auto-execute-attachments behavior treated &lt;code&gt;.vbs&lt;/code&gt; like any other attachment. Three Microsoft platform decisions, each individually defensible, composed into a one-double-click remote code execution path on a freshly installed Windows 98 machine.&lt;/p&gt;
&lt;p&gt;The three artifacts collapse into a single comparison table:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Execution surface&lt;/th&gt;
&lt;th&gt;Propagation vector&lt;/th&gt;
&lt;th&gt;On by default?&lt;/th&gt;
&lt;th&gt;Primary lesson&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;July 1995&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Concept&lt;/strong&gt; [@fsecure-concept] [@virusencyclopedia-concept]&lt;/td&gt;
&lt;td&gt;Word WordBasic macro&lt;/td&gt;
&lt;td&gt;Infected document opened in Word&lt;/td&gt;
&lt;td&gt;Yes (macro auto-exec)&lt;/td&gt;
&lt;td&gt;A document is an executable when the application supports macros.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;March 1999&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Melissa&lt;/strong&gt; [@cert-ca-1999-04-melissa]&lt;/td&gt;
&lt;td&gt;Word VBA macro&lt;/td&gt;
&lt;td&gt;Word + Outlook MAPI; 50 address-book entries per infected host&lt;/td&gt;
&lt;td&gt;Yes (macro auto-exec, MAPI access)&lt;/td&gt;
&lt;td&gt;A macro with address-book access creates a self-amplifying email storm by trusted senders.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;May 2000&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ILOVEYOU&lt;/strong&gt; [@cert-ca-2000-04-iloveyou]&lt;/td&gt;
&lt;td&gt;VBScript via Windows Script Host (&lt;code&gt;wscript.exe&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Outlook attachment, double-extension hidden by Explorer default&lt;/td&gt;
&lt;td&gt;Yes (WSH on by default, extensions hidden)&lt;/td&gt;
&lt;td&gt;The &quot;Office macro&quot; attack class generalized to any double-clickable script the platform interpreted.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Document-as-execution-surface had a known fix shape from the moment Concept shipped: disable auto-execute, prompt the user, and -- eventually -- block by default. The block-by-default fix, for &lt;a href=&quot;https://paragmali.com/blog/attack-surface-reduction-rules-the-quiet-layer-that-stopped-/&quot; rel=&quot;noopener&quot;&gt;Office VBA macros&lt;/a&gt; downloaded from the internet, did not fully ship until February 2022, &lt;strong&gt;twenty-seven years after Concept&lt;/strong&gt; [@ms-learn-internet-macros-blocked]. Section 9 walks the deprecation playbook that delay is evidence for.&lt;/p&gt;
&lt;p&gt;But document execution is only half of the era&apos;s attack story. What happens when the execution surface is not a document the user opened, but a network port a worm reached without the user doing anything at all?&lt;/p&gt;
&lt;h2&gt;4. The Attack Class That Cracked the Server (2001-2003)&lt;/h2&gt;
&lt;p&gt;Two dates frame the whole story.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;June 18, 2001:&lt;/strong&gt; Microsoft publishes Security Bulletin MS01-033, &quot;Unchecked Buffer in Index Server ISAPI Extension Could Enable Web Server Compromise.&quot; The bulletin patches an unchecked stack buffer in &lt;code&gt;idq.dll&lt;/code&gt;, the Indexing Service ISAPI extension loaded by Internet Information Services (IIS) 4.0 and 5.0. A specially crafted HTTP &lt;code&gt;GET&lt;/code&gt; to a URL ending in &lt;code&gt;.ida&lt;/code&gt; can overflow the buffer and execute attacker-supplied code in the IIS worker process, which runs as &lt;code&gt;LocalSystem&lt;/code&gt; [@ms01-033-idq].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;July 19, 2001:&lt;/strong&gt; thirty-one days later, the second-generation Code Red worm saturates roughly &lt;strong&gt;359,000 IIS servers&lt;/strong&gt; in under fourteen hours [@caida-codered] [@cert-ca-2001-19-codered]. The worm reaches its victims via a single HTTP GET. No user clicks. No email attachment. No double-click. A web server with port 80 open to the Internet and the unpatched &lt;code&gt;idq.dll&lt;/code&gt; is, by definition, &lt;em&gt;already&lt;/em&gt; listening for the attack.&lt;/p&gt;

A computing monoculture exists when a large population of independently administered hosts run identical software with identical defaults. The security significance is statistical: a single vulnerability discovered in the monoculture&apos;s shared software is, in expectation, exploitable against the entire population. The 2001-2003 Windows-server worms (Code Red, Nimda, Slammer) are the canonical case studies; CAIDA&apos;s Code Red measurement and Moore et al.&apos;s Slammer measurement are the empirical anchors that made the monoculture argument quantitative rather than rhetorical [@caida-codered] [@caida-slammer].
&lt;p&gt;What kind of defense survives a thirty-one-day patch-to-mass-exploitation window? The next seven months answer that question four different ways.&lt;/p&gt;
&lt;h3&gt;Code Red I (mid-July 2001)&lt;/h3&gt;
&lt;p&gt;A Northern California security boutique called eEye Digital Security discovered and reverse-engineered the worm. Marc Maiffret and Ryan Permeh named it &quot;Code Red&quot; after the Mountain Dew flavor they were drinking through the analysis [@eeye-codered-ii].Popular retellings sometimes date the discovery to July 13, 2001. The eEye back-reference in their August 4, 2001 Code Red II advisory points at advisory &lt;code&gt;AL20010717&lt;/code&gt; -- &lt;strong&gt;July 17, 2001&lt;/strong&gt; [@eeye-codered-ii]. &quot;Mid-July 2001&quot; or &quot;July 17, 2001&quot; is the better-attested date. The Mountain Dew naming detail comes from contemporaneous interviews with the eEye analysts, not the AL20010804 advisory itself.&lt;/p&gt;
&lt;p&gt;The initial Code Red variant -- &quot;Code Red v1&quot; -- carried a fixed-seed random-number generator in its IP scanner. Because every infected host generated the same sequence of scan targets, the worm spent most of its scanning budget on the same small set of IP addresses, and its spread was bounded. It was annoying. It was not yet a measurement event.&lt;/p&gt;
&lt;p&gt;That changed when somebody fixed the scanner.&lt;/p&gt;
&lt;h3&gt;Code Red v2 (July 19, 2001)&lt;/h3&gt;
&lt;p&gt;Code Red v2 was a rewritten worm using the same MS01-033 vulnerability but with a proper random scanner. The fix was tiny -- a different seed and a real entropy source -- and the consequences were huge. The CAIDA measurement, published by Moore, Shannon, and Brown in the Internet Measurement Workshop 2002, recorded the outbreak: &lt;strong&gt;&quot;On July 19, 2001, more than 359,000 computers connected to the Internet were infected with the Code-Red (CRv2) worm in less than 14 hours&quot;&lt;/strong&gt; [@caida-codered] [@cert-ca-2001-19-codered]. The peak rate was over 2,000 newly infected hosts per minute.&lt;/p&gt;
&lt;p&gt;The exploit path on each victim looked like this:&lt;/p&gt;

sequenceDiagram
    participant W as Worm host
    participant V as Victim IIS
    participant I as idq.dll
    participant S as LocalSystem shell
    W-&amp;gt;&amp;gt;V: HTTP GET /default.ida + long URL
    V-&amp;gt;&amp;gt;I: ISAPI dispatch to Indexing Service
    I-&amp;gt;&amp;gt;I: Buffer overflow in URL parse
    I-&amp;gt;&amp;gt;S: Shellcode runs in LocalSystem context
    S-&amp;gt;&amp;gt;S: Patch idq.dll in memory, install worm body
    S-&amp;gt;&amp;gt;W: Spawn 100 scanner threads
    Note over W,V: Each thread tries random IP:80, repeat
&lt;p&gt;The lesson that should have been read off Code Red v2 was a property of the population, not of the worm. The vulnerable population was large (anyone running IIS 4.0 or 5.0 with default modules enabled and the MS01-033 patch not applied), identical (every IIS install shipped the same &lt;code&gt;idq.dll&lt;/code&gt;), and reachable (TCP port 80 is by definition Internet-facing on a web server). That set of properties is the operational definition of a monoculture, and Code Red v2 was its first quantitative case study.&lt;/p&gt;
&lt;h3&gt;Code Red II (August 4, 2001)&lt;/h3&gt;
&lt;p&gt;Sixteen days after Code Red v2 saturated the IIS population, a &lt;em&gt;different&lt;/em&gt; worm appeared with a confusing name. &quot;Code Red II&quot; reused the MS01-033 vulnerability and the same &lt;code&gt;.ida&lt;/code&gt; injection vector, but the rest of it was unrelated to v1 or v2. eEye&apos;s August 4, 2001 analysis by Permeh and Maiffret documents the difference: where the earlier worms had a self-contained scanner-and-payload binary in memory, Code Red II dropped a copy of &lt;code&gt;cmd.exe&lt;/code&gt; named &lt;code&gt;root.exe&lt;/code&gt; into the IIS &lt;code&gt;/scripts&lt;/code&gt; and &lt;code&gt;/msadc&lt;/code&gt; directories, then dropped a trojanized &lt;code&gt;explorer.exe&lt;/code&gt; that re-enabled the C: and D: drives as the IIS virtual roots &lt;code&gt;/c&lt;/code&gt; and &lt;code&gt;/d&lt;/code&gt; [@eeye-codered-ii].&lt;/p&gt;
&lt;p&gt;The practical effect: any HTTP GET to &lt;code&gt;/scripts/root.exe?/c+dir&lt;/code&gt; on a compromised host returned a directory listing of the victim&apos;s &lt;code&gt;C:\&lt;/code&gt; drive, executed in the LocalSystem context. A permanent, anonymous, remote shell, reachable by anyone who knew the URL [@eeye-codered-ii].&lt;/p&gt;
&lt;p&gt;The lesson Code Red II adds: &lt;em&gt;one worm&apos;s residual artifact is another worm&apos;s propagation vector&lt;/em&gt;. Patching MS01-033 closed the door that let Code Red II in. It did not close the doors Code Red II left open behind it. A web server infected by Code Red II before its operator patched MS01-033 still had &lt;code&gt;root.exe&lt;/code&gt; waiting in &lt;code&gt;/scripts&lt;/code&gt;, indefinitely. The patching mental model -- &quot;apply the patch, the bug is fixed&quot; -- mismodels the state.&lt;/p&gt;
&lt;h3&gt;Nimda (September 18, 2001)&lt;/h3&gt;
&lt;p&gt;Six weeks later, exactly that mismodeling was exploited.&lt;/p&gt;
&lt;p&gt;The Nimda worm appeared on September 18, 2001, one week after the September 11 attacks, which the worm&apos;s name initially fed conspiracies about; &quot;nimda&quot; is &quot;admin&quot; backwards. The CERT/CC advisory CA-2001-26 records its four propagation vectors:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;(a) from client to client via email, (b) from client to client via open network shares, (c) from web server to client via browsing of compromised web sites, (d) from client to web server via active scanning for and exploitation of various Microsoft IIS 4.0 / 5.0 directory traversal vulnerabilities&quot; [@cert-ca-2001-26-nimda].&lt;/p&gt;
&lt;/blockquote&gt;

flowchart LR
    A[Infected client] --&amp;gt;|Email with readme.exe| B[New client via IE MIME bug MS01-020]
    A --&amp;gt;|Write to writable share| C[New client via SMB share]
    D[Infected IIS server] --&amp;gt;|Inject JS into served pages| E[New client via web browse]
    A --&amp;gt;|HTTP scan + Unicode traversal| F[New IIS server via dir traversal]
    F --&amp;gt;|Reuse Code Red II root.exe if present| F
    F --&amp;gt; D
&lt;p&gt;Some retellings give Nimda &quot;five&quot; propagation vectors, conflating distinct sub-paths or counting the reuse of Code Red II&apos;s &lt;code&gt;root.exe&lt;/code&gt; as a separate vector. CERT&apos;s canonical taxonomy, reproduced verbatim above, is four [@cert-ca-2001-26-nimda]. The fifth-vector phrasing in popular retellings is folk-knowledge.&lt;/p&gt;
&lt;p&gt;The connected-graph structure matters. The patch for the IIS Unicode directory-traversal bug (MS00-078, originally posted October 17, 2000) had been available for eleven months [@ms00-078-iis-traversal]. The patch for the IE MIME-handling bug (MS01-020, originally posted March 29, 2001) had been available for nearly six months [@ms01-020-ie-mime]. The MS01-033 patch behind Code Red and Code Red II had been available for three months [@ms01-033-idq]. Microsoft shipped the cumulative remediation as MS01-044 [@cert-ca-2001-26-nimda]. Every individual hole had been a known, patched single-issue vulnerability. Nimda took the graph of those holes and walked it.&lt;/p&gt;
&lt;p&gt;The lesson is structural. Response treats vulnerabilities as point fixes. Nimda&apos;s empirical evidence was that, in a sufficiently large monoculture, the unpatched subsets of multiple vulnerabilities had become &lt;em&gt;connected&lt;/em&gt;. Patching is a per-host, per-vulnerability operation; the attacker&apos;s view is the union over all hosts of the union over all unpatched vulnerabilities. The latter is a much larger surface.&lt;/p&gt;
&lt;h3&gt;SQL Slammer (January 25, 2003, 05:30 UTC)&lt;/h3&gt;
&lt;p&gt;Sixteen months after Nimda, the era&apos;s capstone arrived in the form of a 376-byte UDP datagram.&lt;/p&gt;
&lt;p&gt;Slammer (also called Sapphire) exploited a buffer overflow in the SQL Server Resolution Service that Microsoft had patched in MS02-039, &lt;strong&gt;six months earlier&lt;/strong&gt;. The payload was small enough to fit in a single UDP packet, and the protocol it targeted (UDP port 1434) was connectionless, so each scan was one packet, sent at line rate. The CAIDA measurement -- Moore, Paxson, Savage, Shannon, Staniford and Weaver, &lt;em&gt;IEEE Security &amp;amp; Privacy&lt;/em&gt; 2003 -- is the primary record:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Sapphire began to infect hosts slightly before 05:30 UTC on Saturday, January 25 (2003). [...] doubled in size every 8.5 seconds. [...] infected more than 90 percent of vulnerable hosts within 10 minutes [...] at least 75,000 hosts, perhaps considerably more [...] over 55 million scans per second.&quot; [@caida-slammer]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Popular retellings often round Slammer&apos;s reach to &quot;75% of vulnerable SQL servers.&quot; The CAIDA primary measurement is &lt;strong&gt;~75,000 hosts&lt;/strong&gt; as the lower bound, and &quot;more than 90 percent of vulnerable hosts within 10 minutes&quot; as the saturation percentage [@caida-slammer]. The two figures are not the same.&lt;/p&gt;
&lt;p&gt;The 8.5-second doubling time is the load-bearing number. Worm spread under random-constant-spread (RCS) scanning follows a logistic curve: exponential at the start, saturating as the worm runs out of vulnerable targets. The differential equation is well behaved and was modeled in detail by Stuart Staniford, Vern Paxson, and Nicholas Weaver at USENIX Security 2002, in a paper that predicted (six months before Slammer) that worms with sufficiently high scan rates would saturate the global vulnerable population in minutes, not hours [@staniford-paxson-weaver-2002].&lt;/p&gt;
&lt;p&gt;Plug the parameters in and watch it happen:&lt;/p&gt;
&lt;p&gt;{`
// SI-style worm spread under random constant scanning.
// dN/dt = K * N * (1 - N/V)
// Where:
//   N(t) = infected population at time t (seconds)
//   V    = total vulnerable population
//   K    = effective contact rate per infected host per second
//          = (scans per second per host) * (V / address-space size)
//
// Slammer defaults (CAIDA Moore et al. 2003):
//   ~75,000 vulnerable MSSQL hosts (lower bound)
//   ~26,000 packets/sec sent from a typical infected host before bandwidth saturation
//   IPv4 routable space ~ 2^32 addresses, of which ~2^31 reachable
//
// Result: doubling time ~8.5 s, ~90% saturation in ~10 min.&lt;/p&gt;
&lt;p&gt;const V = 75000;
const scansPerSecPerHost = 26000;
const addressSpace = Math.pow(2, 31);
const K = scansPerSecPerHost * (V / addressSpace);
const dt = 1;
let N = 1;
let lastPrint = 0;
for (let t = 0; t &amp;lt;= 700; t += dt) {
  const dN = K * N * (1 - N / V);
  N += dN * dt;
  if (t - lastPrint &amp;gt;= 30 || (N &amp;gt;= V * 0.9 &amp;amp;&amp;amp; lastPrint &amp;lt; t)) {
    const pct = (100 * N / V).toFixed(1);
    console.log(`t=${t.toString().padStart(3)}s  N=${Math.round(N).toString().padStart(6)}  (${pct}%)`);
    lastPrint = t;
    if (N &amp;gt;= V * 0.999) break;
  }
}
`}&lt;/p&gt;
&lt;p&gt;The simulator says what CAIDA measured: saturation, regardless of where the human patch process starts from, in roughly ten minutes. Read that twice. There is no version of &quot;patch faster&quot; that wins this race. The race ends before a human operator can log in, open the bulletin, download the binary, and apply it. Even if every operator on the planet had been at their console with the patch staged and ready, they could not have outrun an 8.5-second doubling.&lt;/p&gt;

The logistic equation $dN/dt = KN(1 - N/V)$ has closed-form solution $N(t) = V / (1 + (V/N_0 - 1) e^{-Kt})$. The doubling time near the start (when $N \ll V$) is $\tau = \ln(2)/K$. For Slammer&apos;s measured doubling time of 8.5 seconds, $K = \ln(2)/8.5 \approx 0.0815$ per second. The time to reach 90% of $V$ from a seed of $N_0 = 1$ is $t_{90} = (1/K) \ln((V - N_0)/(N_0 \cdot V/(0.9V) - N_0)) \approx (1/K) \ln(0.9V/0.1) \approx (1/0.0815) \ln(9V)$. For $V = 75{,}000$, $t_{90} \approx 12.3 \cdot \ln(675{,}000) \approx 165$ seconds, plus the time spent in the slow start-up phase from $N_0=1$ to a few hundred infections. The empirical 10-minute figure includes both phases. The structural result is parameter-insensitive: any worm with a per-host scan rate that produces a sub-minute doubling will saturate before any human operator can intervene.
&lt;p&gt;If the attacker&apos;s loop (find bug, weaponize, propagate) is now structurally faster than the defender&apos;s loop (find bug, ship patch, customer installs), then &quot;patch faster&quot; stops being the answer and a different answer becomes necessary. The only durable defense against a sub-minute doubling time is to &lt;strong&gt;ship fewer vulnerabilities to begin with&lt;/strong&gt;. That requires changes upstream of the patch pipeline -- in how code is written, reviewed, tested, and signed off.&lt;/p&gt;
&lt;p&gt;Which is what the advisory version of secure development had been preaching since 1975.&lt;/p&gt;
&lt;p&gt;So why was Microsoft still shipping &lt;code&gt;idq.dll&lt;/code&gt;-class bugs in 2001?&lt;/p&gt;
&lt;h2&gt;5. What Microsoft Already Had (and Why It Wasn&apos;t Enough)&lt;/h2&gt;
&lt;p&gt;This is the section that confronts the literal thesis head-on. Take an inventory of what existed, in Microsoft and outside it, on January 1, 2002:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://paragmali.com/blog/windows-security-boundaries-the-document-that-decides-what-g/&quot; rel=&quot;noopener&quot;&gt;Microsoft Security Response Center (MSRC)&lt;/a&gt;.&lt;/strong&gt; Founded in 1998 to coordinate vulnerability disclosure and ship security bulletins (the numbered series MS98-001 onward) [@msrc-org] [@howard-lipner-push-2003]. The org chart was real; so was the bulletin pipeline; so was the working relationship with CERT/CC and external researchers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Secure Windows Initiative (SWI).&lt;/strong&gt; Started around 2000 as a small in-house secure-development team, led by Michael Howard inside the Windows division [@howard-lipner-push-2003].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;STRIDE.&lt;/strong&gt; A categorical list of threat types (Spoofing, Tampering, Repudiation, Information disclosure, Denial of service, Elevation of privilege), written by Loren Kohnfelder and Praerit Garg in an internal Microsoft memo dated April 1, 1999, titled &quot;The Threats to Our Products.&quot; The memo is no longer hosted on Microsoft&apos;s own site, but it has been publicly preserved at Adam Shostack&apos;s archive [@shostack-stride-memo-archive], with an independent mirror at FIRST [@first-stride-memo-mirror]; Shostack&apos;s 2014 book remains the authoritative chain-of-custody analysis [@shostack-tm-book].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A Microsoft-authored secure-coding book.&lt;/strong&gt; Michael Howard and David LeBlanc&apos;s &lt;em&gt;Writing Secure Code&lt;/em&gt;, Microsoft Press, first edition November 2001 -- two months before the memo. Bill Gates is widely reported to have required Microsoft engineers to read it; the book itself documents the banned-API list, threat-modeling templates, and STRIDE walkthroughs that the Push later mandated [@howard-leblanc-wsc].&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Outside Microsoft, the substrate was older still:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Saltzer and Schroeder.&lt;/strong&gt; Jerome Saltzer and Michael Schroeder, &quot;The Protection of Information in Computer Systems,&quot; &lt;em&gt;Proceedings of the IEEE&lt;/em&gt; 63(9), September 1975. Eight design principles -- economy of mechanism, fail-safe defaults, complete mediation, open design, separation of privilege, least privilege, least common mechanism, psychological acceptability -- still the textbook starting point [@saltzer-schroeder-1975].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Orange Book.&lt;/strong&gt; DoD Trusted Computer System Evaluation Criteria (DoD 5200.28-STD), 1983 and reissued 1985. Graded assurance levels D, C1, C2, B1, B2, B3, A1. The pre-existing vocabulary of &quot;trusted computing&quot; that the Gates memo deliberately echoed and broadened to &quot;trustworthy&quot; [@tcsec-orange-book].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OpenBSD audit culture.&lt;/strong&gt; Theo de Raadt&apos;s OpenBSD project, since the summer of 1996, with a permanent audit team that the project&apos;s own page describes verbatim: &quot;Our security auditing team typically has between six and twelve members who continue to search for and fix new security holes. We have been auditing since the summer of 1996&quot; [@openbsd-security].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Attack trees.&lt;/strong&gt; Bruce Schneier, &quot;Attack Trees,&quot; &lt;em&gt;Dr. Dobb&apos;s Journal&lt;/em&gt;, December 1999. A formal methodology for describing system security as goal-rooted decision trees with AND/OR composition and per-leaf cost annotations [@schneier-attack-trees-1999].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CERT/CC.&lt;/strong&gt; Carnegie Mellon&apos;s Computer Emergency Response Team, founded November 1988 in response to the Morris worm. Author of the CA-1999-04 / CA-2001-19 / CA-2001-26 / CA-2000-04 advisories that frame the previous two sections [@cert-ca-1999-04-melissa] [@cert-ca-2001-19-codered] [@cert-ca-2001-26-nimda] [@cert-ca-2000-04-iloveyou].&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Lay those rows out as a table and look at the right-most column:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Discipline component&lt;/th&gt;
&lt;th&gt;Who had it&lt;/th&gt;
&lt;th&gt;When&lt;/th&gt;
&lt;th&gt;Release-blocking authority?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Foundational principles&lt;/td&gt;
&lt;td&gt;Saltzer and Schroeder [@saltzer-schroeder-1975]&lt;/td&gt;
&lt;td&gt;1975&lt;/td&gt;
&lt;td&gt;No (academic publication)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Graded assurance criteria&lt;/td&gt;
&lt;td&gt;DoD Orange Book [@tcsec-orange-book]&lt;/td&gt;
&lt;td&gt;1985&lt;/td&gt;
&lt;td&gt;No (procurement criterion only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Response coordination&lt;/td&gt;
&lt;td&gt;CERT/CC [@cert-ca-1999-04-melissa]&lt;/td&gt;
&lt;td&gt;1988&lt;/td&gt;
&lt;td&gt;No (external coordinator)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Audit-driven engineering&lt;/td&gt;
&lt;td&gt;OpenBSD [@openbsd-security]&lt;/td&gt;
&lt;td&gt;1996&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes -- within OpenBSD only&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vendor response center&lt;/td&gt;
&lt;td&gt;MSRC [@msrc-org] [@howard-lipner-push-2003]&lt;/td&gt;
&lt;td&gt;1998&lt;/td&gt;
&lt;td&gt;No (post-release)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Internal threat categorization&lt;/td&gt;
&lt;td&gt;Kohnfelder and Garg STRIDE memo [@shostack-tm-book] [@shostack-stride-memo-archive]&lt;/td&gt;
&lt;td&gt;April 1999&lt;/td&gt;
&lt;td&gt;No (advisory)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;External threat-modeling methodology&lt;/td&gt;
&lt;td&gt;Schneier attack trees [@schneier-attack-trees-1999]&lt;/td&gt;
&lt;td&gt;December 1999&lt;/td&gt;
&lt;td&gt;No (publication)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;In-house secure-development team&lt;/td&gt;
&lt;td&gt;SWI (Howard) [@howard-lipner-push-2003]&lt;/td&gt;
&lt;td&gt;~2000&lt;/td&gt;
&lt;td&gt;No (advisory)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Secure-coding book&lt;/td&gt;
&lt;td&gt;Howard and LeBlanc [@howard-leblanc-wsc]&lt;/td&gt;
&lt;td&gt;November 2001&lt;/td&gt;
&lt;td&gt;No (recommendation)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The load-bearing column is the last one. Every row except OpenBSD-within-OpenBSD reads &lt;strong&gt;No&lt;/strong&gt;, and OpenBSD&apos;s &quot;Yes&quot; is a special case -- the auditors and the engineers were the same self-selected community on a small homogeneous codebase shipped without a revenue obligation.&lt;/p&gt;
&lt;p&gt;That column is the article&apos;s first aha moment.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Microsoft was not the first to articulate secure-systems-design principles (Saltzer and Schroeder, 1975). It was not the first to do audit-driven engineering (OpenBSD, 1996). It was not the first to popularize threat modeling externally (Schneier, December 1999), have an internal threat-categorization framework (Kohnfelder and Garg, April 1999), or run a security-response organization (CERT/CC since 1988; MSRC since 1998). What Microsoft &lt;em&gt;was&lt;/em&gt; first to do, on January 15, 2002 and operationalized on February 11, 2002, was apply &lt;strong&gt;release-blocking executive authority across an entire dominant-platform vendor&lt;/strong&gt; to make secure development a non-negotiable engineering gate.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The corrected sentence is harder to fit on a magazine cover. It is also defensible.&lt;/p&gt;

OpenBSD shipped audit-driven engineering culture six years before the Windows Security Push, with the slogan its security page has carried for two decades:
Only two remote holes in the default install, in a heck of a long time! -- OpenBSD Project, security page [@openbsd-security]
&lt;p&gt;OpenBSD&apos;s model worked for a small homogeneous codebase with self-selected auditors and a permissive-license, no-revenue context. The SDL&apos;s model was built for a fifty-thousand-person, hundred-million-line, quarterly-revenue context. They are parallel paths, not competitors. The era&apos;s lesson is that &lt;em&gt;both&lt;/em&gt; were necessary discoveries; neither alone would have served the other&apos;s population.
&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;What did &quot;advisory&quot; mean in 2000-2001 Microsoft? Steve Lipner&apos;s ACSAC 2004 paper is explicit: in the pre-Push state, an engineering manager could decline a security review with no organizational consequence. SWI could &lt;em&gt;recommend&lt;/em&gt;. SWI could not &lt;em&gt;require&lt;/em&gt;. The Microsoft-authored book sat on every engineer&apos;s desk and the threat-categorization memo had been internal for almost three years -- and Code Red v1, Code Red v2, Code Red II, and Nimda all exploited code that had shipped &lt;em&gt;after&lt;/em&gt; SWI&apos;s founding [@howard-lipner-push-2003] [@lipner-acsac-2004].&lt;/p&gt;
&lt;p&gt;That is the empirical evidence the era ran on. Methods without authority did not stop the worms.&lt;/p&gt;

Microsoft was not the first to articulate, audit, popularize, categorize, or respond. Microsoft was the first to make secure development non-negotiable at desktop-monopoly scale.
&lt;p&gt;So if the methods, the books, the threat-modeling framework, the response center, the engineers, and the public peer pressure were all already there, what changed at 5:22 PM Pacific on Tuesday, January 15, 2002?&lt;/p&gt;
&lt;h2&gt;6. The Memo (January 15, 2002)&lt;/h2&gt;
&lt;p&gt;Open with the email header itself, preserved verbatim by Wired&apos;s republication and the Help With Windows mirror, both of which kept the original &lt;code&gt;From:&lt;/code&gt;, &lt;code&gt;Sent:&lt;/code&gt;, &lt;code&gt;To:&lt;/code&gt;, &lt;code&gt;Subject:&lt;/code&gt; block intact:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;-----Original Message-----
From: Bill Gates
Sent: Tuesday, January 15, 2002 5:22 PM
To: Microsoft and Subsidiaries: All FTE
Subject: Trustworthy computing
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;[@gates-memo-wired] [@helpwithwindows-billg]&lt;/p&gt;
&lt;p&gt;Popular retellings sometimes describe the memo as a &quot;5 AM email Bill Gates wrote in the dark.&quot; The preserved mail headers above are unambiguous: the memo was sent at &lt;strong&gt;5:22 PM Pacific&lt;/strong&gt; on a Tuesday afternoon, with full distribution to &quot;Microsoft and Subsidiaries: All FTE&quot; -- every full-time employee of the company [@gates-memo-wired] [@helpwithwindows-billg]. The 5 AM phrasing is folk-knowledge; the headers preserved by Wired are the primary record.&lt;/p&gt;
&lt;p&gt;The memo runs roughly 1,500 words. It is structured around four pillars -- Security, Privacy, Reliability, and Business Integrity -- that, the memo argues, must take precedence over feature work whenever the two are in tension [@gates-memo-wired]:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pillar&lt;/th&gt;
&lt;th&gt;What the memo asks for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Code resilient to attack; products that ship secure out of the box, by default, in deployment.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Privacy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Products that handle customer data with informed consent and minimal collection.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reliability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Products that fail predictably and recover gracefully; uptime as a measurable property.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Business Integrity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Transparent dealings; respect for the customer relationship across the company&apos;s behavior, not just its products.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Read the four together and the structure is not a list of features. It is a redefinition of what shipping the product &lt;em&gt;means&lt;/em&gt;. A Windows release in 2001 shipped when the feature list closed; the memo proposed that, going forward, a Windows release ships when feature list, security posture, privacy posture, reliability posture, and the company&apos;s standing with the customer were all simultaneously acceptable.&lt;/p&gt;
&lt;p&gt;The operational anchor of the memo is one sentence every subsequent retelling quotes, and that the Push directly inherited as its decision rule:&lt;/p&gt;

&quot;When we face a choice between adding features and resolving security issues, we need to choose security.&quot; -- Bill Gates, &quot;Trustworthy computing&quot; memo, January 15, 2002 [@gates-memo-wired]
&lt;p&gt;Note what the memo &lt;em&gt;did not do&lt;/em&gt;. It did not name an algorithm. It did not invent STRIDE; STRIDE had been internal for two and a half years already [@shostack-tm-book]. It did not write &lt;code&gt;banned.h&lt;/code&gt;; the banned-API list had been in Howard and LeBlanc&apos;s book on bookshelves for two months [@howard-leblanc-wsc]. And, contrary to a common retelling, it did not delay the launch of Visual Studio .NET.&lt;/p&gt;
&lt;p&gt;Visual Studio .NET launched on schedule on &lt;strong&gt;February 13, 2002&lt;/strong&gt;, four weeks after the memo, at the VSLive! 2002 Conference in San Francisco, with Bill Gates delivering the keynote address [@msft-news-vsnet-launch-2002]. The December 2001 work the retrospectives sometimes call a &quot;delay&quot; was a &lt;em&gt;pre-launch security review&lt;/em&gt; of the .NET runtime; the memo references that review by name as the &lt;strong&gt;template&lt;/strong&gt; for what the company was about to do across every product [@gates-memo-wired]. The &quot;delayed by security&quot; framing is folk-knowledge; the memo itself describes VS .NET&apos;s December review as a success story.&lt;/p&gt;
&lt;p&gt;What the memo &lt;em&gt;did&lt;/em&gt; do was supply the one input every other piece on the table had been missing: &lt;strong&gt;executive authority, top-down, to halt feature work on security grounds without arguing about it.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To see why that is the operational form of the memo&apos;s contribution, compare it to Gates&apos;s two other priority memos. The &quot;Internet Tidal Wave&quot; of May 26, 1995 redirected Microsoft toward the web; the company restructured around online services and browser strategy in its wake [@gates-tidal-wave-bbc-pdf]. The &lt;strong&gt;.NET / NGWS strategy memo&lt;/strong&gt;, delivered alongside Gates&apos;s Forum 2000 keynote on &lt;strong&gt;June 22, 2000&lt;/strong&gt;, redirected the company toward managed code and a unified runtime; Visual Studio .NET, the CLR, ASP.NET, and ADO.NET all trace to it.Common retellings date the .NET strategy memo to 1999. The Microsoft News Center record places the NGWS / .NET unveiling at Forum 2000 on &lt;strong&gt;June 22, 2000&lt;/strong&gt;; the strategy was branded &quot;Next Generation Windows Services&quot; before the .NET name stuck. The 1999 dating slips in because the underlying COM-runtime work began earlier, but the company-wide priority memo is a 2000 document.&lt;/p&gt;
&lt;p&gt;Both pointed Microsoft at something new. Trustworthy Computing was different in shape. It did not redirect the company toward something new. It &lt;em&gt;halted&lt;/em&gt; the company in place. The pillars were not a roadmap; they were a precondition. That structural difference -- &lt;em&gt;stop, before you start anything else&lt;/em&gt; -- is what gave the Push its character.&lt;/p&gt;

The memo named three deputies who would carry the program forward. Craig Mundie (then Microsoft&apos;s chief technical officer, leading the Trustworthy Computing leadership team) was the named architect of the Trustworthy Computing initiative itself [@msft-news-charney-jan-2002]; Jeff Raikes (then Group Vice President for Productivity and Business Services) carried the program into Office [@msft-news-raikes-fusion-2002]; and on January 31, 2002 -- sixteen days after the memo -- Microsoft announced the hire of Scott Charney from PricewaterhouseCoopers&apos; Cybercrime Prevention and Response Practice as Chief Security Strategist, with a start date of April 1, 2002, to make the program operationally permanent [@msft-news-charney-jan-2002]. Charney would lead Microsoft&apos;s Trustworthy Computing organization for the next thirteen years. The memo was one event; the people who made it survive past the ten-week Push were the institutional half of the story.
&lt;p&gt;The memo was the discrete institutional moment. What it required next was the operationalization step that converted it from rhetoric into engineering. That step took twenty-seven days to start and roughly ten weeks to run.&lt;/p&gt;
&lt;h2&gt;7. The Windows Security Push (February-April 2002)&lt;/h2&gt;
&lt;p&gt;The mechanics come from Michael Howard and Steve Lipner&apos;s IEEE &lt;em&gt;Security and Privacy&lt;/em&gt; paper of January-February 2003, &quot;Inside the Windows Security Push,&quot; and from Lipner&apos;s December 2004 ACSAC paper &quot;The Trustworthy Computing Security Development Lifecycle.&quot; Stripped of the framing, the numbers are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Feature work in the Windows Division halted on or about &lt;strong&gt;February 11, 2002&lt;/strong&gt; [@howard-lipner-push-2003].&lt;/li&gt;
&lt;li&gt;The Push ran for approximately &lt;strong&gt;ten weeks&lt;/strong&gt;, through April 2002 [@howard-lipner-push-2003].&lt;/li&gt;
&lt;li&gt;The participating headcount was approximately &lt;strong&gt;8,500 Windows engineers&lt;/strong&gt; [@howard-lipner-push-2003].The round figure of &quot;10,000 engineers&quot; in many retrospectives is a company-wide aggregate that includes the &lt;em&gt;serial&lt;/em&gt; Office, .NET, and SQL Server pushes that followed through 2002-2003. The Windows-only Push figure from the Howard and Lipner primary is &lt;strong&gt;~8,500&lt;/strong&gt;; the trade-press corroboration (Washington Technology, July 2002) cross-references Gates&apos;s own July 19, 2002 internal newsletter [@howard-lipner-push-2003] [@washtech-microsoft-100m].&lt;/li&gt;
&lt;li&gt;The total cost in foregone feature work was approximately &lt;strong&gt;$100 million&lt;/strong&gt; [@washtech-microsoft-100m] [@howard-lipner-push-2003].&lt;/li&gt;
&lt;li&gt;The measurable outcome was approximately a &lt;strong&gt;50% reduction in publicly reported security vulnerabilities&lt;/strong&gt; for Windows Server 2003 over comparable post-release windows versus Windows 2000 [@howard-lipner-push-2003].The ~50% figure is per-window externally-discovered vulnerability counts, per Howard and Lipner 2003 -- &lt;em&gt;not&lt;/em&gt; per-KLoC defect density. The narrative role (measurable post-release improvement) holds either way, but the caveat matters for readers reusing the number.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Push pipeline looked like this:&lt;/p&gt;

flowchart LR
    A[Mandatory training: Howard, Lipner, LeBlanc as instructors] --&amp;gt; B[STRIDE threat model per component]
    B --&amp;gt; C[Banned-API audit against banned.h and strsafe.h]
    C --&amp;gt; D[Fuzz testing of network-facing components]
    D --&amp;gt; E[Final Security Review gate]
    E --&amp;gt; F[Release approval or block]
&lt;p&gt;Three of the boxes in that pipeline need definitions, because they are the load-bearing terms the rest of the article and every SDL descendant inherit.&lt;/p&gt;

A C header authored at Microsoft during and after the Push that re-declares roughly forty unsafe C runtime functions (`strcpy`, `strcat`, `gets`, `sprintf`, `_snprintf`, `wcscpy`, `_mbscpy`, and more) as compile-time errors. The pattern is a `#pragma deprecated` plus a `#define` that expands to an undefined symbol, so any source file that includes `banned.h` and then calls a banned function fails to compile. The descendant in Microsoft&apos;s current Windows driver toolchain is the static-analyzer warning **C28719**, which release-gates Windows driver submissions to this day [@msft-c28719].

A safer-by-default replacement string-handling API set introduced by Microsoft alongside `banned.h`. The `Strsafe.h` header (and the Win32 reference page that still ships in Microsoft Learn) defines `StringCbCopy`, `StringCbCat`, `StringCbPrintf`, `StringCchCopy`, `StringCchCat`, `StringCchPrintf`, and their wide-character variants. Every function takes an explicit destination-buffer size and returns an `HRESULT` so the caller can detect truncation rather than overrun [@msft-strsafe]. The C11 `_s` family (`strcpy_s`, `strcat_s`, `sprintf_s`) is the standards-track parallel.

The release-blocking sign-off step at the end of the SDL pipeline. Before a product can ship, an FSR examines the threat model, the residual vulnerabilities, the banned-API audit results, the fuzz-test coverage, the static-analysis warnings, and the operational response plan, and decides whether the release meets the security bar. A failed FSR blocks the release. The FSR is the single component that converts every preceding &quot;should&quot; into a hard &quot;must&quot; -- it is where the advisory pipeline becomes the mandatory one [@lipner-acsac-2004] [@howard-lipner-sdl-book].
&lt;p&gt;Place the same banned-API substitution that every Windows engineer learned that spring next to its FSR-approved replacement, with the surviving 2026 compiler-enforced warning called out:&lt;/p&gt;
&lt;p&gt;{`
// BEFORE THE PUSH -- this compiles, and overflows if src is too long.
// C runtime; allowed in C89; the entire bug class behind Code Red et al.
void copyName_BANNED(char* dst, const char* src) {
  // strcpy(dst, src);
  // After banned.h is included, the above line FAILS TO COMPILE:
  //   error C4996: &apos;strcpy&apos;: This function or variable may be unsafe.
  //   error C28719: Banned API Usage: strcpy is a Banned API.
}&lt;/p&gt;
&lt;p&gt;// AFTER THE PUSH -- this is the FSR-approved replacement.
// strsafe.h, mandatory after February 2002 for Windows code.
// Microsoft&apos;s C28719 still release-gates Windows drivers in 2026.
function copyName_OK(dst, dstSize, src) {
  // StringCbCopy(dst, dstSize, src);
  // Returns S_OK on success, STRSAFE_E_INSUFFICIENT_BUFFER on truncation.
  // The compiler knows dstSize; the static analyzer can prove the bound.
  console.log(&apos;FSR-approved: explicit destination size, returns HRESULT.&apos;);
}&lt;/p&gt;
&lt;p&gt;copyName_OK(&apos;buffer&apos;, 16, &apos;David Cutler&apos;);
`}&lt;/p&gt;
&lt;p&gt;The substitution is the entire engineering theme of the Push in one line. &lt;code&gt;strcpy(dst, src)&lt;/code&gt; is undecidable in the general case: you cannot prove from the call site that &lt;code&gt;src&lt;/code&gt; fits in &lt;code&gt;dst&lt;/code&gt; without information the call site does not have. &lt;code&gt;StringCbCopy(dst, dstSize, src)&lt;/code&gt; is mechanically checkable: the destination size is explicit, the function returns truncation as a recoverable error, and a static analyzer can verify the bound at every call site. The class of bugs behind Code Red did not become &lt;em&gt;easier&lt;/em&gt; to write; it became &lt;em&gt;uncompilable&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The state change is best shown as a comparison table:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Discipline component&lt;/th&gt;
&lt;th&gt;Pre-Push state&lt;/th&gt;
&lt;th&gt;Post-Push state&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Training&lt;/td&gt;
&lt;td&gt;Opt-in; not all engineers attended&lt;/td&gt;
&lt;td&gt;Mandatory across the Windows Division [@howard-lipner-push-2003]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Threat modeling&lt;/td&gt;
&lt;td&gt;Per-team optional&lt;/td&gt;
&lt;td&gt;Per-component mandatory; STRIDE-driven [@howard-lipner-push-2003]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Banned-API enforcement&lt;/td&gt;
&lt;td&gt;Recommended in the SWI guidance&lt;/td&gt;
&lt;td&gt;Compile-time error via &lt;code&gt;banned.h&lt;/code&gt;; replacement via &lt;code&gt;strsafe.h&lt;/code&gt; [@msft-strsafe] [@msft-c28719]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code review&lt;/td&gt;
&lt;td&gt;Voluntary&lt;/td&gt;
&lt;td&gt;Release-gate via Final Security Review [@lipner-acsac-2004]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authority&lt;/td&gt;
&lt;td&gt;Advisory (SWI could recommend)&lt;/td&gt;
&lt;td&gt;Release-blocking (FSR could block) [@lipner-acsac-2004]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Measurable outcome&lt;/td&gt;
&lt;td&gt;None published&lt;/td&gt;
&lt;td&gt;~50% reduction in publicly reported vulnerabilities, WS2003 vs Win2000 [@howard-lipner-push-2003]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The right-hand column is, line by line, the same activities the left-hand column lists. Training is training. Threat modeling is threat modeling. The banned-API list is the same list LeBlanc and Howard had been publishing for years. Static analysis is static analysis. What changed in every row is the verb: from &quot;may,&quot; &quot;should,&quot; and &quot;recommended&quot; to &quot;must,&quot; &quot;shall,&quot; and &quot;release-blocking.&quot;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The breakthrough was organizational, not technical. The Push used the same training material, the same banned-API list, the same threat-modeling framework, and the same code-review checklist that SWI, Howard, LeBlanc, and Schneier had been writing for two years. What changed was the signoff power. Training became mandatory; threat modeling became per-component-mandatory; banned APIs became compile-time errors; code review became a release gate; and the Final Security Review acquired the authority to block a ship date. The Push did not invent new methods. It gave the existing methods executive authority.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Same checklists, different signoff power. That single sentence is the unit of work the Push did. Every other secure-development framework on the industry shelf in 2026 is, organizationally, a restatement of that unit at different scales: BSIMM observes how vendors did it, OWASP SAMM prescribes how to do it, NIST SSDF mandates it for U.S. federal suppliers, ISO/IEC 27034 makes it certifiable. The technology was downstream of the authority [@bsimm-home] [@owasp-samm-model] [@nist-ssdf-218] [@iso-27034-1].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ten weeks of training is one event. A discipline is a &lt;em&gt;repeatable&lt;/em&gt; event. The Push needed to be codified into something a product team could &lt;em&gt;do&lt;/em&gt; on every release.&lt;/p&gt;
&lt;h2&gt;8. What the Discipline Became: The SDL Lineage (2002-2006)&lt;/h2&gt;
&lt;p&gt;Codification ran in two steps.&lt;/p&gt;
&lt;p&gt;The first step was Steve Lipner&apos;s ACSAC 2004 paper, &quot;The Trustworthy Computing Security Development Lifecycle,&quot; the first formal &lt;em&gt;external&lt;/em&gt; description of the SDL as a multi-phase release-engineering process [@lipner-acsac-2004]. ACSAC is a peer-reviewed venue with a security-practitioner audience; the paper put the program on the academic record and started the citation chain.&lt;/p&gt;
&lt;p&gt;The second step was the book. Howard and Lipner, &lt;em&gt;The Security Development Lifecycle&lt;/em&gt;, Microsoft Press 2006 (ISBN 978-0-7356-2214-2) [@howard-lipner-sdl-book]. The book documents every phase, every checklist, every threat-modeling template, every banned-API entry, every FSR criterion. It is what made the methodology &lt;em&gt;exportable&lt;/em&gt;: an organization not named Microsoft could pick up the book and run an SDL-shape program of its own.&lt;/p&gt;

A software-engineering process model that integrates security activities into every phase of a product release. The canonical Microsoft formulation, in the 2006 Howard and Lipner book, is a seven-phase pipeline: Training, Requirements, Design (with mandatory STRIDE threat modeling), Implementation (with banned-API enforcement and mandatory static analysis), Verification (fuzz testing and dynamic analysis), Release (Final Security Review and a signed-off response plan), and Response (feeds back into MSRC). The current Microsoft public formulation organizes the same activities as 10 practices spanning 5 lifecycle stages: Design, Code, Build and Deploy, Run, and Zero Trust governance [@msft-sdl-practices] [@msft-sdl-overview].
&lt;p&gt;The SDL phase pipeline in its canonical 2006 form:&lt;/p&gt;

flowchart LR
    A[Training] --&amp;gt; B[Requirements]
    B --&amp;gt; C[Design: STRIDE threat modeling]
    C --&amp;gt; D[Implementation: banned-API + static analysis]
    D --&amp;gt; E[Verification: fuzz + dynamic analysis]
    E --&amp;gt; F[Release: Final Security Review]
    F --&amp;gt; G[Response: MSRC]
    G -.feedback.-&amp;gt; A
&lt;p&gt;The current Microsoft SDL has shifted with the industry. The 2026 public formulation organizes the same activities as ten practices spanning five lifecycle stages: Design, Code, Build and Deploy, Run, and Zero Trust governance [@msft-sdl-practices] [@msft-sdl-overview]. Practices 1, 3, and 10 (security standards, threat modeling, training) map directly back to the 2002 Push and the 2006 book. Practices 2 and 4 (proven security features and cryptography standards) became prominent after the 2014-2017 TLS-bug wave: Heartbleed in April 2014 [@nvd-cve-2014-0160-heartbleed], POODLE in October 2014, Logjam in May 2015, ROBOT in December 2017. Practices 5 through 9 (supply chain, engineering environment, security testing, operational platform, monitoring and response) absorb post-SolarWinds (December 2020), Log4Shell (December 2021), and xz-utils (March 2024) lessons that did not exist in the original 2006 codification [@cisa-secure-by-design] [@slsa-home] [@freund-xz-disclosure].&lt;/p&gt;
&lt;p&gt;The SDL did not invent training, did not invent threat modeling, did not invent banned APIs, and did not invent audit-driven review. What it did was &lt;em&gt;assemble&lt;/em&gt; them, &lt;em&gt;mandate&lt;/em&gt; them, and &lt;em&gt;gate releases&lt;/em&gt; on them at a scale and authority no one had previously attempted at a desktop-monopoly vendor. Saltzer and Schroeder (1975), OpenBSD (1996), CERT/CC (1988), Schneier (1999), Kohnfelder and Garg (1999), and Howard and LeBlanc (2001) all contributed substrate; the SDL was an organizational achievement that depended on every one of those.&lt;/p&gt;

Two people deserve named credit for the SDL surviving past its 2002 birth. Scott Charney, joining Microsoft in March 2002 as Chief Security Strategist, ran the Trustworthy Computing organization for thirteen years and kept the program funded, staffed, and politically supported through three Windows releases (XP SP2 in 2004, Vista in 2006, Windows 7 in 2009). Steve Lipner became the program&apos;s external voice -- the IEEE *Security and Privacy* paper, the ACSAC paper, the Microsoft Press book, and the conference circuit that turned an internal-Microsoft methodology into an industry-wide practice. The historical credit for &quot;founding&quot; goes to Gates; the historical credit for *sustaining* goes to Charney and Lipner.
&lt;p&gt;A discipline becomes industry-standard when other organizations adopt or are compelled to adopt it. What happened to the SDL&apos;s template between 2006 and 2026?&lt;/p&gt;
&lt;h2&gt;9. What the Era Taught the Next 25 Years&lt;/h2&gt;
&lt;p&gt;Every major secure-development framework published since 2006 traces a recognizable lineage back to the same Push-shape ancestor. The genealogy fans out:&lt;/p&gt;

flowchart TD
    P0[2002 Windows Security Push] --&amp;gt; M1[2004 Microsoft SDL Lipner ACSAC]
    M1 --&amp;gt; B[2008 BSIMM descriptive 128 activities]
    M1 --&amp;gt; S[2009 OWASP SAMM prescriptive 15 practices]
    M1 --&amp;gt; I[2011 ISO/IEC 27034 certifiable]
    M1 --&amp;gt; F[2018 SAFECode Fundamental Practices 3rd ed]
    M1 --&amp;gt; N[2022 NIST SSDF SP 800-218 federal-supplier]
    M1 --&amp;gt; L[2021-2023 SLSA Build track post-SolarWinds]
    M1 --&amp;gt; C[2023 CISA Secure by Design + Pledge]
&lt;p&gt;The shorthand for each descendant:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Microsoft SDL.&lt;/strong&gt; The 2004 ACSAC paper and the 2006 book; today&apos;s ten-practice five-stage formulation [@lipner-acsac-2004] [@msft-sdl-practices].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BSIMM.&lt;/strong&gt; The Building Security In Maturity Model, descriptive (not prescriptive): 128 activities observed across 111 organizations in 8 industries, grouped into 12 practices in 4 domains [@bsimm-home].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OWASP SAMM v2.&lt;/strong&gt; Open Software Assurance Maturity Model, prescriptive: 15 security practices grouped into 5 business functions (Governance, Design, Implementation, Verification, Operations), with 3 maturity levels per practice [@owasp-samm-model] [@owasp-samm-about].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ISO/IEC 27034-1:2011.&lt;/strong&gt; The first internationally certifiable application-security standard, confirmed in 2022 [@iso-27034-1].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SAFECode Fundamental Practices, 3rd ed.&lt;/strong&gt; A community-curated practice catalog from the Software Assurance Forum for Excellence in Code, with an explicit smallest-organization onramp [@safecode-fundamental-practices].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NIST SP 800-218 (SSDF).&lt;/strong&gt; The Secure Software Development Framework, February 2022; legally voluntary in form but de-facto mandatory for U.S. federal suppliers via Executive Order 14028 and OMB Memorandum M-22-18 [@nist-ssdf-218].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SLSA v1.0.&lt;/strong&gt; Supply-chain Levels for Software Artifacts, the post-SolarWinds extension that adds build-integrity attestation to the SDL pattern [@slsa-v1-levels] [@slsa-home].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CISA Secure by Design and the Secure-by-Design Pledge.&lt;/strong&gt; A U.S. federal policy framework restating the SDL principles as expectations on commercial software vendors; the Pledge is voluntary and not legally binding [@cisa-secure-by-design] [@cisa-sbd-pledge].&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Below the family tree, every organization that picks one of these frameworks is also making a context-specific decision. A 2026 decision guide -- drawn from the SOTA work -- looks like this:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Primary framework&lt;/th&gt;
&lt;th&gt;Threat modeling&lt;/th&gt;
&lt;th&gt;Supply chain&lt;/th&gt;
&lt;th&gt;Memory safety&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Large proprietary vendor&lt;/td&gt;
&lt;td&gt;Microsoft SDL [@msft-sdl-practices]&lt;/td&gt;
&lt;td&gt;STRIDE in Microsoft TM Tool [@msft-threat-modeling-tool]&lt;/td&gt;
&lt;td&gt;SLSA Build L3 [@slsa-v1-levels]&lt;/td&gt;
&lt;td&gt;Rust in new components [@weston-bluehat-il-2023] [@cisa-memory-safe-roadmaps]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;U.S. federal supplier&lt;/td&gt;
&lt;td&gt;NIST SSDF + Secure by Design [@nist-ssdf-218] [@cisa-secure-by-design]&lt;/td&gt;
&lt;td&gt;Manifesto-aligned [@threat-modeling-manifesto]&lt;/td&gt;
&lt;td&gt;SLSA Build L2+ [@slsa-v1-levels]&lt;/td&gt;
&lt;td&gt;CISA memory-safe roadmap [@cisa-memory-safe-roadmaps]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mid-size SaaS&lt;/td&gt;
&lt;td&gt;OWASP SAMM [@owasp-samm-model]&lt;/td&gt;
&lt;td&gt;OWASP Threat Dragon [@owasp-threat-dragon]&lt;/td&gt;
&lt;td&gt;SLSA Build L1 [@slsa-v1-levels]&lt;/td&gt;
&lt;td&gt;Language choice per service&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Open-source project&lt;/td&gt;
&lt;td&gt;SAFECode + SLSA [@safecode-fundamental-practices] [@slsa-home]&lt;/td&gt;
&lt;td&gt;STRIDE or LINDDUN&lt;/td&gt;
&lt;td&gt;SLSA Build L1 + provenance&lt;/td&gt;
&lt;td&gt;Language choice per project&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Privacy-critical&lt;/td&gt;
&lt;td&gt;LINDDUN&lt;/td&gt;
&lt;td&gt;LINDDUN + DPIA&lt;/td&gt;
&lt;td&gt;per regulator&lt;/td&gt;
&lt;td&gt;per language toolchain&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI/LLM-integrated&lt;/td&gt;
&lt;td&gt;NIST AI RMF + OWASP LLM Top 10 [@nist-ai-rmf] [@owasp-llm-top-10]&lt;/td&gt;
&lt;td&gt;LLM Top 10 categories&lt;/td&gt;
&lt;td&gt;per model supply chain&lt;/td&gt;
&lt;td&gt;per language toolchain&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The table is a snapshot, not a prescription; the underlying point is that every cell is a child of the same 2002 organizational pattern, specialized to a population.&lt;/p&gt;
&lt;h3&gt;The five-stage cohort-migration playbook&lt;/h3&gt;
&lt;p&gt;Every meaningful security improvement since 2002 has had to walk a population through the same five-stage migration without breaking the legitimate-use long tail. The stages, drawn directly from how Microsoft has operated and what the larger industry has copied:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Ship telemetry first.&lt;/strong&gt; Before flipping any default, instrument the current behavior so you know who is using it, how, and how often.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Publish guidance naming the unsafe path as exceptional.&lt;/strong&gt; Documentation calls the behavior &quot;supported but deprecated&quot;; the change is announced.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flip the default behind documented escape hatches.&lt;/strong&gt; The new default is safe; users with a legitimate need can still opt back in via Group Policy, a registry key, an unblock checkbox, or an admin command.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deprecate on a published schedule.&lt;/strong&gt; Telemetry says the long tail is small enough to commit to a removal date; the date is announced one or more years out.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remove the capability.&lt;/strong&gt; The feature is no longer present; the escape hatch is no longer reachable.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Two worked examples make the playbook concrete -- the Office VBA macro block of 2022 and the SMBv1 deprecation of 1996-2017.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Office VBA macros from the internet (announced February 2022).&lt;/strong&gt; Microsoft committed to blocking VBA macros in Office documents that arrived from the internet (carrying the Mark of the Web). The five-channel rollout, as documented and re-documented on the current Microsoft Learn page, ran:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Channel&lt;/th&gt;
&lt;th&gt;Default-block date&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Current Channel Preview 2203&lt;/td&gt;
&lt;td&gt;April 12, 2022&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Current Channel 2206&lt;/td&gt;
&lt;td&gt;July 27, 2022 (after a July 2022 pause-and-resume)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Monthly Enterprise 2208&lt;/td&gt;
&lt;td&gt;October 11, 2022&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Semi-Annual Enterprise (Preview) 2208&lt;/td&gt;
&lt;td&gt;October 11, 2022&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Semi-Annual Enterprise 2208&lt;/td&gt;
&lt;td&gt;January 10, 2023&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;[@ms-learn-internet-macros-blocked]&lt;/p&gt;
&lt;p&gt;The escape hatches were explicit: per-document Unblock from the file&apos;s Properties dialog, configured Trusted Locations, signed-by-Trusted-Publishers, or Group Policy overrides for managed environments [@ms-learn-internet-macros-blocked]. The capability was not removed -- the playbook stopped at stage 3. The July 2022 pause-and-resume is the playbook&apos;s self-correcting feedback loop in action: Microsoft paused the Current Channel rollout in response to deployment-side issues, fixed them, and resumed [@ms-learn-internet-macros-blocked]. That this fix took &lt;strong&gt;twenty-seven years&lt;/strong&gt; from Concept&apos;s 1995 first detection to the Office VBA macro block of February 2022 is the era&apos;s tax for cohort migration without breaking the legitimate-use long tail.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://paragmali.com/blog/the-connection-that-refused-to-downgrade-twenty-five-years-o/&quot; rel=&quot;noopener&quot;&gt;SMBv1&lt;/a&gt; deprecation (1996 to 2025).&lt;/strong&gt; Server Message Block version 1 shipped in 1996. Microsoft publicly deprecated SMBv1 in 2014 (the long tail was many years of legacy installations). Ned Pyle, Principal Program Manager for Microsoft&apos;s Storage and File Services team, published the canonical &quot;Stop using SMB1&quot; Tech Community post on September 16, 2016 [@pyle-stop-using-smb1]. May and June 2017 brought the empirical forcing function: the WannaCry ransomware in May, the NotPetya wiper in June, both exploiting EternalBlue against SMBv1. October 2017&apos;s Windows 10 version 1709 shipped SMBv1 off by default. Windows Server 2019 and later, plus Windows 11, do not install SMBv1 at all. For Windows Home and Pro, the SMBv1 client auto-uninstalls after 15 days of non-use [@ms-learn-smbv1-not-installed]:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;1996&lt;/td&gt;
&lt;td&gt;SMBv1 ships with Windows NT 4.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2014&lt;/td&gt;
&lt;td&gt;Public deprecation announced&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;September 16, 2016&lt;/td&gt;
&lt;td&gt;Ned Pyle&apos;s &quot;Stop using SMB1&quot; Tech Community post [@pyle-stop-using-smb1]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;May-June 2017&lt;/td&gt;
&lt;td&gt;WannaCry and NotPetya empirical forcing function&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;October 2017 (1709)&lt;/td&gt;
&lt;td&gt;SMBv1 default-off in Windows 10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows Server 2019+, Windows 11&lt;/td&gt;
&lt;td&gt;Not installed by default; 15-day auto-uninstall on Home/Pro [@ms-learn-smbv1-not-installed]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &quot;Deprecation takes a decade&quot; is not vendor inefficiency. It is the cost of executing each playbook stage without breaking the legitimate-use long tail of business-critical software that depends on the capability. An empirical forcing function -- a worm, a ransomware wave, a public catastrophe -- is what compresses the late stages from years to months. WannaCry and NotPetya did to SMBv1 in 2017 what Code Red and Nimda did to the Windows defaults in 2002.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The aggregate catalog of unsafe defaults the era&apos;s lessons forced into the playbook, each at its own stage in 2026:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;NetBIOS over TCP exposed by default (deprecated; off by default).&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://paragmali.com/blog/ntlmless-the-death-of-ntlm-in-windows/&quot; rel=&quot;noopener&quot;&gt;NTLM&lt;/a&gt; as a first-class protocol (Microsoft announced default-off deprecation in October 2023, with a rolling transition through Windows Server 2025 and later releases [@techcommunity-ntlm-evolution-2023]).&lt;/li&gt;
&lt;li&gt;ActiveX by default in the IE Internet zone (removed with IE retirement in 2022).&lt;/li&gt;
&lt;li&gt;Autorun on removable media (default-off after Windows 7 patch in February 2011 [@kb971029-autorun-wayback]).&lt;/li&gt;
&lt;li&gt;Office macros enabled by default (default-block for internet-marked files since 2022 [@ms-learn-internet-macros-blocked]).&lt;/li&gt;
&lt;li&gt;PowerShell v2 (deprecated 2017, removed by default in Windows 11 23H2 [@devblogs-powershell-v2-deprecation]).&lt;/li&gt;
&lt;li&gt;Office Equation Editor (deprecated 2017, removed 2018 after CVE-2017-11882 [@nvd-cve-2017-11882]).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The 2002 template won. The modern industry runs on its descendants. But &quot;won&quot; does not mean &quot;solved&quot; -- the same eight-engineer SWI of 2000 has descendants in 2026 that still ship the same memory-safety bugs Cutler&apos;s NT kernel shipped in 1993. What changed? What did not?&lt;/p&gt;
&lt;h2&gt;10. State of the Art (and the Wars Ahead)&lt;/h2&gt;
&lt;p&gt;Open with the humility. Microsoft&apos;s own 2019 MSRC retrospective is the figure CISA preserves verbatim: &lt;strong&gt;&quot;approximately 70% of the vulnerabilities Microsoft assigns a CVE each year continue to be memory safety issues&quot;&lt;/strong&gt; [@cisa-urgent-need-memory-safety] [@cisa-memory-safe-roadmaps].&lt;/p&gt;
&lt;p&gt;Twenty-five years after the SDL&apos;s birth, the dominant CVE class is the same one the NT 3.1 -&amp;gt; NT 4.0 -&amp;gt; IIS 5.0 series shipped throughout the 1990s and Code Red weaponized in 2001.An earlier draft credited Cutler&apos;s NT-kernel team with shipping &lt;code&gt;idq.dll&lt;/code&gt; in 1993. That attribution is wrong on both counts. &lt;code&gt;idq.dll&lt;/code&gt; first shipped with &lt;strong&gt;Microsoft Index Server 1.0 for Windows NT 4.0 in 1996&lt;/strong&gt;, and it was authored by the Index Server / IIS-ISAPI team, not the Cutler-led NT-kernel team. The load-bearing claim -- that the dominant CVE class today is the same memory-safety class the NT-line products shipped throughout the 1990s and Code Red weaponized in 2001 -- is preserved without the inaccurate attribution. The discipline the era forced was necessary; it was not sufficient.&lt;/p&gt;
&lt;p&gt;Three frontiers carry that residual problem forward into the next decade.&lt;/p&gt;
&lt;h3&gt;Frontier 1: supply-chain integrity (SLSA v1.0 Build track levels)&lt;/h3&gt;
&lt;p&gt;SLSA -- Supply-chain Levels for Software Artifacts -- is the post-SolarWinds extension of the SDL pattern to the build pipeline itself. The v1.0 specification defines four Build track levels, with verbatim per-level guarantees [@slsa-v1-levels]:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Build L0.&lt;/strong&gt; No SLSA. No claims about provenance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build L1.&lt;/strong&gt; &quot;Provenance showing how the package was built.&quot; Crucially, the spec is explicit that at L1 &quot;provenance may be incomplete and/or unsigned&quot; -- L1 defends against mistakes and gives consumers something to inspect, not against tampering [@slsa-v1-levels].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build L2.&lt;/strong&gt; Signed provenance, &quot;generated by a hosted build platform.&quot; The signature belongs to the build platform, not the producer -- specifically, &quot;by a key that is only accessible to the build platform&quot; -- so post-build tampering by the producer is detectable [@slsa-v1-levels].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build L3.&lt;/strong&gt; Hardened build platform: builds run in isolation so one build cannot influence another, and the signing key is &quot;not accessible to user-defined build steps&quot; so an insider with a malicious build script cannot forge signed provenance [@slsa-v1-levels].&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A Source track existed in SLSA&apos;s v0.1 draft and was explicitly &lt;em&gt;deferred&lt;/em&gt; from v1.0. The future-directions page is direct about why: &quot;A Source track could provide protection against tampering of the source code prior to the build&quot; [@slsa-future-directions]. The reason it is not in v1.0: there is no automatic decision procedure that distinguishes a malicious-but-syntactically-clean patch from a benign one.&lt;/p&gt;
&lt;p&gt;The xz-utils CVE-2024-3094 attack is the canonical case. Andres Freund&apos;s March 29, 2024 oss-security disclosure described a multi-year campaign by an attacker using the handle &quot;Jia Tan&quot; who, over two and a half years (the first patch landed in October 2021), built a maintainer-grade reputation and pushed a backdoor into the xz release tarballs that diverged subtly from the git source [@freund-xz-disclosure]. Russ Cox&apos;s timeline reconstructs the social-engineering chain: the &quot;Jigar Kumar&quot; and &quot;Dennis Ens&quot; sockpuppet accounts pressuring the original maintainer to delegate authority, the gradual accretion of commit access, the backdoor delivered in the release artifacts but not the git history [@cox-xz-timeline].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; SLSA&apos;s Build track addresses the integrity of the path from source to artifact. It does not address the integrity of the source itself. A malicious patch that lands in the upstream repository and is built by an SLSA Build L3 platform produces a properly attested, properly signed artifact that is malicious. The xz-utils case is the existence proof. Detection here still depends on individual engineer-curiosity in the field -- Andres Freund noticed an anomalous CPU spike on his Debian sid SSH logins and chased it -- not on any mechanically verifiable property of the supply chain.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Frontier 2: AI/LLM-integrated software&lt;/h3&gt;
&lt;p&gt;The threat-modeling frameworks the SDL absorbed -- STRIDE, PASTA, LINDDUN -- were designed for systems whose components have specifications. An LLM is not such a component. Its behavior is an empirical artifact of its training data and the prompt context it receives; there is no spec a verifier can use to bound the set of outputs the model will produce for a given input.&lt;/p&gt;
&lt;p&gt;The partial responses on the table in 2026: the NIST AI Risk Management Framework (AI RMF 1.0), released January 26, 2023 [@nist-ai-rmf]; the OWASP Top 10 for Large Language Model Applications, now part of the OWASP GenAI Security Project [@owasp-llm-top-10]; and the draft &lt;strong&gt;NIST SP 800-218A IPD&lt;/strong&gt; (&quot;Secure Software Development Practices for Generative AI and Dual-Use Foundation Models&quot;), published April 29, 2024, by Souppaya, Vassilev, Ogata, Stanley, and Scarfone as an SSDF Community Profile mandated by Executive Order 14110 section 4.1(a)(ii) of October 30, 2023 [@nist-sp-800-218a-ipd] [@nist-sp-800-218a-ipd-pdf].&lt;/p&gt;
&lt;p&gt;To bring this frontier to the same mechanism-grade depth as Frontier 1, the worked example below traces a single named vulnerability class -- &lt;strong&gt;Indirect Prompt Injection (IPI)&lt;/strong&gt; -- from primary disclosure through vendor mitigation, productization, federal-supplier profile, and a real-world CVE.&lt;/p&gt;

A class of attack against LLM-integrated applications in which the attacker never interacts with the model directly. Instead, the attacker plants adversarial instructions into data the model will later retrieve -- a web page the model browses, a document the model summarizes, an email the model is asked about, a code-repository file the model is asked to refactor. When the LLM ingests that data, it treats the injected instructions as part of its prompt context and acts on them. The term was defined by Greshake, Abdelnabi, Mishra, Endres, Holz, and Fritz in their AISec 23 paper [@greshake-ipi-arxiv] [@greshake-ipi-acm].
&lt;p&gt;&lt;strong&gt;The vulnerability class.&lt;/strong&gt; The Greshake et al. paper (arXiv v1 February 23, 2023; AISec 23 proceedings November 30, 2023, Copenhagen) demonstrated working IPI attacks against Bing Chat (GPT-4 powered), GPT-4-integrated synthetic applications, and code-completion engines [@greshake-ipi-arxiv]. The paper&apos;s threat taxonomy enumerates four families: data theft, worming (LLM-to-LLM propagation through injected outputs that subsequent LLMs read), information-environment contamination, and arbitrary code execution at the application-functionality layer [@greshake-ipi-arxiv] [@greshake-ipi-acm].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The vendor mitigation -- Microsoft Spotlighting.&lt;/strong&gt; Hines, Lopez, Hall, Zarfati, Zunger, and Kiciman published &quot;Defending Against Indirect Prompt Injection Attacks With Spotlighting&quot; (arXiv v1 March 20, 2024) [@hines-spotlighting-arxiv]. Spotlighting is a family of prompt-engineering techniques -- datamarking, encoding, per-token-marker transformations -- that, in the paper&apos;s words, provide &quot;a reliable and continuous signal of provenance&quot; so the model can distinguish instructions from retrieved data. The empirical claim is verbatim: &lt;strong&gt;&quot;spotlighting reduces the attack success rate from greater than 50% to below 2% in our experiments with minimal impact on task efficacy&quot;&lt;/strong&gt; on GPT-family models [@hines-spotlighting-arxiv].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The productization -- Azure AI Content Safety Prompt Shields.&lt;/strong&gt; Spotlighting moved from a research paper to a productized API surface: Microsoft Learn documents Prompt Shields as &quot;a unified API in Azure AI Content Safety that detects and blocks adversarial user input attacks on large language models&quot; [@azure-prompt-shields]. The Microsoft Docs Zero Trust SFI guidance documents the layered defense-in-depth pattern Prompt Shields and Spotlighting compose into: &quot;Prompt shields ... Spotlighting ... Plan drift detection ... Critic agents ... Tool chain analysis ... Security guardrails&quot; [@msdocs-defend-ipi]. MSRC&apos;s July 2025 blog &quot;How Microsoft defends against indirect prompt injection attacks&quot; is the canonical Microsoft narrative [@msrc-ipi-blog].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The framework mapping -- OWASP LLM01.&lt;/strong&gt; The OWASP GenAI Security Project&apos;s LLM01 page enumerates seven prevention-and-mitigation strategies for prompt injection [@owasp-llm01-prompt-injection]. Spotlighting is the algorithmic implementation of Category 6 (&quot;Segregate and identify external content&quot;); system-prompt enforcement is Category 1 (&quot;Constrain model behavior&quot;); tool-call permission scoping is Category 4 (&quot;Enforce privilege control and least privilege access&quot;); human-in-the-loop checkpoints for high-risk tool calls (file write, email send, payment) are Category 5 (&quot;Require human approval for high-risk actions&quot;) [@owasp-llm01-prompt-injection].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The federal-supplier profile -- NIST SP 800-218A IPD.&lt;/strong&gt; The draft NIST SP 800-218A profile takes the OWASP and Microsoft Research mitigation vocabulary and translates it into SSDF practice-level language [@nist-sp-800-218a-ipd] [@nist-sp-800-218a-ipd-pdf]. The legal anchor is Executive Order 14110 section 4.1(a)(ii) of October 30, 2023; the initial public draft published April 29, 2024 with a comment deadline of June 2, 2024 [@nist-sp-800-218a-ipd].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The real-world CVE -- CVE-2024-5184 (EmailGPT).&lt;/strong&gt; The OWASP LLM01 page Scenario #5 references CVE-2024-5184 directly. The NVD record classifies it as CWE-74 (Improper Neutralization, Injection) with CVSS Base Score 6.5 Medium; the CNA is Synopsys (Black Duck) [@nvd-cve-2024-5184]. The Black Duck CyRC advisory reconstructs the disclosure timeline: initial contact February 26, 2024; reminders April 4 and May 1; public advisory June 5, 2024 -- about ninety-nine days with &lt;strong&gt;no vendor response&lt;/strong&gt; [@blackduck-cyrc-emailgpt]. Mohammed Alshehri at Black Duck CyRC discovered the vulnerability; the CyRC recommendation, verbatim, is to &lt;strong&gt;&quot;remove the applications from networks immediately&quot;&lt;/strong&gt; [@blackduck-cyrc-emailgpt]. That recommendation is the operational evidence that the field still lacks a reliable in-band mitigation it can ship without removing the application from production.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Four gaps deserve naming for readers reusing this material. First, &lt;strong&gt;no primary-source-grade threat-modeling method exists&lt;/strong&gt; for the prompt-context, training-data-supply-chain, or fine-tuning-data attack surfaces in the closed-list way STRIDE exists for component-with-spec systems; OWASP LLM01&apos;s seven categories are a useful checklist but not a generative methodology. Second, &lt;strong&gt;Spotlighting&apos;s empirical 50%-to-2% reduction is per-model, per-task, and adversary-specific&lt;/strong&gt; [@hines-spotlighting-arxiv] -- tested against specific GPT-family models with specific attack templates. Third, &lt;strong&gt;the CVE-2024-5184 disclosure timeline (Feb 26 to Jun 5, 2024, no vendor response)&lt;/strong&gt; [@blackduck-cyrc-emailgpt] demonstrates the field still lacks the institutional analog of MSRC&apos;s 2002-era coordinated-disclosure norms for LLM-integrated applications. Fourth, &lt;strong&gt;the 2002-style cohort migration is not yet available&lt;/strong&gt;: there is no equivalent of &quot;ship telemetry, publish guidance, flip the default, deprecate, remove&quot; for &quot;prompt-injection-vulnerable LLM agent integrations,&quot; because the legitimate-use long tail is the entire space of LLM-integrated applications, not a single deprecated protocol like SMBv1.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Mapping the article&apos;s thesis onto this frontier: Greshake et al. named the &lt;strong&gt;class&lt;/strong&gt; (February 2023) the way Saltzer and Schroeder named the &lt;strong&gt;principles&lt;/strong&gt; in 1975; Microsoft published the &lt;strong&gt;mitigation&lt;/strong&gt; (Spotlighting, March 2024) with a measurable effect; Microsoft &lt;strong&gt;productized&lt;/strong&gt; it (Azure Prompt Shields); NIST published the &lt;strong&gt;federal-supplier profile&lt;/strong&gt; (SP 800-218A IPD, April 2024); and a &lt;strong&gt;real-world CVE with no vendor response&lt;/strong&gt; demonstrates the cycle has not yet completed at industry scale. The 2002 pattern -- discipline, then authority, then mitigation, then productization, then federal-supplier mandate, then coordinated-disclosure norm -- is &lt;em&gt;in progress&lt;/em&gt; for the AI/LLM frontier, and the reader can see exactly which steps remain.&lt;/p&gt;
&lt;h3&gt;Frontier 3: the formal-verification gap&lt;/h3&gt;
&lt;p&gt;The proof-of-correctness path has narrowed the gap between SOTA shipped code and the theoretical upper bound, but not closed it.&lt;/p&gt;
&lt;p&gt;The canonical worked example is &lt;strong&gt;seL4&lt;/strong&gt;: a formally verified microkernel, Klein et al., SOSP 2009 [@klein-sel4-sosp-2009]. The seL4 FAQ lists per-architecture kernel sizes for the verified configurations: roughly 10,000 source-lines-of-code on RISC-V 64, 12,100 on AArch32, 12,600 on AArch64 with hypervisor extensions, and 16,000 on x64 [@sel4-faq]. The proof-to-code ratio is approximately &lt;strong&gt;20 to 1&lt;/strong&gt; -- twenty lines of Isabelle/HOL proof for every line of kernel C -- and the proof effort was approximately twenty person-years for the original 2009 verification [@klein-sel4-sosp-2009].&lt;/p&gt;
&lt;p&gt;Why has seL4-class verification not scaled from a microkernel to a desktop OS? The barrier is compositional: each new feature requires re-proving every relevant invariant compositionally. The cost grows non-linearly with feature surface; even with two and a half decades of tooling improvement, no verified OS at desktop-Linux or Windows scale exists in production.&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s parallel path -- the one running today, not over the next twenty years -- is the introduction of &lt;a href=&quot;https://paragmali.com/blog/rust-in-the-windows-kernel-a-field-guide-to-the-2024-2026-me/&quot; rel=&quot;noopener&quot;&gt;memory-safe Rust&lt;/a&gt; into selected Windows components. David Weston&apos;s BlueHat IL 2023 talk gave the two named exemplars: the Win32k GDI region engine (~36,000 lines of Rust) and DWriteCore (~152,000 lines of Rust) [@weston-bluehat-il-2023].&lt;/p&gt;
&lt;p&gt;Why does Rust help when seL4-style proof does not scale? Because Rust does not try to prove &quot;the program is correct.&quot; It enforces a weaker but mechanically checkable property at the type-system level: no aliased mutable borrows, no use-after-free. That weaker property closes most of the bug class behind the 70% memory-safety figure, by construction, at compile time -- without any per-program proof effort.&lt;/p&gt;
&lt;p&gt;That trade-off is the load-bearing engineering pattern of every secure-development framework since 2002. There is a name for it in the formal-methods literature, and a 1953 theorem behind it.&lt;/p&gt;

A mechanically checkable proxy property that closes the most common subset of an undecidable semantic property&apos;s bug class. Rice&apos;s theorem (Henry Rice, *Transactions of the AMS* 74, 1953) says any non-trivial semantic property of a Turing-recognizable program is undecidable -- you cannot, in general, write a checker that decides whether an arbitrary program has the property. The SDL&apos;s engineering workaround has always been to substitute a *decidable* property that catches the most common cases. `banned.h` substitutes &quot;is this textual symbol present?&quot; (trivially decidable, mechanically enforceable) for &quot;is this string copy memory-safe?&quot; (undecidable). C28719 is the descendant of that substitution that still release-gates Windows drivers in 2026 [@msft-c28719]. Rust&apos;s borrow-checker is the same trick at the language layer: it substitutes &quot;is every borrow either exclusive or shared?&quot; for &quot;is the program memory-safe?&quot;, closing a much larger class of bugs by construction.
&lt;p&gt;The unifying pattern across sections 7, 9, and 10:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Rice&apos;s theorem says the question we &lt;em&gt;want&lt;/em&gt; to answer is undecidable. The discipline that emerged from the 2002 Push said: substitute a question we &lt;em&gt;can&lt;/em&gt; answer, make the substitution good enough, and gate releases on the substituted question. Every generation since -- &lt;code&gt;banned.h&lt;/code&gt;, &lt;code&gt;strsafe.h&lt;/code&gt;, C28719, the Rust borrow-checker, SLSA Build attestations -- has substituted a better question.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The series this article opens has five more parts -- beginning with &lt;a href=&quot;https://paragmali.com/blog/eight-primitives-one-worm-the-windows-security-wars-part-2-2/&quot; rel=&quot;noopener&quot;&gt;Part 2 (2002-2008)&lt;/a&gt; -- each working a generation forward:&lt;/p&gt;

flowchart LR
    P1[Part 1: Wild West and TwC memo 1995-2002] --&amp;gt; P2[Part 2: XP SP2 DEP NX Windows Firewall WRP early ASLR Aug 2004]
    P2 --&amp;gt; P3[Part 3: Vista UAC MIC BitLocker PatchGuard driver signing Nov 2006]
    P3 --&amp;gt; P4[Part 4: Windows 7 to 10 AppContainer Credential Guard Device Guard 2009-2015]
    P4 --&amp;gt; P5[Part 5: Cloud era Azure AD Conditional Access Entra ID 2015-present]
    P5 --&amp;gt; P6[Part 6: Endpoint defenses HVCI VBS Pluton Rust in Windows 2018-2026]
&lt;p&gt;Mandatory Integrity Control (MIC) is a Windows Vista (2006) feature, not an NT-era latent design. Vista introduced integrity levels (Low, Medium, High, System) and the integrity-level-tagged DACLs that make MIC work; UAC builds on top. Part 3 of this series will work the mechanism in detail.&lt;/p&gt;
&lt;p&gt;For readers who want the mechanics rather than the history: this article is the institutional birth; the companion in-depth posts cover the primitives. The &lt;a href=&quot;https://paragmali.com/blog/windows-access-control-25-years-of-attacks/&quot; rel=&quot;noopener&quot;&gt;Windows access-control model&lt;/a&gt; post walks the SRM, DACLs, SACLs, and SIDs in operational detail; the &lt;a href=&quot;https://paragmali.com/blog/dpapi-and-dpapi-ng-the-credential-vault-under-everything/&quot; rel=&quot;noopener&quot;&gt;DPAPI&lt;/a&gt; post covers the user-key derivation pipeline; the &lt;a href=&quot;https://paragmali.com/blog/kerberos-in-windows-the-other-half-of-ntlmless/&quot; rel=&quot;noopener&quot;&gt;NT Kerberos&lt;/a&gt; post covers the LSA, the KDC, the TGT, and the ticket-granting flow; the &lt;a href=&quot;https://paragmali.com/blog/the-card-that-wasnt-a-card-how-windows-authentication-outgre/&quot; rel=&quot;noopener&quot;&gt;smart cards&lt;/a&gt; post covers the certificate-bound credential path.&lt;/p&gt;
&lt;p&gt;The story ends, but the wars do not. The institutional pattern the era forced is now twenty-five years old; the bug class that forced it is still ~70% of shipped CVEs. The next twenty-five years will repeat the operationalization pattern at progressively more abstract layers -- supply chain, machine-learning model, the developer&apos;s autonomous agent. The hard part has never been the technical question. The hard part is always the executive willingness to halt feature work to answer it.&lt;/p&gt;
&lt;h2&gt;11. Frequently Asked Questions&lt;/h2&gt;
&lt;p&gt;Every retelling of this era invites a predictable set of pushbacks. Address them head-on, so the article can end on wonder, not on quibble.&lt;/p&gt;


No, and the cost-and-mechanism evidence is the rebuttal. The Push was approximately ten weeks of paused feature work across ~8,500 Windows engineers at a total cost of ~$100 million in foregone feature work, and the methodology survived twenty-plus years as the published Microsoft SDL, ISO/IEC 27034, OWASP SAMM, BSIMM, NIST SSDF, SLSA, and CISA Secure by Design [@howard-lipner-push-2003] [@washtech-microsoft-100m] [@msft-sdl-practices] [@iso-27034-1] [@owasp-samm-model] [@bsimm-home] [@nist-ssdf-218] [@slsa-home] [@cisa-secure-by-design]. A PR move does not survive a fiscal-quarter reporting cycle, let alone two decades and a peer-reviewed primary-source accounting in IEEE *Security and Privacy* [@howard-lipner-push-2003].

Partly. OpenBSD&apos;s audit-driven engineering culture started in the summer of 1996, six years before the Windows Security Push; its &quot;six to twelve&quot; auditor team has been continuously active since [@openbsd-security]. The OpenBSD slogan -- &quot;only two remote holes in the default install, in a heck of a long time&quot; -- is real and earned [@openbsd-security]. The distinction is scale and incentive: OpenBSD&apos;s model worked for a small homogeneous codebase with self-selected auditors and a permissive-license, no-revenue context; the SDL&apos;s model was built for a fifty-thousand-person, hundred-million-line, quarterly-revenue context. Parallel paths, not competitors.

No -- the eEye back-reference in their own August 4, 2001 Code Red II advisory points at advisory `AL20010717.html`, that is, **July 17, 2001**, for the original Code Red I discovery [@eeye-codered-ii]. CAIDA&apos;s measurement of the saturating Code Red v2 outbreak covers the **July 19, 2001** event with ~359,000 unique IPs in under fourteen hours [@caida-codered]. The defensible phrasings are &quot;mid-July 2001&quot; or &quot;July 17, 2001&quot; for Code Red I, and &quot;July 19, 2001&quot; for Code Red v2.

No. ILOVEYOU was a **VBScript / Windows Script Host email worm**, executed by `wscript.exe` when the user double-clicked the `LOVE-LETTER-FOR-YOU.TXT.vbs` attachment in Outlook [@cert-ca-2000-04-iloveyou]. The &quot;Concept / Melissa / ILOVEYOU&quot; grouping in popular retellings conflates two distinct execution surfaces: Office macros (Concept, Melissa) and the Windows scripting host (ILOVEYOU). The classification matters because the fixes are different -- Office macro auto-execute is an Office configuration; WSH-by-default and the hidden double-extension display in Explorer were Windows shell decisions.

No. The January 15, 2002 memo halted *Windows-division* feature work for the February-April 2002 Push, at the ~8,500-engineer scale Howard and Lipner document [@howard-lipner-push-2003]. The Office division, the .NET division, and the SQL Server division ran analogous pushes *serially* through 2002-2003, not simultaneously. The company-wide aggregate figure of &quot;10,000 engineers&quot; rolls those serial pushes together; the Windows-only number from the primary record is ~8,500 [@howard-lipner-push-2003] [@washtech-microsoft-100m]. Visual Studio .NET launched on schedule on February 13, 2002, after the December 2001 pre-launch security review the Gates memo names as the **template** for what the rest of the company was about to do [@gates-memo-wired].

Loren Kohnfelder and Praerit Garg, internal Microsoft memo &quot;The Threats to Our Products,&quot; dated April 1, 1999 -- nearly three years before the Gates memo [@shostack-tm-book]. The memo is **no longer hosted on Microsoft&apos;s own web site**, but it has been publicly preserved at Adam Shostack&apos;s archive [@shostack-stride-memo-archive] (Shostack&apos;s landing page notes the document is no longer available on Microsoft&apos;s web site, &quot;so we keep a copy here&quot;), with an independent mirror at FIRST&apos;s CTI SIG curriculum [@first-stride-memo-mirror]. The chain-of-custody analysis is Shostack&apos;s *Threat Modeling: Designing for Security*, Wiley 2014 [@shostack-tm-book]. Microsoft&apos;s current Threat Modeling Tool is the operational descendant [@msft-threat-modeling-tool]. STRIDE&apos;s existence is the strongest single piece of evidence that the article&apos;s literal thesis (&quot;Microsoft had no security team before January 15, 2002&quot;) needs the corrected reading in section 5 -- the methodology was *internal* by 1999; what was missing was the authority to require its use.

No, and the article explicitly disclaims this reading. The underlying ideas -- Saltzer and Schroeder 1975, the Orange Book 1985, CERT/CC 1988, OpenBSD 1996, Schneier&apos;s Attack Trees December 1999, Kohnfelder and Garg&apos;s STRIDE April 1999, Howard and LeBlanc&apos;s *Writing Secure Code* November 2001 -- all predate it [@saltzer-schroeder-1975] [@tcsec-orange-book] [@openbsd-security] [@schneier-attack-trees-1999] [@shostack-tm-book] [@howard-leblanc-wsc]. What January 15, 2002 was, is the moment a fifty-thousand-person desktop-monopoly vendor first applied release-blocking executive authority to make secure development a non-negotiable engineering gate. The corrected reading -- **industrial-scale operationalization at a dominant vendor**, not the *invention* of the field -- is the only one the evidence supports.

For readers who finish the article wanting to verify or extend the claims directly, the five most-useful primary sources cited throughout, by section:&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Section 6 (the memo).&lt;/strong&gt; Bill Gates, &quot;Trustworthy computing&quot; memo to &quot;Microsoft and Subsidiaries: All FTE,&quot; sent Tuesday, January 15, 2002 5:22 PM Pacific. Wired&apos;s republication preserves the original mail headers verbatim [@gates-memo-wired]; the Help With Windows mirror preserves the same &lt;code&gt;From:&lt;/code&gt; / &lt;code&gt;Sent:&lt;/code&gt; / &lt;code&gt;To:&lt;/code&gt; / &lt;code&gt;Subject:&lt;/code&gt; block [@helpwithwindows-billg].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Section 7 (the Push).&lt;/strong&gt; Michael Howard and Steve Lipner, &quot;Inside the Windows Security Push,&quot; IEEE &lt;em&gt;Security and Privacy&lt;/em&gt; 1(1):57-61, January-February 2003 [@howard-lipner-push-2003]. The primary-source paper for the approximately 8,500-engineer, approximately ten-week, approximately one-hundred-million-dollar, approximately 50% post-release-vulnerability-reduction numbers. DOI of record: &lt;code&gt;10.1109/MSECP.2003.1176996&lt;/code&gt;; IEEE Xplore is paywalled.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Section 4 (Code Red).&lt;/strong&gt; David Moore, Colleen Shannon, Jeffery Brown, &quot;Code-Red: a case study on the spread and victims of an Internet worm,&quot; CAIDA 2002 [@caida-codered]. The 359,000-host measurement.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Section 4 (Slammer).&lt;/strong&gt; David Moore, Vern Paxson, Stefan Savage, Colleen Shannon, Stuart Staniford, Nicholas Weaver, &quot;The Spread of the Sapphire/Slammer Worm,&quot; CAIDA / ICSI / Silicon Defense / UCSD / UC Berkeley 2003 [@caida-slammer]. The 8.5-second-doubling, ten-minute-saturation, approximately 75,000-host primary.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Section 10 (formal verification).&lt;/strong&gt; Gerwin Klein, Kevin Elphinstone, Gernot Heiser, et al., &quot;seL4: Formal Verification of an OS Kernel,&quot; SOSP 2009 [@klein-sel4-sosp-2009]. The formal-verification anchor; project FAQ at [@sel4-faq].&lt;/li&gt;&lt;/ul&gt;


&lt;p&gt;One sentence to carry forward, restating the article&apos;s load-bearing observation in plain English: the breakthrough was organizational, not technical. Same checklists, different signoff power. That pattern -- &quot;make existing methods mandatory, and gate releases on them&quot; -- is what every secure-development framework on the industry shelf in 2026 has, in its own vocabulary, copied. The next twenty-five years will copy it at the supply-chain layer, the machine-learning-model layer, and the autonomous-agent layer; the pattern is what travels.&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;windows-security-wars-part-1-trustworthy-computing&quot; keyTerms={[
  { term: &quot;Security Reference Monitor (SRM)&quot;, definition: &quot;The kernel component of Windows NT that performs the access check on a securable object.&quot; },
  { term: &quot;DACL&quot;, definition: &quot;Discretionary Access Control List: ordered ACEs granting or denying access rights to principals.&quot; },
  { term: &quot;SACL&quot;, definition: &quot;System Access Control List: the audit list, telling the kernel which access attempts to log.&quot; },
  { term: &quot;SID&quot;, definition: &quot;Security Identifier: a variable-length binary identifier naming a Windows principal.&quot; },
  { term: &quot;Macro virus&quot;, definition: &quot;A program that infects documents by hijacking the host application&apos;s embedded scripting language and auto-execute hooks.&quot; },
  { term: &quot;VBScript / Windows Script Host (WSH)&quot;, definition: &quot;Microsoft&apos;s general-purpose scripting language and the Windows executable host (wscript.exe / cscript.exe) that runs it.&quot; },
  { term: &quot;Monoculture&quot;, definition: &quot;A large population of independently administered hosts running identical software with identical defaults; a single vulnerability is exploitable across the entire population.&quot; },
  { term: &quot;banned.h&quot;, definition: &quot;Microsoft&apos;s header that re-declares unsafe C runtime functions as compile-time errors; surviving descendant in 2026 is the C28719 static-analysis warning.&quot; },
  { term: &quot;strsafe.h&quot;, definition: &quot;Microsoft&apos;s safer-by-default replacement string-handling API set with explicit destination-buffer sizes and HRESULT returns.&quot; },
  { term: &quot;Final Security Review (FSR)&quot;, definition: &quot;The release-blocking sign-off step at the end of the SDL pipeline; converts every preceding &apos;should&apos; into a hard &apos;must.&apos;&quot; },
  { term: &quot;Security Development Lifecycle (SDL)&quot;, definition: &quot;A software-engineering process model that integrates security activities into every phase of a product release.&quot; },
  { term: &quot;Decidable surrogate&quot;, definition: &quot;A mechanically checkable proxy property that closes the most common subset of an undecidable semantic property&apos;s bug class.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>windows-security</category><category>security-history</category><category>sdl</category><category>trustworthy-computing</category><category>code-red</category><category>threat-modeling</category><category>malware-history</category><category>microsoft</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>Edge&apos;s Two Password Cryptographies: A Beautiful PSI on the Wire, and Plaintext RAM by Design</title><link>https://paragmali.com/blog/edge-two-password-cryptographies/</link><guid isPermaLink="true">https://paragmali.com/blog/edge-two-password-cryptographies/</guid><description>Microsoft Edge ships a homomorphic-encryption PSI for breach checking and decrypts every saved password into process RAM at launch. Both designs are deliberate. They defend different threat models.</description><pubDate>Mon, 11 May 2026 00:00:00 GMT</pubDate><content:encoded>
Microsoft Edge ships two cryptographic designs for &quot;passwords&quot; inside the same `msedge.exe` binary, owned by the same product team, with radically different threat models. The first -- Password Monitor -- is a deployed Private Set Intersection protocol built on Microsoft SEAL, the first production consumer homomorphic-encryption deployment in a browser, and is state-of-the-art cryptography for defending against a compromised breach-corpus server. The second -- Edge&apos;s local credential storage -- decrypts every saved password into process memory at browser launch and keeps it there for the lifetime of the session, a design Tom Joran Sonstebyseter Ronning&apos;s `EdgeSavedPasswordsDumper` (May 4, 2026) made legible and that Microsoft classified as &quot;by design.&quot; These are not incompatible designs. They are precise statements about which threat models the Edge product team is and is not defending against, and treating them as one unified &quot;password security&quot; story masks where the actual compromise happens in 2026.
&lt;h2&gt;1. Two cryptographies, one product, one week&lt;/h2&gt;
&lt;p&gt;On &lt;strong&gt;January 21, 2021&lt;/strong&gt;, Microsoft Research&apos;s Cryptography and Privacy group announced Edge&apos;s Password Monitor ships a homomorphic-encryption-based Private Set Intersection protocol built on Microsoft SEAL. The post is explicit that this is &quot;possible due to pioneering cryptography research and technology incubation done here at Microsoft Research,&quot; that it is the result of a collaboration &quot;between [the] Cryptography and Privacy Research Group, and Edge product team,&quot; and that the protocol descends from two specific papers: &quot;Fast Private Set Intersection from Homomorphic Encryption&quot; and &quot;Labeled PSI from Fully Homomorphic Encryption with Malicious Security&quot; [@msr-password-monitor-2021]. It is, by a comfortable margin, the first production consumer deployment of homomorphic encryption in a browser.&lt;/p&gt;
&lt;p&gt;On &lt;strong&gt;May 4, 2026, at 14:29:51 UTC&lt;/strong&gt;, a researcher in Oslo named Tom Joran Sonstebyseter Ronning posted to X: &quot;Microsoft Edge loads all your saved passwords into memory in cleartext -- even when you&apos;re not using them&quot; [@ronning-x]. He linked a GitHub repository called &lt;code&gt;EdgeSavedPasswordsDumper&lt;/code&gt;: roughly 230 lines of C# that opens a handle to the parent &lt;code&gt;msedge.exe&lt;/code&gt; process and reads every saved credential as plaintext, with no kernel exploit, no admin (against same-user processes), and no &lt;a href=&quot;https://paragmali.com/blog/dpapi-and-dpapi-ng-the-credential-vault-under-everything/&quot; rel=&quot;noopener&quot;&gt;DPAPI&lt;/a&gt; bypass [@ronning-github]. The README confirms the behaviour is present in &quot;any Edge versions that&apos;s Chromium based (from version 79 and newer, including 147.0.3912.98 and any future version)&quot; [@ronning-github]. Two days later, on &lt;strong&gt;May 6, 2026&lt;/strong&gt;, Microsoft told Forbes that the in-memory behaviour is &quot;an expected feature of the application&quot; and &quot;by design&quot; [@forbes-winder].&lt;/p&gt;
&lt;p&gt;Both designs ship in the same binary. Both are owned by the same product team. Both can be defended on technical grounds. And both stories get told about the same word: &quot;passwords.&quot;&lt;/p&gt;
&lt;p&gt;This article argues they are about two different threat models, and the apparent contradiction in the headline disappears once you separate them.&lt;/p&gt;

A two-party cryptographic protocol in which Alice holds a set $S_A$, Bob holds a set $S_B$, and they jointly compute $S_A \cap S_B$ such that each party learns the intersection (or, in some variants, only one party does) and nothing else about the other party&apos;s set beyond what the intersection implies.
&lt;p&gt;The PSI story is genuinely beautiful. It begins in 1986 with a paper hardly anyone reads, climbs through a 35-year cryptographic engineering effort to make oblivious transfer cheap enough to be free, lands in 2017 on a homomorphic-encryption breakthrough whose cost curve fits the breach-checking problem exactly, and ships on consumers&apos; desktops by 2021 [@msr-password-monitor-2021]. The endpoint-storage story is genuinely awkward. Edge unwraps every DPAPI-encrypted saved credential into process memory when the password feature first activates, keeps the plaintext resident for the lifetime of the session, and accepts that any same-user process can read it back out [@ronning-github]. Microsoft&apos;s official position is that local code execution on the user&apos;s machine is &quot;outside the threat model&quot; of the browser password store -- a position that is internally consistent with a decade of MSRC policy and also true [@forbes-winder].&lt;/p&gt;
&lt;p&gt;The thesis: &lt;strong&gt;&quot;password security&quot; is at least two threat models&lt;/strong&gt;, and Microsoft has chosen to deploy genuinely state-of-the-art cryptography against one of them while explicitly conceding the other. Treating both as one unified story is how product narratives obscure where the actual compromise happens in 2026.&lt;/p&gt;

timeline
    title PSI and browser credential storage, 1986 to 2026
    1986 : Meadows PSI
         : NRL matchmaking
    1999 : Huberman-Franklin-Hogg
         : DH meet-in-the-middle
    2003 : IKNP03 OT extension
    2004 : FNP04 polynomial PSI
    2015 : KOS15 active security
    2016 : KKRT16 OPRF-PSI
    2017 : CLR17 HE-PSI
         : Signal SGX contact discovery
    2018 : CHLR18 Labeled PSI
         : HIBP v2 k-anonymity
    2019 : Google Password Checkup
         : Silent OT
    2021 : Edge Password Monitor ships
         : Cong et al. CCS 2021
    2024 : Chrome App-Bound Encryption
    2026 : Ronning EdgeSavedPasswordsDumper
         : Microsoft &quot;by design&quot;
&lt;p&gt;To see why the two designs are not a contradiction, we need to understand how PSI got to be deployable at all -- a story that begins thirty-five years before Edge Password Monitor existed.&lt;/p&gt;
&lt;h2&gt;2. Why Private Set Intersection exists at all&lt;/h2&gt;
&lt;p&gt;Imagine two parties, neither of whom trusts the other. Alice has a set of identifiers; Bob has a set of identifiers. They want to learn which identifiers they share -- and only that. Each party wants to learn nothing about elements not in the intersection.&lt;/p&gt;
&lt;p&gt;This is not an obvious problem to need a protocol for. If Alice and Bob trusted a third party, they would hand over their sets. If they trusted each other, they would compare directly. The problem only becomes interesting when neither assumption holds. The 2026 canonical version looks like this: &lt;em&gt;Microsoft holds a curated set of roughly five billion breached credentials, and the user holds a few hundred passwords saved in their browser. The user wants to know which of their passwords appear in Microsoft&apos;s breach corpus -- and they want Microsoft to learn nothing about the passwords that do not.&lt;/em&gt; (Throughout this article the &quot;five billion&quot; figure is the author&apos;s 2026 forward projection of Microsoft&apos;s compromised-credential corpus; the contemporaneous Microsoft Research figure used in the 2021 Password Monitor announcement is four billion [@msr-password-monitor-2021], and the §3 sidenote spells out the inference.)&lt;/p&gt;
&lt;p&gt;That framing did not exist in 1986. The original motivation was much weirder.&lt;/p&gt;
&lt;h3&gt;The 1986 paper&lt;/h3&gt;
&lt;p&gt;Catherine Meadows, then at the U.S. Naval Research Laboratory, published &quot;A More Efficient Cryptographic Matchmaking Protocol for Use in the Absence of a Continuously Available Third Party&quot; at the 1986 IEEE Symposium on Security and Privacy [@meadows-1986][@ieee-6234864]. The titular &quot;matchmaking&quot; problem was prosaic. Two parties want to learn whether they share an interest in some sensitive list -- classified-mailing-list membership, intelligence-source overlap, the everyday work of compartmented information systems -- without revealing anything else.&lt;/p&gt;
&lt;p&gt;Meadows&apos;s protocol uses commutative encryption. Alice and Bob both raise the elements of their sets to private exponents over a Diffie-Hellman group. After two rounds, both parties hold the doubly-blinded versions of both sets. Equal underlying elements produce equal doubly-blinded values, because exponentiation in an Abelian group commutes. Unequal elements look like uniform-random group elements to both sides. The intersection comes out; the rest does not.&lt;/p&gt;
&lt;p&gt;Meadows wrote this ten years before Diffie-Hellman key exchange shipped in SSL 3.0 (November 1996), the protocol family TLS would standardise in 1999 [@wikipedia-tls], and thirty-five years before her protocol&apos;s intellectual descendants would ship in a consumer browser.&lt;/p&gt;
&lt;h3&gt;The 1999 revival&lt;/h3&gt;
&lt;p&gt;The same protocol shape was rediscovered and given its modern formulation by Bernardo Huberman, Matthew Franklin, and Tad Hogg at Xerox PARC in 1999. Their paper &quot;Enhancing Privacy and Trust in Electronic Communities&quot; was published at the First ACM Conference on Electronic Commerce [@hfh-1999]. The motivations were online-community problems that look quaint today: which of your friends are on this matchmaking site, do we share interests on a sensitive bulletin board, can two early-internet communities establish trust without leaking their member lists. The protocol they wrote down -- usually called &quot;DH meet-in-the-middle&quot; or just &quot;the Huberman-Franklin-Hogg protocol&quot; -- is the canonical PSI shape every security engineer still reaches for first.The dblp BibTeX record gives the canonical DOI as 10.1145/336992.337012, which the ACM Digital Library 403s to most non-browser User-Agents. The dblp HTML mirror returns 200 and confirms the citation [@dblp-hfh].&lt;/p&gt;
&lt;h3&gt;What had to exist before&lt;/h3&gt;
&lt;p&gt;PSI predates breach checking by twenty years. The cryptographers who built PSI did not know they were building Edge Password Monitor. They were building a protocol primitive that happened, much later, to map cleanly onto a problem the world did not yet have.&lt;/p&gt;
&lt;p&gt;The first such mapping landed in 2018 with HIBP&apos;s k-anonymity API and the cluster of academic and industry PSI deployments that followed [@hunt-pwned-v2-2018]. The primitive predated the killer application by two and a half decades. This is the normal shape of cryptographic engineering: the primitive sits on the shelf until the world needs it.&lt;/p&gt;
&lt;p&gt;The DH meet-in-the-middle protocol is elegant. It is also catastrophically wrong for the breach-checking use case. To see why, we have to count exponentiations.&lt;/p&gt;
&lt;h2&gt;3. Early approaches: DH meet-in-the-middle and FNP04&lt;/h2&gt;
&lt;p&gt;Let us walk the DH meet-in-the-middle protocol step by step. Alice holds a set $S_A$. Bob holds a set $S_B$. Both parties agree on a Diffie-Hellman group $G$ of prime order $q$ with generator $g$, and on a cryptographic hash function $H: {0,1}^* \to G$ that maps set elements into the group. Alice picks a private exponent $a \in \mathbb{Z}_q$; Bob picks $b$.&lt;/p&gt;
&lt;p&gt;The protocol proceeds in two rounds:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Alice computes ${H(x)^a : x \in S_A}$, shuffles, and sends to Bob.&lt;/li&gt;
&lt;li&gt;Bob computes ${H(y)^b : y \in S_B}$, shuffles, and sends to Alice.&lt;/li&gt;
&lt;li&gt;Alice exponentiates every value Bob sent her by $a$, producing ${H(y)^{ab} : y \in S_B}$. She sends this set back to Bob &lt;em&gt;in the order Bob originally sent his&lt;/em&gt; ${H(y)^b}$, so Bob can index by his own set.&lt;/li&gt;
&lt;li&gt;Bob exponentiates Alice&apos;s first-round values by $b$, producing ${H(x)^{ab} : x \in S_A}$. (In the symmetric variant Bob also sends his doubly-blinded set back to Alice; either side can then perform the match.)&lt;/li&gt;
&lt;li&gt;Both parties now hold the same doubly-blinded set for both sides. Equal underlying elements collide; unequal ones do not. They intersect locally.&lt;/li&gt;
&lt;/ol&gt;

sequenceDiagram
    participant A as Alice (set S_A)
    participant B as Bob (set S_B)
    Note over A,B: shared group G, hash H, private exponents a (Alice), b (Bob)
    A-&amp;gt;&amp;gt;B: shuffled set of H(x)^a for x in S_A
    B-&amp;gt;&amp;gt;A: shuffled set of H(y)^b for y in S_B
    A-&amp;gt;&amp;gt;A: compute H(y)^(ba) for each item from Bob
    B-&amp;gt;&amp;gt;B: compute H(x)^(ab) for each item from Alice
    Note over A,B: equal underlying elements yield equal doubly-blinded values
    A-&amp;gt;&amp;gt;B: ordered set of H(y)^(ab) for matching
    Note over A,B: intersection computed locally
&lt;p&gt;Why this is right. Under the Decisional Diffie-Hellman (DDH) assumption in $G$, the doubly-blinded values $H(x)^{ab}$ for $x \notin S_A \cap S_B$ look uniformly random to the other side. Equal underlying elements collide; unequal underlying elements do not. The reader can verify this for themselves in the demonstration below, which is the canonical pedagogical version of the protocol.&lt;/p&gt;
&lt;p&gt;{&lt;code&gt;// Toy PSI -- pedagogical only, NOT secure (small modulus, weak hash). const p = 2n ** 61n - 1n;      // Mersenne prime, small for demo const g = 37n;                  // generator over Z_p* (toy) const H = s =&amp;gt; {   // toy hash: deterministic map string -&amp;gt; [1, p-1]   let h = 1469598103934665603n;   for (const c of s) h = ((h ^ BigInt(c.charCodeAt(0))) * 1099511628211n) % p;   return h === 0n ? 1n : h; }; const expMod = (base, exp, mod) =&amp;gt; {   let r = 1n, b = base % mod, e = exp;   while (e &amp;gt; 0n) {     if (e &amp;amp; 1n) r = (r * b) % mod;     b = (b * b) % mod;     e &amp;gt;&amp;gt;= 1n;   }   return r; }; const S_A = [&quot;alice-at-example.com&quot;, &quot;bob-at-example.com&quot;, &quot;carol-at-example.com&quot;]; const S_B = [&quot;dave-at-example.com&quot;, &quot;bob-at-example.com&quot;, &quot;carol-at-example.com&quot;]; const a = 0xC0FFEEn, b = 0xBADCAFEn; const A1 = S_A.map(x =&amp;gt; expMod(H(x), a, p));   // Alice -&amp;gt; Bob const B1 = S_B.map(y =&amp;gt; expMod(H(y), b, p));   // Bob -&amp;gt; Alice const A2 = A1.map(v =&amp;gt; expMod(v, b, p));       // Bob blinds Alice&apos;s set const B2 = B1.map(v =&amp;gt; expMod(v, a, p));       // Alice blinds Bob&apos;s set // Reveal intersection by matching doubly-blinded values const setA2 = new Set(A2.map(String)); const intersection = S_B.filter((_, i) =&amp;gt; setA2.has(String(B2[i]))); console.log(&quot;Intersection:&quot;, intersection);&lt;/code&gt;}&lt;/p&gt;
&lt;p&gt;The protocol does work. It gives semi-honest security under DDH and costs $O(|S_A| + |S_B|)$ group exponentiations per side, plus the same again to blind the received set. In a balanced setting -- two sets of similar size, perhaps a few thousand elements each -- it is genuinely deployable.&lt;/p&gt;
&lt;h3&gt;The three things that go wrong at scale&lt;/h3&gt;
&lt;p&gt;For breach checking, the protocol breaks in three documented ways.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Set-cardinality leakage.&lt;/strong&gt; The shuffled lists Alice and Bob send each other have lengths $|S_A|$ and $|S_B|$. Bob learns precisely how many passwords Alice has saved; Alice learns precisely how big Bob&apos;s breach corpus is. The first leak is small but real; the second is fine when the server publishes its corpus size anyway (HIBP does), but the protocol does not hide it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Online-cost asymmetry.&lt;/strong&gt; The server pays $O(|S_B|)$ exponentiations per client query. At the five-billion-element scale of Microsoft&apos;s compromised-credential corpus, no realistic group exponentiation cost makes this feasible per query: even at 100 microseconds per exponentiation (optimistic for $|q| = 256$), five billion exponentiations is more than five days of single-core CPU. Sharding helps. Caching helps. Pre-computation helps. None makes the asymptotic curve workable as the corpus grows.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;No labeled variant.&lt;/strong&gt; The protocol returns set membership, not associated metadata. Edge Password Monitor wants to tell you &quot;this credential appeared in breach X&quot; -- so the protocol has to support associating a server-side label with each set element and returning the label for matched elements. DH meet-in-the-middle does not, without unpleasant extensions.&lt;/p&gt;
&lt;h3&gt;FNP04: the right idea, wrong substrate&lt;/h3&gt;
&lt;p&gt;The algebraic alternative arrived in 2004 with Freedman, Nissim, and Pinkas&apos;s &quot;Efficient Private Matching and Set Intersection&quot; at EUROCRYPT [@fnp-2004]. The idea is gorgeous. Alice encodes her set $S_A = {x_1, \dots, x_n}$ as the polynomial whose roots are her set:&lt;/p&gt;
&lt;p&gt;$$p(z) = \prod_{i=1}^{n} (z - x_i)$$&lt;/p&gt;
&lt;p&gt;Alice encrypts each coefficient of $p$ under an additively-homomorphic encryption scheme (Paillier, in the paper). She sends the encrypted coefficients to Bob. Bob homomorphically evaluates $p(y)$ for every element $y$ of his set $S_B$ and returns the encrypted results. If $y \in S_A$, then $p(y) = 0$, and after decryption Alice sees a zero in the corresponding position. If $y \notin S_A$, then $p(y)$ is a non-trivial polynomial evaluation that, randomized correctly, decrypts to a uniform value Alice cannot interpret.&lt;/p&gt;
&lt;p&gt;This is the first asymmetric PSI -- the first protocol where one party can do most of the work while the other sends only a small encrypted query. It is also, in deployment terms, structurally infeasible at scale. Paillier ciphertexts live in $\mathbb{Z}^*_{n^2}$ and are $2 \cdot |n|$ bits each [@paillier-1999] (2048 bits for FNP04&apos;s $|n| = 1024$ default; 4096 bits for the $|n| \geq 2048$ that modern security demands). Paillier homomorphic evaluation needs full-size modular exponentiation per coefficient, and the server compute scales as $O(|S_A| \cdot |S_B|)$. At Edge Password Monitor&apos;s target scale -- a client set of a few hundred passwords against a five-billion-element server corpus -- a single query would take minutes to hours of server compute and tens of megabytes of round-trip data per query.The 5-billion-element estimate is INFERRED, not measured (see §2 for the article-wide projection disclosure). No published source benchmarks FNP04 at that scale; the inference combines the $O(|S_A| \cdot |S_B|)$ asymptotic with measured Paillier throughput on commodity hardware. The order-of-magnitude conclusion is sound; treat the precise number as a back-of-envelope.The polynomial-roots idea is not dead. Thirteen years later, Chen, Laine, and Rindal will revive exactly this construction inside CLR17 [@clr-2017], with Paillier replaced by BFV-style somewhat-homomorphic encryption and a partition-and-evaluate trick that fixes the $O(|S_A| \cdot |S_B|)$ blow-up. The structure survives; the substrate gets swapped.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Protocol&lt;/th&gt;
&lt;th&gt;Era&lt;/th&gt;
&lt;th&gt;Server cost&lt;/th&gt;
&lt;th&gt;Communication&lt;/th&gt;
&lt;th&gt;Verdict at 5B-element scale&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;DH meet-in-the-middle [@hfh-1999]&lt;/td&gt;
&lt;td&gt;1999&lt;/td&gt;
&lt;td&gt;$O(&lt;/td&gt;
&lt;td&gt;S_B&lt;/td&gt;
&lt;td&gt;)$ DH exponentiations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FNP04 [@fnp-2004]&lt;/td&gt;
&lt;td&gt;2004&lt;/td&gt;
&lt;td&gt;$O(&lt;/td&gt;
&lt;td&gt;S_A&lt;/td&gt;
&lt;td&gt;\cdot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(preview) HE-PSI on BFV [@clr-2017]&lt;/td&gt;
&lt;td&gt;2017&lt;/td&gt;
&lt;td&gt;$O(&lt;/td&gt;
&lt;td&gt;S_B&lt;/td&gt;
&lt;td&gt;\log&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The naive approach -- &quot;just hash and compare&quot; -- leaks set cardinality at a minimum, and plain hashing is brute-forceable against any password the server can guess. Doing PSI properly under encryption requires either $O(|S_A| \cdot |S_B|)$ server work and 2048-bit Paillier ciphertexts (FNP04, dead at billions), or a new primitive: oblivious transfer at scale. It takes a decade of engineering to make that primitive free.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;FNP04&apos;s polynomial idea will turn out to be the right idea -- but only after we replace Paillier with somewhat-homomorphic encryption thirteen years later. Before we can get there, we need a different breakthrough: making the underlying oblivious-transfer primitive cheap enough that &lt;em&gt;every&lt;/em&gt; PSI in the literature can ride on it.&lt;/p&gt;
&lt;h2&gt;4. The evolution: oblivious transfer extension&lt;/h2&gt;
&lt;p&gt;Here is the central fact that drove a decade of cryptographic engineering: &lt;strong&gt;every PSI protocol that scales eventually reduces to &quot;many oblivious transfers.&quot;&lt;/strong&gt; OT is the universal building block. Once you can do millions of OTs per second, you can do nearly any two-party secure computation, including PSI. The question is how cheap &quot;many OTs&quot; can become.&lt;/p&gt;

A two-party primitive. In 1-out-of-2 OT, the sender holds two messages $(m_0, m_1)$, the receiver chooses a bit $b$, and after the protocol runs the receiver learns $m_b$ while the sender learns nothing about $b$. OT is universal -- it suffices for secure two-party computation of any function -- and it is also expensive: implemented directly from public-key primitives, each OT costs at least one Diffie-Hellman exponentiation, on the order of a millisecond per OT on commodity hardware.

A two-phase protocol that performs $m$ OTs at the cost of $\kappa$ &quot;base&quot; OTs (typically $\kappa = 128$, implemented with public-key crypto) plus $O(m)$ symmetric primitive calls. Because $\kappa$ is small and constant, the per-OT cost drops from public-key cost (~1 ms) to symmetric-crypto cost (~100 ns) -- roughly three orders of magnitude, and the asymptotic gap widens with $m$.
&lt;h3&gt;Generation 1: IKNP03&lt;/h3&gt;
&lt;p&gt;In 2003, Yuval Ishai, Joe Kilian, Kobbi Nissim, and Erez Petrank published &quot;Extending Oblivious Transfers Efficiently&quot; at CRYPTO 2003 [@iknp-2003].&lt;/p&gt;
&lt;p&gt;Ishai and Petrank are at Technion; Kilian and Nissim were at NEC Labs America at the time. The construction is short enough to summarize in one paragraph and important enough to be called &lt;em&gt;the&lt;/em&gt; OT extension: start with $\kappa$ &quot;base&quot; OTs done the expensive way (one public-key operation each), then use them to seed pseudorandom generators and a clever transposition trick that, with $O(m)$ hash-function calls, produces $m$ effective OTs. The base cost stays fixed at $\kappa$ public-key operations; the per-OT marginal cost collapses to a few hash invocations.&lt;/p&gt;
&lt;p&gt;The numerical impact: before IKNP, secure-computation researchers cited oblivious-transfer cost in milliseconds; after IKNP, in hundreds of nanoseconds. Three orders of magnitude is the difference between &quot;research artifact&quot; and &quot;this protocol can ship.&quot;No IACR ePrint preprint existed at publication time; a post-conference upload appeared in 2008 as ePrint 2008/508. ePrint 2003/052 is a different paper (Klima, Pokorny, Rosa). The Springer LNCS chapter [@iknp-2003] is the canonical reference.&lt;/p&gt;
&lt;h3&gt;Generation 2: KOS15&lt;/h3&gt;
&lt;p&gt;IKNP03 is secure against a &lt;em&gt;semi-honest&lt;/em&gt; adversary -- one who follows the protocol but tries to learn extra information from the transcript. Real-world deployments often need &lt;em&gt;active&lt;/em&gt; security: protection against an adversary who deviates to extract information or bias the output.&lt;/p&gt;
&lt;p&gt;In 2015, Marcel Keller, Emmanuela Orsini, and Peter Scholl published &quot;Actively Secure OT Extension with Optimal Overhead&quot; [@kos-2015]. The construction adds a correlation-check phase on top of IKNP03 that catches active deviations with overwhelming probability. The paper&apos;s own abstract: &quot;no more than 5% more time than the passively secure IKNP extension, in both LAN and WAN environments, and thus is essentially optimal with respect to the passive protocol.&quot; Modern implementations (libOTe, EMP-toolkit, MP-SPDZ) report on the order of 10-20% wall-clock overhead and 5-10% communication overhead over semi-honest IKNP03 in production -- the &quot;optimal overhead&quot; in the title is the claim that this margin vanishes as the OT count grows.&lt;/p&gt;
&lt;p&gt;After KOS15, &quot;active security is free&quot; became the industry default. Every modern OT-extension library -- libOTe, EMP-toolkit, MP-SPDZ -- ships KOS15 (or a close variant) as the production-grade default. The earlier semi-honest-only choice is a research artifact.&lt;/p&gt;
&lt;h3&gt;Generation 3: Silent OT&lt;/h3&gt;
&lt;p&gt;In 2019, a six-author collaboration -- Elette Boyle, Geoffroy Couteau, Niv Gilboa, Yuval Ishai, Lisa Kohl, and Peter Scholl -- published &quot;Efficient Pseudorandom Correlation Generators: Silent OT Extension and More&quot; at CRYPTO 2019 [@silent-ot-2019]. The construction replaces the communication-heavy IKNP/KOS phase with a &lt;em&gt;Pseudorandom Correlation Generator&lt;/em&gt; (PCG): the two parties exchange a few-kilobyte seed and locally expand it into millions of correlated OTs.&lt;/p&gt;

A protocol primitive that, given a short shared seed, lets two parties locally expand the seed into long correlated random strings -- in the OT case, the random correlations needed to &quot;consume&quot; each OT call. Once the seed is exchanged, no further communication is needed to produce more OTs; the parties simply expand more locally. PCGs reduce the per-OT wire cost to zero in the post-seed phase.
&lt;p&gt;The numerical impact this time is &lt;em&gt;bandwidth&lt;/em&gt;. Pre-Silent-OT, OT-extension protocols sent on the order of $\kappa$ bits per OT. Silent OT sends a polylogarithmic amount of data total for the entire extension. The precursor construction &quot;Compressing Vector OLE&quot; by Boyle, Couteau, Gilboa, Ishai, Kohl, and Rindal [@boyle-vector-ole-2019] laid the algebraic foundation.&lt;/p&gt;
&lt;p&gt;For Edge Password Monitor&apos;s deployment shape (small client set, large server set), Silent OT does not land in the production protocol -- HE-PSI provides the asymmetric communication scaling -- but its existence in 2019 is part of why the industry treats OT extension as essentially solved engineering and feels free to ride a higher-layer protocol on top.&lt;/p&gt;
&lt;h3&gt;The OPRF-PSI plateau: KKRT16&lt;/h3&gt;
&lt;p&gt;Pure OT-extension is one substrate; the other is the Oblivious Pseudorandom Function.&lt;/p&gt;

A two-party protocol in which the sender holds a key $k$, the receiver holds an input $x$, and after the protocol the receiver learns $F_k(x)$ while the sender learns nothing about $x$. The receiver gets the PRF output without giving up the input; the sender keeps the key without giving up the output. OPRFs are the building block under most modern PSI: each party evaluates the OPRF on their set, then plaintext-compares the outputs.
&lt;p&gt;In 2016, Vladimir Kolesnikov, Ranjit Kumaresan, Mike Rosulek, and Ni Trieu published &quot;Efficient Batched Oblivious PRF with Applications to Private Set Intersection&quot; at CCS 2016 [@kkrt-2016]. The paper builds a batched OPRF directly on top of KOS-style OT extension. The reported benchmark: intersecting two $2^{20}$-element sets on a LAN took about 3.8 seconds total. For several years, KKRT16 was the deployment-grade symmetric-PSI protocol.&lt;/p&gt;
&lt;p&gt;KKRT16 is great if your two sets are roughly the same size. The Edge Password Monitor problem is fundamentally asymmetric -- the client holds a few hundred saved passwords, the server holds billions of breached credentials. For &lt;em&gt;asymmetric&lt;/em&gt; PSI, the OT-extension lineage hits a wall the next generation has to climb.&lt;/p&gt;

flowchart LR
    A[&quot;Kappa base OTs&lt;br /&gt;(public-key)&quot;] --&amp;gt; B[&quot;IKNP03 extension&lt;br /&gt;(symmetric)&quot;]
    B --&amp;gt; C[&quot;KOS15 active security&quot;]
    C --&amp;gt; D[&quot;Silent OT&lt;br /&gt;(PCG-based)&quot;]
    B --&amp;gt; E[&quot;KKRT16 OPRF-PSI&quot;]
    C --&amp;gt; F[&quot;CHLR18 HE-PSI&lt;br /&gt;+ OPRF wrapping&quot;]
    D --&amp;gt; G[&quot;Modern OT-extension libraries:&lt;br /&gt;libOTe, EMP-toolkit&quot;]
    E --&amp;gt; H[&quot;Symmetric balanced PSI&quot;]
    F --&amp;gt; I[&quot;Edge Password Monitor&quot;]
&lt;h2&gt;5. The breakthrough: HE-based PSI&lt;/h2&gt;
&lt;p&gt;Asymmetric PSI requires that the server&apos;s heavy compute stays on the server, and that the client send only a tiny encrypted query whose size is independent of $|S_B|$. That is exactly what fully homomorphic encryption -- or, more precisely, &lt;em&gt;somewhat-homomorphic&lt;/em&gt; encryption -- can offer.&lt;/p&gt;

An encryption scheme is *homomorphic* if operations on ciphertexts decrypt to the corresponding operations on plaintexts. *Somewhat-homomorphic encryption* (SWHE) supports a bounded depth of operations (typically additions and multiplications) before noise growth requires re-encryption. *Fully homomorphic encryption* (FHE) supports arbitrary-depth circuits via bootstrapping. The BFV scheme (Brakerski-Fan-Vercauteren), implemented in Microsoft SEAL [@ms-seal], is the SWHE variant Edge Password Monitor uses; FHE is the popular term but the actual deployed circuit depth fits comfortably within SWHE.
&lt;h3&gt;CLR17: the cost curve flips&lt;/h3&gt;
&lt;p&gt;In 2017, Hao Chen, Kim Laine, and Peter Rindal published &quot;Fast Private Set Intersection from Homomorphic Encryption&quot; at CCS 2017 [@clr-2017]. The construction is a clean revival of FNP04&apos;s polynomial-roots idea, with three engineering moves that fix every reason FNP04 was infeasible.&lt;strong&gt;Move 1: SWHE instead of Paillier.&lt;/strong&gt; BFV ciphertexts pack many plaintext slots and support SIMD-style homomorphic operations. A single ciphertext can encrypt and evaluate over thousands of plaintext values in parallel; the slot count is set at scheme-parameter time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Move 2: Cuckoo hash partitioning.&lt;/strong&gt; The receiver Cuckoo-hashes its set $S_R$ into bins. The sender hashes each element of $S_S$ to the same set of bins. Instead of one giant polynomial whose roots are all of $S_S$, the sender builds one small polynomial per bin -- typically a few thousand bins, each holding a few hundred elements.&lt;/p&gt;

A hashing scheme that uses $k$ hash functions and inserts each element into one of $k$ candidate bins, displacing existing occupants if necessary (the displaced element finds another of its candidate bins). Cuckoo hashing achieves $O(1)$ worst-case lookup; the achievable load factor depends on the number of hash functions and the bucket size -- roughly 49% with $k=2$ (the original Pagh-Rodler 2001 construction [@pagh-rodler-2001]), roughly 91% with $k=3$, and higher with a stash of evicted elements or $k \geq 4$. CLR17 and CHLR18 use parameter choices in the high-load regime. In CLR17, Cuckoo hashing pairs the receiver&apos;s set with the sender&apos;s set so that two equal elements end up in the same bin with overwhelming probability.
&lt;p&gt;&lt;strong&gt;Move 3: Partition-and-evaluate.&lt;/strong&gt; The receiver encrypts its bins under BFV and sends them. The sender homomorphically evaluates its per-bin polynomial at the encrypted receiver&apos;s bin. Because of SIMD slot packing, each bin&apos;s polynomial is evaluated in parallel across all slots, and the sender&apos;s total work is $O(|S_S| \log |S_R|)$ FHE operations instead of FNP04&apos;s $O(|S_R| \cdot |S_S|)$.&lt;/p&gt;
&lt;p&gt;The headline benchmark from the paper, on the MSR publication page: &quot;36 seconds of online-computation and 12.5 MB of round trip communication to intersect five thousand 32-bit strings with 16 million 32-bit strings&quot; [@msr-clr17-pub]. Communication scales linearly in the small set and logarithmically in the large set. The cost curve is finally right.&lt;/p&gt;

sequenceDiagram
    participant C as Client (Edge)
    participant S as Server (Microsoft)
    Note over C,S: stage 1 -- OPRF preprocessing (binds queries to server&apos;s secret key)
    C-&amp;gt;&amp;gt;S: blinded credential beta * H(cred)
    S-&amp;gt;&amp;gt;C: alpha * (blinded H(cred)) using server key alpha
    C-&amp;gt;&amp;gt;C: unblind, obtain F_alpha(cred)
    Note over C,S: stage 2 -- HE-PSI on sharded corpus
    C-&amp;gt;&amp;gt;S: BFV ciphertext encrypting F_alpha(cred), sharded by 2-byte prefix
    S-&amp;gt;&amp;gt;S: Cuckoo-hash shard, evaluate per-bin polynomial homomorphically
    S-&amp;gt;&amp;gt;C: encrypted match result + label ciphertext
    C-&amp;gt;&amp;gt;C: decrypt result, then if match surface breach metadata
&lt;h3&gt;CHLR18: labeled, malicious, deployable&lt;/h3&gt;
&lt;p&gt;The next year, the same authors plus Zhicong Huang published &quot;Labeled PSI from Fully Homomorphic Encryption with Malicious Security&quot; at CCS 2018 [@chlr-2018]. The paper adds three production-grade properties.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Labels.&lt;/strong&gt; Each element in the server&apos;s set can carry an associated label (which breach, when, severity). When the receiver finds a match, they also recover the label.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Malicious security.&lt;/strong&gt; The protocol is secure against an actively malicious sender, layered on top of the underlying semi-honest construction via an OPRF preprocessing step. The OPRF is the same primitive we met in §4; here it does double duty: it prevents the client from brute-forcing the server&apos;s corpus offline (the client cannot evaluate $F_k(\cdot)$ without server interaction) and provides the malicious-security guarantee.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Arbitrary-length items.&lt;/strong&gt; The protocol handles long inputs (full URLs plus usernames, in the breach-checking case), not just short fixed-width keys.&lt;/p&gt;
&lt;p&gt;The headline benchmark: &quot;for an intersection of $2^{20}$ and 512 size sets of arbitrary length items our protocol has a total online running time of just 1 second (single thread), and a total communication cost of 4 MB&quot; [@msr-chlr18-pub]. A larger benchmark of $2^{28}$ and 1024 takes 12 seconds multithreaded with less than 18 MB of communication.&lt;/p&gt;
&lt;h3&gt;Cong et al. 2021: the production-grade successor&lt;/h3&gt;
&lt;p&gt;The protocol that ships in Edge Password Monitor today is the descendant published by Kelong Cong, Radames Cruz Moreno, Mariana Botelho da Gama, Wei Dai, Ilia Iliashenko, Kim Laine, and Michael Rosenberg at CCS 2021: &quot;Labeled PSI from Homomorphic Encryption with Reduced Computation and Communication&quot; [@cong-2021]. The paper is the basis for Microsoft&apos;s open-source APSI library [@ms-apsi], whose README states verbatim that it &quot;provides a PSI functionality for asymmetric set sizes based on the protocol described in eprint.iacr.org/2021/1116&quot; and that it &quot;uses the BFV encryption scheme implemented in the Microsoft SEAL library.&quot;The Cong et al. 2021 byline is seven authors: Kelong Cong, Radames Cruz Moreno, Mariana Botelho da Gama, Wei Dai, Ilia Iliashenko, Kim Laine, Michael Rosenberg. Some upstream reporting conflates a different author list onto the same URL; the citation_author meta-tags returned by ePrint 2021/1116 confirm this seven-author septuple [@cong-2021].&lt;/p&gt;
&lt;h3&gt;The OPRF wrapping and corpus sharding&lt;/h3&gt;
&lt;p&gt;Two practical layers on top of the bare HE-PSI protocol turn the academic construction into a production deployment, and the Microsoft Research Password Monitor blog is explicit about both [@msr-password-monitor-2021].&lt;/p&gt;
&lt;p&gt;First, the OPRF preprocessing. Without it, a malicious client could send candidate passwords one at a time and observe match results, brute-forcing the server&apos;s corpus. With it, every client query passes through $F_k(\cdot)$ where $k$ is a server secret. The MSR blog states: &quot;the client communicates with the server to obtain a hash $H$ of the credential, where $H$ denotes a hash function that only the server knows... using an OPRF... the client is prevented from performing an efficient dictionary attack on the server&quot; [@msr-password-monitor-2021].&lt;/p&gt;
&lt;p&gt;Second, corpus sharding. The MSR blog notes that the corpus is sharded by the first two bytes of a username-hash. The blog&apos;s verbatim example: &quot;Suppose the database $D$ consists of 4 billion credentials, then after sharding each subset, it will contain about 60,000 credentials on average.&quot; At the article&apos;s 2026 5-billion projection the math is the same -- corpus divided by $2^{16}$ -- and per-shard work is closer to 76,000 credentials. Either way, the per-query homomorphic evaluation runs against tens of thousands of credentials instead of the full corpus. This is the same engineering trade as Apple&apos;s 15-bit bucketing -- a small information leak (the client reveals which shard their query lives in) in exchange for tractable per-query compute.&lt;/p&gt;

A Windows facility, introduced in Windows 2000, that encrypts arbitrary blobs under a user-derived key chain (ultimately rooted in the user&apos;s password, with hardware-bound variants under DPAPI-NG) and exposes a simple `CryptProtectData` / `CryptUnprotectData` API [@ms-learn-dpapi-ng]. Browsers including Chromium store the symmetric key that wraps their saved-password database under DPAPI at rest. This protects the on-disk database when the user is not logged in, but it does not protect process memory after the same user has unwrapped the data into a running browser.

This unique security feature is possible due to pioneering cryptography research and technology incubation done here at Microsoft Research. -- Microsoft Research, January 21, 2021 [@msr-password-monitor-2021]
&lt;p&gt;The administrator-visible group policy that controls this feature is &lt;code&gt;PasswordMonitorAllowed&lt;/code&gt;, documented on Microsoft Learn [@ms-learn-edge-pm].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Asymmetric PSI on somewhat-homomorphic encryption flips the cost curve so that communication scales with the small client set, not the enormous server set. That is why a homomorphic-encryption protocol can ship on a consumer browser in 2021 without melting the user&apos;s CPU. The cryptographic case for Edge Password Monitor is auditable down to the published papers and unequivocally well-engineered.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Microsoft has shipped the first production consumer homomorphic-encryption deployment in a browser, against the threat &quot;server-side breach corpus leakage,&quot; on the same browser that, in §7, will turn out to hold every saved credential in plaintext RAM the entire time you have it open. To make sense of that contrast, we need to see what the rest of the industry did with the same problem.&lt;/p&gt;
&lt;h2&gt;6. State of the art: four deployed compromised-credential services&lt;/h2&gt;
&lt;p&gt;PSI on paper is one thing. PSI in production is another. The &quot;pure PSI&quot; ideal -- both parties learn the intersection and &lt;em&gt;nothing else&lt;/em&gt;, no information leaks on either side -- is impractical at planetary scale. Every deployed compromised-credential service in 2026 makes a concession somewhere.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The concessions reveal which threats each provider takes most seriously. Read the next table by column 3 (&quot;what is revealed on the wire&quot;) and column 6 (&quot;dictionary-attack hardening&quot;) side by side: that pair tells you the threat model each provider chose.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The four services compared here are HIBP Pwned Passwords v3, Google Password Checkup, Apple Password Monitoring (iCloud Keychain), and Microsoft Edge Password Monitor. A fifth, Signal contact discovery, is technically a contact-discovery service rather than a breach checker, but it sits on the same protocol map and is the canonical &quot;we used a TEE instead of pure crypto&quot; data point.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Protocol family&lt;/th&gt;
&lt;th&gt;What&apos;s revealed on the wire&lt;/th&gt;
&lt;th&gt;Server trust&lt;/th&gt;
&lt;th&gt;Bandwidth at scale&lt;/th&gt;
&lt;th&gt;Dictionary-attack hardening&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;HIBP Pwned Passwords v3 [@hibp-api-v3]&lt;/td&gt;
&lt;td&gt;Pure SHA-1 5-hex-char k-anonymity&lt;/td&gt;
&lt;td&gt;A 20-bit hash prefix per query&lt;/td&gt;
&lt;td&gt;None (zero-trust API)&lt;/td&gt;
&lt;td&gt;Trivial (a few KB per query)&lt;/td&gt;
&lt;td&gt;None on the wire; SHA-1 hash makes corpus searchable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Password Checkup [@thomas-usenix-2019]&lt;/td&gt;
&lt;td&gt;k-anonymity + blinded-hash OPRF&lt;/td&gt;
&lt;td&gt;A small hash prefix per query&lt;/td&gt;
&lt;td&gt;Honest-but-curious&lt;/td&gt;
&lt;td&gt;Tens of KB per query&lt;/td&gt;
&lt;td&gt;OPRF prevents corpus enumeration by the client&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apple Password Monitoring [@apple-password-monitoring]&lt;/td&gt;
&lt;td&gt;EC-based PSM on NIST P-256 + 15-bit bucket&lt;/td&gt;
&lt;td&gt;A 15-bit prefix + double-blinded EC point&lt;/td&gt;
&lt;td&gt;Honest-but-curious&lt;/td&gt;
&lt;td&gt;A few hundred KB per query (padded)&lt;/td&gt;
&lt;td&gt;OPRF + double-blinding + padding-to-fixed-count&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Signal contact discovery (2017) [@signal-private-contact-2017]&lt;/td&gt;
&lt;td&gt;SGX enclave + ORAM (no pure crypto)&lt;/td&gt;
&lt;td&gt;Nothing visible to Signal staff&lt;/td&gt;
&lt;td&gt;TEE attestation&lt;/td&gt;
&lt;td&gt;Negligible (single SGX RPC)&lt;/td&gt;
&lt;td&gt;Enclave isolation rather than crypto hardening&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft Edge Password Monitor [@msr-password-monitor-2021]&lt;/td&gt;
&lt;td&gt;HE-PSI on Microsoft SEAL + OPRF + 2-byte shard&lt;/td&gt;
&lt;td&gt;2-byte username-hash prefix + BFV ciphertext&lt;/td&gt;
&lt;td&gt;Honest-but-curious&lt;/td&gt;
&lt;td&gt;Single MB-range round trip&lt;/td&gt;
&lt;td&gt;OPRF binds queries to server key; HE prevents transcript leaks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;HIBP Pwned Passwords v3: the k-anonymity baseline&lt;/h3&gt;
&lt;p&gt;Troy Hunt launched Pwned Passwords v2 in 2018 with the help of Junade Ali at Cloudflare, adding a k-anonymity API; the design is published in two posts, Hunt&apos;s &quot;I&apos;ve Just Launched Pwned Passwords Version 2&quot; and Ali&apos;s &quot;Validating Leaked Passwords with k-Anonymity&quot; [@hunt-pwned-v2-2018][@ali-cloudflare-2018]. The protocol is delightfully simple: the client hashes the candidate password under SHA-1, sends the first 5 hex characters (20 bits) of the hash to the API, and the API returns every suffix in that bucket. The client compares locally.&lt;/p&gt;

A privacy property: each query produces output that is consistent with at least $k$ other potential queries the client could have made. In the HIBP context, $k$ is the number of distinct password hashes that share the same 20-bit SHA-1 prefix -- typically a few hundred. The server learns the bucket but not which specific password the client cares about, and (because hashes are sparse over the prefix space) cannot easily distinguish &quot;the user has password X&quot; from &quot;the user has password Y&quot; if X and Y share the prefix.
&lt;p&gt;The HIBP corpus serves &quot;18B+ Monthly Requests&quot; against roughly a billion hashes [@hibp-passwords]. Operationally, this is a one-shot HTTP GET. There is no PSI on the wire beyond TLS. The whole protocol fits on the back of an envelope. The cost: each query leaks the 20-bit prefix, which is enough to identify the user&apos;s password if the attacker has independent information narrowing the candidate space.&lt;/p&gt;
&lt;p&gt;{&lt;code&gt;async function sha1Hex(s) {   const buf = new TextEncoder().encode(s);   const hash = await crypto.subtle.digest(&quot;SHA-1&quot;, buf);   return [...new Uint8Array(hash)].map(b =&amp;gt; b.toString(16).padStart(2, &quot;0&quot;)).join(&quot;&quot;).toUpperCase(); } async function showBucket(password) {   const h = await sha1Hex(password);   const prefix = h.slice(0, 5);    // 5 hex chars -- 20 bits sent to server   const suffix = h.slice(5);   console.log(&quot;Password:&quot;, password);   console.log(&quot;SHA-1:   &quot;, h);   console.log(&quot;Prefix (leaves your device):&quot;, prefix);   console.log(&quot;Suffix (compared locally):  &quot;, suffix);   console.log(&quot;Approx bucket size: ~&quot;, Math.round(847_223_402 / (1&amp;lt;&amp;lt;20)), &quot;entries&quot;); } showBucket(&quot;hunter2&quot;);&lt;/code&gt;}&lt;/p&gt;
&lt;p&gt;The mental model the runnable above gives is the precise shape of the trade. Every HIBP query says &quot;I am asking about a password whose SHA-1 starts with these 20 bits.&quot; There are roughly $2^{20} \approx 1{,}048{,}576$ possible prefixes, so each query narrows the server&apos;s posterior over your password by exactly that much.&lt;/p&gt;
&lt;h3&gt;Google Password Checkup: k-anonymity with an OPRF on top&lt;/h3&gt;
&lt;p&gt;In August 2019, Kurt Thomas and colleagues at Google published &quot;Protecting Accounts from Credential Stuffing with Password Breach Alerting&quot; at USENIX Security [@thomas-usenix-2019]. The accompanying blog post on the Google Security Blog announces the deployment [@google-blog-password-checkup-2019]. The numbers are familiar at this point: &quot;a cloud service that mediates access to over 4 billion credentials found in breaches and a Chrome extension serving as an initial client. Based on anonymous telemetry from nearly 670,000 users and 21 million logins, we find that 1.5% of logins on the web involve breached credentials&quot; [@thomas-usenix-2019].&lt;/p&gt;
&lt;p&gt;The protocol upgrades HIBP&apos;s k-anonymity baseline with an OPRF preprocessing round: instead of hashing under SHA-1 locally and sending the prefix, the client first obtains $F_k(\text{password})$ via an OPRF interaction, where $k$ is a Google-held key. The OPRF output is then bucketed and matched against Google&apos;s corpus. The OPRF prevents the client from enumerating Google&apos;s corpus offline; the bucketing limits per-query server work.&lt;/p&gt;
&lt;h3&gt;Apple Password Monitoring: PSM with double-blinding&lt;/h3&gt;
&lt;p&gt;Apple&apos;s protocol is the most cryptographically elaborate of the four. The Apple Platform Security guide is unusually explicit [@apple-password-monitoring][@apple-security-guide-pdf]. From the guide, verbatim: &quot;a form of cryptographic private set intersection is deployed that compares the users&apos; passwords against a large set of leaked passwords&quot;; the corpus is &quot;approximately 1.5 billion passwords... into $2^{15}$ different buckets&quot;; and the protocol uses elliptic-curve PSM on NIST P-256 with a double-blinded structure.&lt;/p&gt;
&lt;p&gt;The math, slightly compressed. Let $H_{\text{SWU}}$ be the Shallue-van de Woestijne-Ulas hash-to-curve.&lt;/p&gt;
&lt;p&gt;Google publishes an open-source PSM construction at &lt;code&gt;google/private-membership&lt;/code&gt; [@google-private-membership-github]; Apple&apos;s protocol shares the EC double-blinding skeleton. Apple computes a per-corpus-element representation:&lt;/p&gt;
&lt;p&gt;$$P_{pw} = \alpha \cdot H_{\text{SWU}}(pw)$$&lt;/p&gt;
&lt;p&gt;where $\alpha$ is a secret random key known only to Apple. The client computes its query:&lt;/p&gt;
&lt;p&gt;$$P_c = \beta \cdot H_{\text{SWU}}(pw)$$&lt;/p&gt;
&lt;p&gt;with $\beta$ chosen randomly per-query. The interaction lets the client recover $\alpha \cdot H_{\text{SWU}}(pw)$ and check it against a 15-bit bucket of $P_{pw}$ values. (Apple&apos;s public documentation hashes only the password; whether the production implementation includes additional salting is not disclosed.) The double-blinding is the point: $\alpha$ stays Apple&apos;s secret (so the client cannot enumerate); $\beta$ stays per-query random (so Apple cannot link two queries from the same client).Apple&apos;s PSM defends &lt;em&gt;also&lt;/em&gt; against the server learning how many unique passwords a user has, by padding-to-fixed-count with random queries: &quot;if a user has fewer than this number, random passwords are generated and added to the queries to make up the difference&quot; [@apple-password-monitoring]. None of the other four services deploys this defence. The padding cost is the price.&lt;/p&gt;
&lt;h3&gt;Signal contact discovery: the TEE outlier&lt;/h3&gt;
&lt;p&gt;In September 2017, Moxie Marlinspike published &quot;Technology Preview: Private Contact Discovery&quot; on Signal&apos;s blog [@signal-private-contact-2017]. The post is candid about the cost calculation that drove Signal toward Intel SGX rather than pure cryptographic PSI:&lt;/p&gt;

Signal clients will be able to efficiently and scalably determine whether the contacts in their address book are Signal users *without revealing the contacts in their address book to the Signal service*. -- Moxie Marlinspike, September 2017 [@signal-private-contact-2017]
&lt;p&gt;Marlinspike is explicit about the cost calculation: &quot;Doing better is difficult. There are a range of options that don&apos;t work... like using bloom filters, encrypted bloom filters, sharded bloom filters.&quot; Signal examines pure cryptographic PSI and decides, given its scale and latency requirements, that an SGX enclave running a constant-time ORAM-protected lookup is the better engineering trade [@signal-cds-github].&lt;/p&gt;

The SGX choice came with side-channel debt that subsequent literature made expensive. Foreshadow (2018) [@foreshadow-2018], SgxPectre (2018) [@sgxpectre-2018], SGAxe (2020) [@sgaxe-2020], and AEPIC Leak (2022) [@aepic-leak-2022] all targeted SGX directly. Each disclosure prompted Signal to publish a re-evaluation. Signal eventually migrated to the second-generation Contact Discovery Service (CDSI), which continues to rely on TEEs but with a hardened threat model. The point for our story is not that SGX is bad. It is that &quot;pure crypto vs. TEE&quot; is not a settled question; every provider revisits it under their own latency, corpus, and threat-model constraints, and each makes a different decision.
&lt;h3&gt;Microsoft Edge Password Monitor&lt;/h3&gt;
&lt;p&gt;The Microsoft deployment is the only one shipping a full HE-PSI protocol on the wire against the full corpus. As established in §5, the protocol stack is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Two-byte username-hash shard selection (corpus partitioned, sender does work only against tens of thousands of elements per query -- the MSR blog&apos;s 2021 example uses 4 billion / $2^{16} \approx$ 60,000; the article&apos;s 2026 5-billion projection yields $\approx$ 76,000).&lt;/li&gt;
&lt;li&gt;OPRF preprocessing (binds queries to a server secret; prevents client-side enumeration).&lt;/li&gt;
&lt;li&gt;BFV-encrypted query, evaluated against the Cuckoo-hashed per-bin polynomials, returned as a single ciphertext per shard.&lt;/li&gt;
&lt;li&gt;Client decrypts; if matched, decrypts the associated label (the breach metadata).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;All four moving parts are described in the MSR blog, the Cong et al. 2021 paper, and the open-source APSI library [@msr-password-monitor-2021][@cong-2021][@ms-apsi]. Communication scales with the small client set; sender compute scales with the (sharded) server set. The Microsoft Edge enterprise documentation says the feature &quot;helps Microsoft Edge users protect their online accounts by informing them if any of their passwords are found in an online leak&quot; [@ms-learn-edge-pm].&lt;/p&gt;
&lt;h3&gt;Four products, four concessions&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Primary concession&lt;/th&gt;
&lt;th&gt;What it defends against&lt;/th&gt;
&lt;th&gt;What it does not&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;HIBP&lt;/td&gt;
&lt;td&gt;20-bit prefix leak per query&lt;/td&gt;
&lt;td&gt;Server learning the password&lt;/td&gt;
&lt;td&gt;A linkage attack on repeated queries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google PCU&lt;/td&gt;
&lt;td&gt;OPRF transcript + prefix&lt;/td&gt;
&lt;td&gt;Client-side corpus enumeration&lt;/td&gt;
&lt;td&gt;Server-side query inference if the prefix is rare&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apple PSM&lt;/td&gt;
&lt;td&gt;15-bit bucket + double-blinding overhead&lt;/td&gt;
&lt;td&gt;Both client and server enumeration; query linkage&lt;/td&gt;
&lt;td&gt;Side-channels on the EC implementation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Signal CDS&lt;/td&gt;
&lt;td&gt;TEE attestation trust&lt;/td&gt;
&lt;td&gt;Server-side mass-data exfiltration&lt;/td&gt;
&lt;td&gt;SGX side-channel attacks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edge PM&lt;/td&gt;
&lt;td&gt;2-byte shard leak + OPRF transcript&lt;/td&gt;
&lt;td&gt;Anything short of breach corpus leakage from inside Microsoft&lt;/td&gt;
&lt;td&gt;Endpoint compromise -- see §7&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Four products. Four different concessions. Each is internally coherent. None of them solves a problem that Tom Joran Sonstebyseter Ronning&apos;s PoC will turn out to make trivial.&lt;/p&gt;
&lt;h2&gt;7. The other half: plaintext RAM &quot;by design&quot;&lt;/h2&gt;
&lt;p&gt;Now we turn the article inside out.&lt;/p&gt;
&lt;p&gt;Everything we have built so far -- IKNP, KOS, KKRT, CLR17, CHLR18, Cong et al., Apple&apos;s PSM, Google&apos;s k-anonymity wrapping, the entire CCS-grade cryptographic stack inside Edge -- assumes the &lt;em&gt;endpoint&lt;/em&gt; is trustworthy. The question Ronning asked on May 4, 2026 is what happens when it is not.&lt;/p&gt;
&lt;h3&gt;The disclosure&lt;/h3&gt;
&lt;p&gt;The X post arrived at 14:29:51 UTC on May 4, 2026 [@ronning-x]: &quot;Microsoft Edge loads all your saved passwords into memory in cleartext -- even when you&apos;re not using them.&quot; Five hours later the GitHub repository went public, with a complete C# proof-of-concept and a long README [@ronning-github]. PCWorld picked up the story two days later under the byline of Laura Pippig, summarising Microsoft&apos;s response in English [@pcworld-pippig-2026]. The Norwegian origin, ITavisen, carried the verbatim &quot;by design&quot; rendering and named Ronning&apos;s affiliation with the transmission-system operator Statnett [@itavisen-2026]. Davey Winder at Forbes reached Microsoft and obtained the official spokesperson statement on May 6, 2026 [@forbes-winder].Ronning works at Statnett and presented this finding at BigBiteOfTech (Palo Alto Networks Norway) on April 29, 2026 -- five days before the public X-post disclosure [@itavisen-2026]. The X bio describes &quot;#PenetrationTesting using only tools that are already on the system.&quot;&lt;/p&gt;
&lt;h3&gt;What the PoC does&lt;/h3&gt;
&lt;p&gt;The C# program is short. &lt;code&gt;OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, ...)&lt;/code&gt; against the parent &lt;code&gt;msedge.exe&lt;/code&gt;. A walk over committed memory regions via &lt;code&gt;VirtualQueryEx&lt;/code&gt;. &lt;code&gt;ReadProcessMemory&lt;/code&gt; reads of every region. Pattern matching for stored credential structures. Output: every saved Edge password as plaintext.&lt;/p&gt;
&lt;p&gt;The README is explicit on the constraints. &quot;Can be run without Adminstrator rights, but will only be able to access Edge processes ran by the same user. If run with Administrator privileges, the program can access and read memory from other users&apos; Edge processes on the same machine&quot; [@ronning-github]. No kernel exploit. No DPAPI bypass. The DPAPI unwrap happened earlier, when Edge launched (or when the password feature first activated); the cleartext has been sitting in &lt;code&gt;msedge.exe&lt;/code&gt;&apos;s heap ever since.&lt;/p&gt;
&lt;p&gt;The tested target is Edge 147.0.3912.98, but the README explicitly generalises: &quot;Any Edge versions that&apos;s Chromium based (from version 79 and newer, including 147.0.3912.98 and any future version, as Microsoft won&apos;t change this feature)&quot; [@ronning-github].&lt;/p&gt;
&lt;h3&gt;What the architectural choice is&lt;/h3&gt;
&lt;p&gt;The behaviour Ronning identifies is not a memory-safety bug. It is a design choice: Edge unwraps every DPAPI-protected saved credential into process memory when the password manager activates, and keeps the plaintext resident for the lifetime of the session.&lt;/p&gt;

flowchart TD
    A[&quot;Saved password file&lt;br /&gt;(SQLite blob)&quot;] --&amp;gt;|&quot;DPAPI-wrapped at rest&quot;| B[&quot;Disk: encrypted with&lt;br /&gt;per-user DPAPI key&quot;]
    B --&amp;gt;|&quot;msedge.exe launches&quot;| C[&quot;DPAPI CryptUnprotectData()&lt;br /&gt;unwraps key&quot;]
    C --&amp;gt;|&quot;password manager activates&quot;| D[&quot;Plaintext credentials&lt;br /&gt;resident in msedge.exe heap&quot;]
    D --&amp;gt;|&quot;OpenProcess + ReadProcessMemory&lt;br /&gt;(same-user, no admin)&quot;| E[&quot;EdgeSavedPasswordsDumper&lt;br /&gt;reads cleartext&quot;]
    D --&amp;gt;|&quot;autofill flow&quot;| F[&quot;Plaintext copied into&lt;br /&gt;renderer / web form&quot;]
    classDef warn fill:#7a3030,stroke:#a04848,color:#fce8e8
    class D warn,stroke:#c33
    classDef accent fill:#5d3a5d,stroke:#8a5a8a,color:#fde0fd
    class E accent,stroke:#939
&lt;p&gt;Chrome and Brave do not do this. Both browsers decrypt credentials only at the autofill RPC -- the password manager fetches the DPAPI-wrapped blob, decrypts in a narrow window, hands the plaintext to the relevant renderer, and zeroes the buffer [@chromium-os-crypt]. PCWorld corroborates: &quot;Other password managers, including those that are built into browsers, don&apos;t operate in this way -- Ronning says Edge is the only Chromium-based browser he&apos;s tested with this behavior&quot; [@pcworld-pippig-2026].&lt;/p&gt;
&lt;p&gt;In July 2024, Google announced Chrome App-Bound Encryption -- a further hardening of exactly this same-user-LCE threat model. ABE binds the on-disk key unwrap to a verified Chrome process identity, so a malicious program impersonating Chrome cannot ask DPAPI to unwrap Chrome&apos;s data even if it runs as the same user [@google-chrome-abe-2024]. Microsoft has the same DPAPI substrate; Edge has not adopted the equivalent control.&lt;/p&gt;
&lt;h3&gt;The .NET runtime tie-in to AMSI&lt;/h3&gt;
&lt;p&gt;The PoC&apos;s original implementation language is a noteworthy detail. Ronning&apos;s README states: &quot;.NET Framework 4.8.1 (changed from 3.5 originally)&quot; [@ronning-github]. The original .NET 3.5 choice was deliberate. The Antimalware Scan Interface (AMSI) [@ms-amsi-portal] scans .NET 4.8+ assemblies before execution; .NET 3.5 predates AMSI&apos;s &lt;code&gt;Amsi*&lt;/code&gt; API surface entirely [@ms-amsi-dotnet48].The current GitHub README has changed the framework version to .NET 4.8.1 (likely to ensure the PoC runs out-of-the-box on modern Windows), but the original framing -- and the original threat-model point -- was the AMSI evasion that .NET 3.5 enables. The sibling AMSI post in this series explains why the 3.5 framing matters.&lt;/p&gt;
&lt;h3&gt;Microsoft&apos;s response, verbatim&lt;/h3&gt;

Safety and security are foundational to Microsoft Edge. Access to browser data as described in the reported scenario would require the device to already be compromised. Design choices in this area involve balancing performance, usability, and security, and we continue to review it against evolving threats. Browsers access password data in memory to help users sign in quickly and securely -- this is an expected feature of the application. We recommend users install the latest security updates and antivirus software to help protect against security threats. -- Microsoft spokesperson, via Forbes, May 6, 2026 [@forbes-winder]

The statement is technically defensible. The threat model is exactly what the spokesperson says: an attacker who can already execute code as the user on the user&apos;s machine. In MSRC&apos;s published servicing criteria [@msrc-servicing-criteria], &quot;exploitation requires local code execution&quot; is a recurring boundary line -- the same line MSRC applied to Mimikatz against LSASS in the pre-Credential-Guard era, and that Microsoft eventually crossed by shipping [Credential Guard](/blog/the-empty-hash-credential-guard-the-lsaiso-trustlet-and-the-/). The &quot;by design&quot; framing is consistent with a decade of precedent.
Microsoft&apos;s response is internally consistent with a decade of MSRC policy. The &quot;exploitation requires local code execution&quot; framing was applied to Mimikatz against LSASS for years before Credential Guard arrived. It is applied to &quot;give me a debugger and I can read anything&quot; type attacks generally. The position is not improvised, and it is not a special accommodation for Edge. The question this article asks is not &quot;is the position internally consistent&quot; -- it is -- but &quot;what threat model does the position concede.&quot; The answer is the same-user local-code-execution threat model. Whether the concession is acceptable depends on whether the user&apos;s environment makes same-user LCE rare (a single-user Surface) or routine (a Citrix farm, an AVD pool, a shared family computer).
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you operate a multi-user Windows host -- RDS, AVD, Citrix, a shared lab, a family PC with multiple sign-in accounts -- every Edge session&apos;s saved credentials are recoverable by any same-user process during that session, and by an administrator across sessions. The &quot;the device is already compromised&quot; framing is asymmetric: a same-user LCE event on a multi-user host is structurally more common than on a single-user laptop, because there are more identities sharing the same physical machine.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Edge does not have a credential-storage vulnerability. Edge has a credential-storage architectural choice. The choice is to spend the entire browser session&apos;s worth of plaintext-in-RAM budget on autofill UX latency. The choice is defensible. It is also a precise statement of which threats the Edge product team is and is not defending against.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Microsoft&apos;s response is technically defensible. It is also a precise statement of which threat model the Edge product team is and is not defending against. To see why both halves of this article describe the same product, we need to look at the architectural alternatives.&lt;/p&gt;
&lt;h2&gt;8. Competing approaches: where should the secret store live?&lt;/h2&gt;
&lt;p&gt;Three architectural positions present themselves, as siblings rather than as a generational ladder:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Browser-as-secret-store, decrypt-on-launch&lt;/strong&gt; (Edge today). Plaintext-in-RAM window: the entire session. Autofill latency: a memcpy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Browser-as-secret-store, decrypt-on-autofill&lt;/strong&gt; (Chrome, Brave). Plaintext-in-RAM window: the autofill RPC. Autofill latency: one DPAPI unwrap per fill (microseconds).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OS-as-secret-broker&lt;/strong&gt; (the design the Windows Credential Manager and DPAPI-NG already implement for native apps). Plaintext never crosses into the browser&apos;s process; a higher-privileged broker holds the plaintext at autofill time and the browser receives a handle, not the secret.&lt;/li&gt;
&lt;/ol&gt;

flowchart LR
    subgraph &quot;Decrypt-on-launch (Edge)&quot;
        A1[Disk: DPAPI blob] --&amp;gt; A2[Browser process&lt;br /&gt;plaintext, full session]
        A2 --&amp;gt; A3[Renderer: autofill memcpy]
    end
    subgraph &quot;Decrypt-on-autofill (Chrome / Brave)&quot;
        B1[Disk: DPAPI blob] --&amp;gt; B2[Browser process&lt;br /&gt;plaintext, narrow RPC]
        B2 --&amp;gt; B3[Renderer: autofill]
    end
    subgraph &quot;OS-as-secret-broker&quot;
        C1[Disk: DPAPI-NG blob] --&amp;gt; C2[OS broker process&lt;br /&gt;plaintext only here]
        C2 -.handle.-&amp;gt; C3[Browser receives handle]
        C3 -.autofill via broker.-&amp;gt; C4[Renderer]
    end
&lt;h3&gt;Six-axis comparison&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Axis&lt;/th&gt;
&lt;th&gt;Decrypt-on-launch (Edge)&lt;/th&gt;
&lt;th&gt;Decrypt-on-autofill (Chrome, Brave)&lt;/th&gt;
&lt;th&gt;OS-as-broker&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Plaintext-in-RAM window&lt;/td&gt;
&lt;td&gt;Full session&lt;/td&gt;
&lt;td&gt;Autofill RPC (~ms)&lt;/td&gt;
&lt;td&gt;Never, in the browser process&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Autofill latency&lt;/td&gt;
&lt;td&gt;Memcpy (nanoseconds)&lt;/td&gt;
&lt;td&gt;DPAPI unwrap (~10s of microseconds)&lt;/td&gt;
&lt;td&gt;IPC + broker policy check (~ms)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Same-user-LCE attack surface&lt;/td&gt;
&lt;td&gt;High (ReadProcessMemory exposes all)&lt;/td&gt;
&lt;td&gt;Low (must catch the RPC window)&lt;/td&gt;
&lt;td&gt;Negligible (no plaintext in the browser)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory-scraping forensics&lt;/td&gt;
&lt;td&gt;Trivial (any same-user dump works)&lt;/td&gt;
&lt;td&gt;Hard (must dump during fill)&lt;/td&gt;
&lt;td&gt;Impossible (no plaintext to dump)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sync UX with cloud account&lt;/td&gt;
&lt;td&gt;Standard&lt;/td&gt;
&lt;td&gt;Standard&lt;/td&gt;
&lt;td&gt;Standard (broker handles sync)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Engineering cost to ship&lt;/td&gt;
&lt;td&gt;Already shipped&lt;/td&gt;
&lt;td&gt;Already shipped (Chromium baseline)&lt;/td&gt;
&lt;td&gt;High (broker IPC, signed code path, extension renegotiation)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The OS-broker position is not hypothetical. The Windows Credential Manager already provides this property for Windows-app credentials. &lt;a href=&quot;https://paragmali.com/blog/your-face-is-not-your-password-inside-windows-hellos-hardwar/&quot; rel=&quot;noopener&quot;&gt;WebAuthn and passkeys&lt;/a&gt; provide it for sites that have adopted the standard. The DPAPI-NG protection descriptors include a &lt;code&gt;WEBCREDENTIALS=&lt;/code&gt; variant [@ms-learn-dpapi-ng][@ms-learn-dpapi-ng-descriptors]. &lt;a href=&quot;https://paragmali.com/blog/pluton-a-tpm-on-silicon-microsoft-can-patch/&quot; rel=&quot;noopener&quot;&gt;Pluton&lt;/a&gt;-anchored vTPM key unwrap provides a hardware-rooted broker substrate [@ms-learn-pluton]. Credential Guard&apos;s LSAISO trustlet is architecturally an isolated secret-broker for LSASS-derived secrets [@ms-learn-credential-guard].&lt;/p&gt;
&lt;p&gt;None of these primitives are wired into Edge&apos;s saved-passwords path. The engineering cost is non-trivial: the broker needs an IPC contract, the browser needs a signed-and-attested code path that talks to the broker, and the renderer extension API surface needs renegotiation. But the cost is finite, and the alternative is what Google has been shipping in Chrome since 2024 -- Chrome&apos;s App-Bound Encryption (see §7) is exactly a step toward the broker model, and Microsoft has the same DPAPI substrate but no equivalent control for Edge [@google-chrome-abe-2024].&lt;/p&gt;
&lt;h3&gt;What &quot;by design&quot; means structurally&lt;/h3&gt;
&lt;p&gt;Microsoft can take the &quot;by design&quot; position because they are not wrong about cryptography. They are right about the bound. No protocol can autofill plaintext into a child renderer without &lt;em&gt;some&lt;/em&gt; process in the chain holding plaintext at the moment of fill. The architectural question is &lt;em&gt;which&lt;/em&gt; process and &lt;em&gt;for how long&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Edge&apos;s answer: &quot;the parent browser process, for the entire session.&quot; Chrome and Brave&apos;s answer: &quot;the parent browser process, for the autofill RPC.&quot; The broker design&apos;s answer: &quot;a separate, higher-privileged process, for the autofill RPC, and never the browser at all.&quot;&lt;/p&gt;
&lt;p&gt;All three are valid points in the design space. The question is not &quot;which is right&quot; -- the answer depends on the user&apos;s environment -- but &quot;what should the default be for a 2026 consumer browser.&quot; The PSI half of the article shows Microsoft can choose the most demanding default when they want to. The endpoint half shows what default they chose here.&lt;/p&gt;
&lt;p&gt;To see why this is a structural property of the problem, not a Microsoft-specific gap, we need to look at the theoretical limits on both sides.&lt;/p&gt;
&lt;h2&gt;9. Theoretical limits&lt;/h2&gt;
&lt;p&gt;Two lower bounds, in parallel: one cryptographic (the PSI side), one architectural (the endpoint side).&lt;/p&gt;
&lt;h3&gt;PSI side: communication and computation lower bounds&lt;/h3&gt;
&lt;p&gt;The communication lower bound for PSI is folklore, used as the comparison baseline in Pinkas-Schneider-Zohner at USENIX Security 2014 [@psz-2014]. Informally: any PSI protocol must transmit at least $\Omega(\min(n_A, n_B) \cdot \kappa)$ bits, where $\kappa$ is the security parameter. The argument is information-theoretic: the receiver has to learn the intersection, which can have size up to $\min(n_A, n_B)$, and each element identifier needs $\Omega(\kappa)$ bits of representation to avoid collisions.&lt;/p&gt;
&lt;p&gt;Silent OT [@silent-ot-2019] meets this lower bound up to polylogarithmic factors in the symmetric balanced setting. HE-PSI in the asymmetric setting gets to $O(n_R \cdot \log n_S)$ ciphertexts via CLR17&apos;s partition-and-evaluate construction [@clr-2017], which is sublinear in $n_S$ -- the breakthrough that makes Edge Password Monitor practical.&lt;/p&gt;
&lt;p&gt;The computation lower bound on the sender side is $\Omega(n_S)$. The sender must, in the limit, touch each element of its set at least once per query. There is no way around this without trading correctness or privacy. Apple &quot;cheats&quot; by reducing the effective $n_S$: their 15-bit bucket cuts the per-query work to roughly $1.5\text{B} / 2^{15} \approx 46{,}000$ elements. Microsoft&apos;s two-byte shard cuts to roughly $5\text{B} / 2^{16} \approx 76{,}000$ elements. The lower bound applies &lt;em&gt;per shard&lt;/em&gt;, not per total corpus.&lt;/p&gt;
&lt;p&gt;The OT-extension lower bound is $\Omega(\kappa)$ base OTs per protocol session, with the bulk of the OT count amortised away by symmetric crypto. KOS15 meets this; Silent OT improves the wire constants further. By 2026, OT extension is essentially solved engineering.&lt;/p&gt;
&lt;h3&gt;Endpoint side: the &quot;no plaintext in process&quot; lower bound&lt;/h3&gt;
&lt;p&gt;The cryptographic side is comfortably tight. The endpoint side is much weirder.For a process $P$ to autofill a credential into a child form, &lt;em&gt;some component&lt;/em&gt; in the trust chain must hold the plaintext at the moment of fill. There are exactly three possible holders:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;$P$ itself.&lt;/strong&gt; The Edge design. Plaintext lives in the parent browser process throughout the session.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A child renderer $Q$.&lt;/strong&gt; The Chrome / Brave design. Plaintext crosses the parent-renderer boundary for the duration of the autofill RPC and gets zeroed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A separate higher-privileged broker $B$.&lt;/strong&gt; The OS-broker design. Plaintext lives in a sibling process that is harder to dump than the browser (in the limit, a PPL or a Credential-Guard-style trustlet).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;No general cryptographic primitive lets a process &lt;em&gt;use&lt;/em&gt; a plaintext credential without ever &lt;em&gt;holding&lt;/em&gt; it. The plaintext is a value; the operations on it (paste-into-form, compute-HMAC-with-it, transmit-over-TLS-as-a-bearer-token) all require it in cleartext at some point. This is not a deficiency of any particular cryptosystem. It is the definition of &quot;use.&quot;&lt;/p&gt;
&lt;p&gt;The plaintext-RAM design Edge ships is not a cryptographic failure. It is a deliberate choice to spend the plaintext-in-RAM budget on UX latency. The escape hatch is &lt;em&gt;architectural&lt;/em&gt;: a hardware-isolated broker process. Pluton-anchored vTPM key unwrap [@ms-learn-pluton], Credential Guard&apos;s LSAISO pattern [@ms-learn-credential-guard], DPAPI-NG with the right protection descriptor [@ms-learn-dpapi-ng-descriptors] -- the OS primitives all exist.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; There is no cryptographic primitive that lets a process autofill plaintext without holding it. The only escape hatch is an architectural one: a higher-privileged broker. Microsoft already ships the broker primitives -- DPAPI-NG, Credential Guard, Pluton. They are not wired into Chromium.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The aha moment the rest of the article was built to deliver: the Ronning PoC is not a &quot;bug&quot; in any meaningful sense. The structural question is whether Microsoft should ship the architectural primitive -- which they already have, in DPAPI-NG and Credential Guard -- but have not wired into Chromium&apos;s password store. The &quot;by design&quot; response is technically true and politically convenient simultaneously. Both are correct readings.&lt;/p&gt;
&lt;p&gt;Both lower bounds are tight or near-tight today. The PSI side is essentially solved engineering; the endpoint side is essentially solved policy and unsolved deployment. The open questions are about which side we invest in next.&lt;/p&gt;
&lt;h2&gt;10. Open problems&lt;/h2&gt;
&lt;p&gt;Four open problems, framed as research directions Microsoft, Apple, and Google have not jointly committed to.&lt;/p&gt;
&lt;h3&gt;Open problem 1: post-quantum PSI and OT extension&lt;/h3&gt;
&lt;p&gt;Every deployed breach-checking protocol today rests on assumptions &lt;a href=&quot;https://paragmali.com/blog/post-quantum-cryptography-on-windows-the-thirty-year-migrati/&quot; rel=&quot;noopener&quot;&gt;Shor&apos;s algorithm&lt;/a&gt; breaks. The OPRFs in Apple PSM and Google Password Checkup rely on discrete log over elliptic curves; the HE-PSI in Edge Password Monitor relies on BFV-on-classical-parameters; Paillier (historic, FNP04) relies on integer factorisation. Harvest-now-decrypt-later exposure on durable transcripts is the near-term migration question: an adversary capturing PSI transcripts today and storing them until a cryptographically relevant quantum computer arrives could, in principle, reconstruct the queries.&lt;/p&gt;
&lt;p&gt;Lattice-based OT extension exists at currently-secure parameters, at roughly $10\times$ the communication of IKNP per OT in early prototypes. Whether the breach-checking deployments at Microsoft, Apple, and Google migrate on the same timeline as the rest of TLS (the IETF post-quantum-handshake transition) is an open coordination problem.&lt;/p&gt;
&lt;h3&gt;Open problem 2: multi-party breach corpora&lt;/h3&gt;
&lt;p&gt;No production deployment of a $&amp;gt;2$-party breach-checking service exists. HIBP, Google, Apple, and Microsoft each hold corpora that overlap but contain unique breaches. Consolidating them privately -- so a query gets the union of all four corpora&apos;s match metadata without any one provider learning more than their own corpus contributed -- would meaningfully improve detection.&lt;/p&gt;
&lt;p&gt;The academic literature on multi-party PSI is substantial and growing, but the engineering and the governance work has not been done. Each provider has a different commercial relationship with the breach dataset, a different legal posture, and a different operational interest in their corpus being canonical. The cryptographic primitive is the easy part.&lt;/p&gt;
&lt;h3&gt;Open problem 3: sub-linear sender-side amortisation&lt;/h3&gt;
&lt;p&gt;The $\Omega(n_S)$ sender-side computation lower bound is &lt;em&gt;per query&lt;/em&gt;. For a service serving billions of queries against a static $S_S$, can per-query cost be amortised across queries via a preprocessing step the sender pays once?&lt;/p&gt;
&lt;p&gt;Cong et al. 2021 [@cong-2021] reduces constants substantially and pushes the practical envelope. Sub-linear &lt;em&gt;asymptotic&lt;/em&gt; sender-side cost is open. The information-theoretic barrier is real -- the sender must touch any element that could be in the receiver&apos;s query -- but the &lt;em&gt;expected&lt;/em&gt; cost over many queries against a static corpus admits a more aggressive analysis under the right access patterns.&lt;/p&gt;
&lt;h3&gt;Open problem 4: hardware-broker browser secret stores&lt;/h3&gt;
&lt;p&gt;The endpoint architectural problem. Migrate Edge, Chrome, and Brave from &quot;process-RAM plaintext&quot; to &quot;OS-broker (plaintext never crosses into the browser)&quot; using DPAPI-NG with a broker-PPL protection descriptor or a Credential Guard-style trustlet.&lt;/p&gt;
&lt;p&gt;WebAuthn and passkeys offer this property already -- the platform authenticator holds the private key, and the browser receives signed assertions without ever seeing the secret. But passkeys require per-site enrollment that traditional username-password sites have not adopted at scale; the long tail of legacy login forms will remain on saved-passwords-as-strings for years.&lt;/p&gt;
&lt;p&gt;The Windows Credential Manager offers the broker property for &lt;em&gt;Windows-app&lt;/em&gt; credentials -- but it is not wired into Chromium for &lt;em&gt;browser&lt;/em&gt; credentials. The engineering work is real; the cryptographic work is essentially trivial. Whether and when Microsoft, Google, or Brave commit to it is the question.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Open problem&lt;/th&gt;
&lt;th&gt;What&apos;s been tried&lt;/th&gt;
&lt;th&gt;Current best&lt;/th&gt;
&lt;th&gt;Why it matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Post-quantum PSI&lt;/td&gt;
&lt;td&gt;Lattice-based OT, ring-LWE OPRFs&lt;/td&gt;
&lt;td&gt;Prototype-grade; 10x classical at ~secure parameters&lt;/td&gt;
&lt;td&gt;Harvest-now-decrypt-later on PSI transcripts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-party breach corpora&lt;/td&gt;
&lt;td&gt;Multi-party PSI literature (e.g., Kolesnikov et al. CCS 2017)&lt;/td&gt;
&lt;td&gt;Academic constructions; no production deploy&lt;/td&gt;
&lt;td&gt;Each provider&apos;s corpus has unique recall&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sub-linear sender cost&lt;/td&gt;
&lt;td&gt;Cong et al. 2021 constants reduction&lt;/td&gt;
&lt;td&gt;Linear $\Omega(n_S)$ per query&lt;/td&gt;
&lt;td&gt;$5 \times 10^9$ corpus, billions of queries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hardware-broker secret stores&lt;/td&gt;
&lt;td&gt;WebAuthn / passkeys; DPAPI-NG, Credential Guard&lt;/td&gt;
&lt;td&gt;Standards exist; wiring into browsers is missing&lt;/td&gt;
&lt;td&gt;The Ronning PoC threat model&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

Open Chromium&apos;s process tree on Windows (Task Manager: Details, group by Path) and look for the `Google Chrome.exe` (or `msedge.exe`) process running with the `--type=` argument absent -- that&apos;s the parent. App-Bound Encryption binds the DPAPI unwrap to that exact parent process&apos;s signature, so a same-user attacker masquerading as Chrome cannot ask DPAPI to unwrap Chrome&apos;s data even with the right user identity. The architectural primitive is sitting in Chrome&apos;s source tree as of July 2024 [@google-chrome-abe-2024]; the equivalent control for Edge&apos;s password store has not shipped.
&lt;p&gt;These four open problems share a structure: each would require coordination across multiple vendors and across the cryptography / platform / browser boundary. None is research-blocked. All are governance-blocked.&lt;/p&gt;
&lt;h2&gt;11. Practical guide&lt;/h2&gt;
&lt;p&gt;What should you do this week?&lt;/p&gt;
&lt;h3&gt;Users&lt;/h3&gt;
&lt;p&gt;If your Edge browser is your password manager and you are on a single-user laptop you control end-to-end, the Ronning PoC&apos;s threat model is &quot;an attacker who can run code as you on your own machine.&quot; If that happens, the attacker is already in a strong position regardless of how Edge holds passwords -- they can keylog the next login, screenshot anything you autofill, or install a malicious browser extension. The marginal risk of the plaintext-RAM design on a single-user laptop is real but bounded.&lt;/p&gt;
&lt;p&gt;If you share a Windows host -- a family PC with multiple accounts, a small-business workstation several employees sign into, a domain-joined laptop on which IT has administrative access -- the calculus changes. Any same-user process can read your Edge plaintext during your session. Any administrator can read it across sessions (the PoC&apos;s &quot;Administrator can access other users&apos; Edge processes&quot; mode). The case for moving saved credentials out of Edge into a dedicated password manager (1Password, Bitwarden, KeePass) is structurally stronger here.&lt;/p&gt;
&lt;p&gt;A dedicated password manager usually still keeps plaintext in &lt;em&gt;its&lt;/em&gt; own process RAM during autofill -- this is the §9 lower bound asserting itself. The difference is the size of the plaintext-in-RAM window: dedicated password managers tend to require an explicit unlock and re-lock after a configurable idle period. Edge&apos;s window is the entire browser session.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; On a multi-user Windows machine -- RDS, AVD, Citrix, a family computer with separate accounts -- disable Edge&apos;s password manager via the &lt;code&gt;PasswordManagerEnabled&lt;/code&gt; group policy and route users to an out-of-process credential broker (1Password&apos;s CLI integration, Bitwarden&apos;s desktop helper, or the platform Credential Manager).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Windows admins&lt;/h3&gt;
&lt;p&gt;The two relevant Edge enterprise policies are documented on Microsoft Learn:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;PasswordManagerEnabled&lt;/code&gt;&lt;/strong&gt; [@ms-learn-passwordmanagerenabled] -- turns Edge&apos;s saved-passwords feature on or off entirely. On a multi-user host with sensitive data, the right value is &lt;code&gt;0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;PasswordMonitorAllowed&lt;/code&gt;&lt;/strong&gt; [@ms-learn-edge-pm] -- controls whether Password Monitor&apos;s breach-checking PSI runs at all. The default is &quot;user-controlled&quot;; in a managed enterprise, you may want to mandatorily enable it (independent of whether the password manager itself is enabled, because Password Monitor can check passwords you type into login forms, not just ones you have saved).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For RDS, AVD, and Citrix environments specifically, the threat model is structurally worse than a single-user laptop. Multiple users share a single Windows host. Their Edge profiles are isolated by Windows ACLs but their &lt;em&gt;processes&lt;/em&gt; are not isolated against an administrator. The PoC&apos;s &quot;Administrator privileges can access other users&apos; Edge processes&quot; mode is exactly the privilege available to a session-host administrator who has been compromised, or to a malicious tenant who escalates locally.&lt;/p&gt;

On a shared-tenant Windows host, the question is not whether same-user LCE will occur -- it is structurally more common than on a single-user laptop -- but how containable it is when it does. Saved browser credentials are an outsized lever for an attacker who pivots laterally: a single compromised user account on a session-host can yield every saved corporate credential for that user, and an administrator escalation can yield every saved credential for every user on the host. The hardening recommendation is to disable browser-based password management entirely (`PasswordManagerEnabled=0`) on session-host images, document an approved credential broker for your environment (Windows Credential Manager for native apps; an enterprise password manager with broker integration for browsers), and audit Edge profile directories on session-host images for stale `Login Data` SQLite files left over from earlier deployments.
&lt;h3&gt;Developers&lt;/h3&gt;
&lt;p&gt;If you ship a component that handles credentials, the design lesson from §9 is not &quot;never hold plaintext&quot; -- you cannot avoid it without an OS-level broker -- but &quot;minimise the plaintext-in-RAM window.&quot;&lt;/p&gt;
&lt;p&gt;The Chrome App-Bound Encryption pattern from July 2024 [@google-chrome-abe-2024] is a template: bind your at-rest key unwrap to a verified process identity so an attacker who exfiltrates your wrapped data cannot trivially unwrap it from a different process. If you must hold plaintext in the parent process for the lifetime of the session (the Edge design), make the trade explicit in the threat model documentation and ensure operations consuming the plaintext are auditable.&lt;/p&gt;
&lt;p&gt;If you can architecturally afford a broker, do it. The IPC cost is real (low-microsecond per call) but small compared to the operational reduction in incident severity. WebAuthn / passkeys are the long-term destination for credentials; the broker pattern is the short-term destination for everything else.&lt;/p&gt;
&lt;h2&gt;12. Frequently asked questions&lt;/h2&gt;

Yes, at rest on disk. DPAPI wraps the symmetric key that encrypts Edge&apos;s `Login Data` SQLite file under a key chain rooted in the user&apos;s password. When the user is logged out (or the machine is powered off), the on-disk blob is opaque to anyone who does not have the user&apos;s DPAPI credentials. The protection ends the moment Edge unwraps the DPAPI blob into process memory, which happens during browser launch or the first password-feature activation. Once unwrapped, the credentials sit in `msedge.exe`&apos;s heap until the process exits, and `ReadProcessMemory` from any same-user process reads them as plaintext. DPAPI is an at-rest control, not an in-memory one.

Partially. If Edge ran as a protected process at an appropriate signature level, only an antimalware-PPL-elevated process could open it for `ReadProcessMemory`, which would substantially raise the bar against a same-user attacker. Browser-process PPL has implications for every loaded DLL (each must be signed at or above the host&apos;s PPL level) and every extension API the renderer expects to call. Chrome and Brave have not adopted PPL for the browser process either. Microsoft has the option; they have not used it. PPL would address the same-user-LCE concern but not the administrator-across-sessions concern.

No. Credential Guard isolates LSASS-derived secrets (NTLM hashes, Kerberos tickets, cached credentials) into the LSAISO trustlet running under Virtualization-Based Security, which is unreachable from the normal-world kernel let alone normal-world user-mode processes. It does not cover browser-owned secrets. Saved Edge credentials live in `msedge.exe`&apos;s heap, not in LSASS, and Credential Guard does not extend protection to arbitrary user-mode application secret stores.

No, in the strict cryptographic sense. K-anonymity leaks the bucket index by design -- the server learns a 20-bit (HIBP), 15-bit (Apple), or 16-bit (Edge shard) prefix of the hash being queried, which carries non-trivial information about which password the client is asking about. A proper PSI protocol leaks nothing beyond the intersection itself. The argument for k-anonymity is that the bucket is large enough -- on the order of hundreds to thousands of possible hashes per bucket -- that the residual information is not actionable for the threats most users face. It is a precise statement of &quot;a small leak in exchange for vast practical efficiency&quot;; the cost is documented and bounded, and that is why every deployed service uses some variant of it. But it is not zero-leak.

Threat-model differences and SGX&apos;s well-documented side-channel literature (see the §6 Aside for the four-attack chronology). For a breach-checking service whose threat model is &quot;the corpus must not leak from inside Microsoft,&quot; HE-PSI offers a clean cryptographic argument that does not depend on any TEE&apos;s silicon-level security claims. The MSR Cryptography and Privacy group had been publishing the relevant HE-PSI papers since 2017 and shipping the SEAL library publicly since 2018, so the substrate was in-house. The cost is real (orders of magnitude more compute than an SGX enclave) but tractable at the sharded scale Edge Password Monitor operates at. The trade is reasonable, and it is documented in the MSR blog [@msr-password-monitor-2021].

AMSI evasion. The Antimalware Scan Interface scans .NET 4.8+ assemblies before execution; .NET 3.5 predates AMSI&apos;s API surface entirely. A C# program targeting .NET 3.5 will run on any modern Windows with the legacy framework installed (which is most of them, because .NET 3.5 is shipped as a Windows feature) and will not be subject to the same managed-runtime scanning that 4.8+ assemblies are. The current GitHub README says &quot;.NET Framework 4.8.1 (changed from 3.5 originally)&quot; [@ronning-github] -- likely to ease running on a clean modern Windows -- but the original .NET 3.5 framing was the deliberate AMSI-evasion choice. The sibling AMSI post in this series explains the scanning architecture in detail.

Per the researcher&apos;s claim and the PCWorld relay, no -- see §7 for the decrypt-on-autofill contrast and Chrome&apos;s App-Bound Encryption hardening [@pcworld-pippig-2026][@google-chrome-abe-2024]. The observable difference is direct: a `ReadProcessMemory`-based scrape of an idle Chrome process returns markedly less than the same scrape of an idle Edge process.

Yes (with caveats). See §7&apos;s MSRC-servicing-criteria Aside for the full framing [@msrc-servicing-criteria]: the short answer is that the position is internally consistent with a decade of MSRC policy and with the §9 architectural lower bound, but it concedes the same-user LCE threat model and shifts defence onto endpoint controls (antivirus, application-control policies, PPL on antimalware processes only) that may not exist on the user&apos;s machine. The architectural primitive that would close the gap (an OS broker) exists on Windows but is not wired into Chromium.
&lt;p&gt;The PSI on the wire is real. The plaintext-RAM concession is also real. Both are statements about which threat model the Edge product team is defending against, and the apparent contradiction in the title disappears once you read them as such.&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;edges-two-password-cryptographies&quot; keyTerms={[
  { term: &quot;Private Set Intersection (PSI)&quot;, definition: &quot;A two-party cryptographic protocol that computes the intersection of two sets without revealing anything else.&quot; },
  { term: &quot;Oblivious Transfer (OT)&quot;, definition: &quot;A primitive in which a sender holds two messages, a receiver picks one, and neither learns the other&apos;s choice or the unsent message.&quot; },
  { term: &quot;OT extension&quot;, definition: &quot;Two-phase protocol that turns kappa public-key OTs into m symmetric-cost OTs, collapsing per-OT cost by orders of magnitude.&quot; },
  { term: &quot;Oblivious Pseudorandom Function (OPRF)&quot;, definition: &quot;Two-party protocol where the receiver learns F_k(x) without revealing x to the sender or learning k.&quot; },
  { term: &quot;Pseudorandom Correlation Generator (PCG)&quot;, definition: &quot;Primitive that locally expands a short shared seed into long correlated random strings, used to make Silent OT communication-free post-seed.&quot; },
  { term: &quot;Homomorphic encryption (HE / SWHE / FHE)&quot;, definition: &quot;Encryption supporting operations on ciphertexts that decrypt to operations on plaintexts; SWHE is bounded depth, FHE is unbounded via bootstrapping.&quot; },
  { term: &quot;Cuckoo hashing&quot;, definition: &quot;Hashing with k candidate bins per element and displacement, achieving O(1) lookup at high load -- the partitioning trick under CLR17 and CHLR18.&quot; },
  { term: &quot;k-anonymity (password monitoring)&quot;, definition: &quot;A precise small information leak: each query is consistent with at least k possible passwords sharing the bucket prefix.&quot; },
  { term: &quot;Data Protection API (DPAPI)&quot;, definition: &quot;Windows facility that wraps blobs under user-derived keys; an at-rest control, not an in-process-memory control.&quot; },
  { term: &quot;App-Bound Encryption (Chrome, July 2024)&quot;, definition: &quot;Chrome control that binds DPAPI unwrap of saved data to the verified Chrome process identity, blocking same-user impersonation attacks.&quot; }
]} questions={[
  { q: &quot;Why does the DH meet-in-the-middle PSI protocol fail at breach-checking scale?&quot;, a: &quot;It costs O(|S_B|) group exponentiations per query, leaks set cardinality on both sides, and provides no labeled-PSI variant.&quot; },
  { q: &quot;What three engineering moves let CLR17 revive FNP04&apos;s polynomial-roots PSI?&quot;, a: &quot;(1) BFV SWHE replaces Paillier for slot-packed homomorphic evaluation, (2) Cuckoo hash partitioning splits the giant polynomial into per-bin polynomials, (3) partition-and-evaluate bounds server work to O(|S_S| log |S_R|).&quot; },
  { q: &quot;What does the OPRF preprocessing layer add to Edge Password Monitor&apos;s bare HE-PSI?&quot;, a: &quot;It prevents a malicious client from brute-forcing the server&apos;s corpus offline; the client cannot evaluate F_k(x) without server interaction.&quot; },
  { q: &quot;What does the EdgeSavedPasswordsDumper PoC require to read Edge passwords as cleartext?&quot;, a: &quot;Same-user OpenProcess + ReadProcessMemory on the parent msedge.exe. No kernel exploit, no admin (against same-user processes), no DPAPI bypass.&quot; },
  { q: &quot;Why is &apos;no cryptographic primitive closes the plaintext-RAM gap&apos; the structural claim of section 9?&quot;, a: &quot;Using a plaintext value requires holding it; the only escape hatch is moving the holder to a higher-privileged broker process, which is an architectural choice, not a cryptographic one.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>private-set-intersection</category><category>homomorphic-encryption</category><category>microsoft-edge</category><category>password-security</category><category>threat-modeling</category><category>dpapi</category><category>cryptography</category><author>noreply@paragmali.com (Parag Mali)</author></item></channel></rss>