58 min read

Edge's Two Password Cryptographies: A Beautiful PSI on the Wire, and Plaintext RAM by Design

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.

Permalink

1. Two cryptographies, one product, one week

On January 21, 2021, Microsoft Research's Cryptography and Privacy group announced Edge's Password Monitor ships a homomorphic-encryption-based Private Set Intersection protocol built on Microsoft SEAL. The post is explicit that this is "possible due to pioneering cryptography research and technology incubation done here at Microsoft Research," that it is the result of a collaboration "between [the] Cryptography and Privacy Research Group, and Edge product team," and that the protocol descends from two specific papers: "Fast Private Set Intersection from Homomorphic Encryption" and "Labeled PSI from Fully Homomorphic Encryption with Malicious Security" [1]. It is, by a comfortable margin, the first production consumer deployment of homomorphic encryption in a browser.

On May 4, 2026, at 14:29:51 UTC, a researcher in Oslo named Tom Joran Sonstebyseter Ronning posted to X: "Microsoft Edge loads all your saved passwords into memory in cleartext -- even when you're not using them" [2]. He linked a GitHub repository called EdgeSavedPasswordsDumper: roughly 500 lines of C# that opens a handle to the parent msedge.exe process and reads every saved credential as plaintext, with no kernel exploit, no admin (against same-user processes), and no DPAPI bypass [3]. The README confirms the behaviour is present in "any Edge versions that's Chromium based (from version 79 and newer, including 147.0.3912.98 and any future version)" [3]. Two days later, on May 6, 2026, Microsoft told Forbes that the in-memory behaviour is "an expected feature of the application" and "by design" [4].

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: "passwords."

This article argues they are about two different threat models, and the apparent contradiction in the headline disappears once you separate them.

Private Set Intersection (PSI)

A two-party cryptographic protocol in which Alice holds a set SAS_A, Bob holds a set SBS_B, and they jointly compute SASBS_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's set beyond what the intersection implies.

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' desktops by 2021 [1]. 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 [3]. Microsoft's official position is that local code execution on the user's machine is "outside the threat model" of the browser password store -- a position that is internally consistent with a decade of MSRC policy and also true [4].

The thesis: "password security" is at least two threat models, 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.

Ctrl + scroll to zoom
The two-thread timeline: PSI's 40-year academic lineage on top, the browser credential-storage architectural choice on the bottom, converging in the same msedge.exe binary in 2026.

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 forty years before Edge Password Monitor existed.

2. Why Private Set Intersection exists at all

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.

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: 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's breach corpus -- and they want Microsoft to learn nothing about the passwords that do not. (Throughout this article the "five billion" figure is the author's 2026 forward projection of Microsoft's compromised-credential corpus; the contemporaneous Microsoft Research figure used in the 2021 Password Monitor announcement is four billion [1], and the §3 sidenote spells out the inference.)

That framing did not exist in 1986. The original motivation was much weirder.

The 1986 paper

Catherine Meadows, then at the U.S. Naval Research Laboratory, published "A More Efficient Cryptographic Matchmaking Protocol for Use in the Absence of a Continuously Available Third Party" at the 1986 IEEE Symposium on Security and Privacy [5][6]. The titular "matchmaking" 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.

Meadows'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.

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 [7], and forty years before her protocol's intellectual descendants would ship in a consumer browser.

The 1999 revival

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 "Enhancing Privacy and Trust in Electronic Communities" was published at the First ACM Conference on Electronic Commerce [8]. 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 "DH meet-in-the-middle" or just "the Huberman-Franklin-Hogg protocol" -- 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 [9].

What had to exist before

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.

The first such mapping landed in 2018 with HIBP's k-anonymity API and the cluster of academic and industry PSI deployments that followed [10]. 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.

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.

3. Early approaches: DH meet-in-the-middle and FNP04

Let us walk the DH meet-in-the-middle protocol step by step. Alice holds a set SAS_A. Bob holds a set SBS_B. Both parties agree on a Diffie-Hellman group GG of prime order qq with generator gg, and on a cryptographic hash function H:{0,1}GH: \{0,1\}^* \to G that maps set elements into the group. Alice picks a private exponent aZqa \in \mathbb{Z}_q; Bob picks bb.

The protocol proceeds in two rounds:

  1. Alice computes {H(x)a:xSA}\{H(x)^a : x \in S_A\}, shuffles, and sends to Bob.
  2. Bob computes {H(y)b:ySB}\{H(y)^b : y \in S_B\}, shuffles, and sends to Alice.
  3. Alice exponentiates every value Bob sent her by aa, producing {H(y)ab:ySB}\{H(y)^{ab} : y \in S_B\}. She sends this set back to Bob in the order Bob originally sent his {H(y)b}\{H(y)^b\}, so Bob can index by his own set.
  4. Bob exponentiates Alice's first-round values by bb, producing {H(x)ab:xSA}\{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.)
  5. Both parties now hold the same doubly-blinded set for both sides. Equal underlying elements collide; unequal ones do not. They intersect locally.
Ctrl + scroll to zoom
DH meet-in-the-middle PSI: each party blinds their set with a private exponent, exchanges the blinded set, and the equal-blinded-value match reveals the intersection without revealing anything else.

Why this is right. Under the Decisional Diffie-Hellman (DDH) assumption in GG, the doubly-blinded values H(x)abH(x)^{ab} for xSASBx \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.

JavaScript Toy DH meet-in-the-middle PSI in ~30 lines
// 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 => {
// toy hash: deterministic map string -> [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) => {
let r = 1n, b = base % mod, e = exp;
while (e > 0n) {
  if (e & 1n) r = (r * b) % mod;
  b = (b * b) % mod;
  e >>= 1n;
}
return r;
};
const S_A = ["alice-at-example.com", "bob-at-example.com", "carol-at-example.com"];
const S_B = ["dave-at-example.com", "bob-at-example.com", "carol-at-example.com"];
const a = 0xC0FFEEn, b = 0xBADCAFEn;
const A1 = S_A.map(x => expMod(H(x), a, p));   // Alice -> Bob
const B1 = S_B.map(y => expMod(H(y), b, p));   // Bob -> Alice
const A2 = A1.map(v => expMod(v, b, p));       // Bob blinds Alice's set
const B2 = B1.map(v => expMod(v, a, p));       // Alice blinds Bob's set
// Reveal intersection by matching doubly-blinded values
const setA2 = new Set(A2.map(String));
const intersection = S_B.filter((_, i) => setA2.has(String(B2[i])));
console.log("Intersection:", intersection);

Press Run to execute.

The protocol does work. It gives semi-honest security under DDH and costs O(SA+SB)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.

The three things that go wrong at scale

For breach checking, the protocol breaks in three documented ways.

Set-cardinality leakage. The shuffled lists Alice and Bob send each other have lengths SA|S_A| and SB|S_B|. Bob learns precisely how many passwords Alice has saved; Alice learns precisely how big Bob'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.

Online-cost asymmetry. The server pays O(SB)O(|S_B|) exponentiations per client query. At the five-billion-element scale of Microsoft's compromised-credential corpus, no realistic group exponentiation cost makes this feasible per query: even at 100 microseconds per exponentiation (optimistic for q=256|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.

No labeled variant. The protocol returns set membership, not associated metadata. Edge Password Monitor wants to tell you "this credential appeared in breach X" -- 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.

FNP04: the right idea, wrong substrate

The algebraic alternative arrived in 2004 with Freedman, Nissim, and Pinkas's "Efficient Private Matching and Set Intersection" at EUROCRYPT [11]. The idea is gorgeous. Alice encodes her set SA={x1,,xn}S_A = \{x_1, \dots, x_n\} as the polynomial whose roots are her set:

p(z)=i=1n(zxi)p(z) = \prod_{i=1}^{n} (z - x_i)

Alice encrypts each coefficient of pp under an additively-homomorphic encryption scheme (Paillier, in the paper). She sends the encrypted coefficients to Bob. Bob homomorphically evaluates p(y)p(y) for every element yy of his set SBS_B and returns the encrypted results. If ySAy \in S_A, then p(y)=0p(y) = 0, and after decryption Alice sees a zero in the corresponding position. If ySAy \notin S_A, then p(y)p(y) is a non-trivial polynomial evaluation that, randomized correctly, decrypts to a uniform value Alice cannot interpret.

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 Zn2\mathbb{Z}^*_{n^2} and are 2n2 \cdot |n| bits each [12] (2048 bits for FNP04's n=1024|n| = 1024 default; 4096 bits for the n2048|n| \geq 2048 that modern security demands). Paillier homomorphic evaluation needs full-size modular exponentiation per coefficient, and the server compute scales as O(SASB)O(|S_A| \cdot |S_B|). At Edge Password Monitor'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(SASB)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 [13], with Paillier replaced by BFV-style somewhat-homomorphic encryption and a partition-and-evaluate trick that fixes the O(SASB)O(|S_A| \cdot |S_B|) blow-up. The structure survives; the substrate gets swapped.
ProtocolEraServer costCommunicationVerdict at 5B-element scale
DH meet-in-the-middle [8]1999$O(S_B)$ DH exponentiations
FNP04 [11]2004$O(S_A\cdot
(preview) HE-PSI on BFV [13]2017$O(S_B\log

FNP04'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 every PSI in the literature can ride on it.

4. The evolution: oblivious transfer extension

Here is the central fact that drove a decade of cryptographic engineering: every PSI protocol that scales eventually reduces to "many oblivious transfers." 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 "many OTs" can become.

Oblivious transfer (OT)

A two-party primitive. In 1-out-of-2 OT, the sender holds two messages (m0,m1)(m_0, m_1), the receiver chooses a bit bb, and after the protocol runs the receiver learns mbm_b while the sender learns nothing about bb. 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.

OT extension

A two-phase protocol that performs mm OTs at the cost of κ\kappa "base" OTs (typically κ=128\kappa = 128, implemented with public-key crypto) plus O(m)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 mm.

Generation 1: IKNP03

In 2003, Yuval Ishai, Joe Kilian, Kobbi Nissim, and Erez Petrank published "Extending Oblivious Transfers Efficiently" at CRYPTO 2003 [14].

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 the OT extension: start with κ\kappa "base" 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)O(m) hash-function calls, produces mm effective OTs. The base cost stays fixed at κ\kappa public-key operations; the per-OT marginal cost collapses to a few hash invocations.

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 "research artifact" and "this protocol can ship."

IKNP03 has no IACR ePrint preprint; ePrint 2003/052 is a different paper by different authors (Klima, Pokorny, Rosa). Cite Springer LNCS only [14].

Generation 2: KOS15

IKNP03 is secure against a semi-honest adversary -- one who follows the protocol but tries to learn extra information from the transcript. Real-world deployments often need active security: protection against an adversary who deviates to extract information or bias the output.

In 2015, Marcel Keller, Emmanuela Orsini, and Peter Scholl published "Actively Secure OT Extension with Optimal Overhead" [15]. The construction adds a correlation-check phase on top of IKNP03 that catches active deviations with overwhelming probability. The paper's own abstract: "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." 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 "optimal overhead" in the title is the claim that this margin vanishes as the OT count grows.

After KOS15, "active security is free" 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.

Generation 3: Silent OT

In 2019, a six-author collaboration -- Elette Boyle, Geoffroy Couteau, Niv Gilboa, Yuval Ishai, Lisa Kohl, and Peter Scholl -- published "Efficient Pseudorandom Correlation Generators: Silent OT Extension and More" at CRYPTO 2019 [16]. The construction replaces the communication-heavy IKNP/KOS phase with a Pseudorandom Correlation Generator (PCG): the two parties exchange a few-kilobyte seed and locally expand it into millions of correlated OTs.

Pseudorandom Correlation Generator (PCG)

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 "consume" 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.

The numerical impact this time is bandwidth. 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 "Compressing Vector OLE" by Boyle, Couteau, Gilboa, and Ishai [17] laid the algebraic foundation.

For Edge Password Monitor'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.

The OPRF-PSI plateau: KKRT16

Pure OT-extension is one substrate; the other is the Oblivious Pseudorandom Function.

Oblivious Pseudorandom Function (OPRF)

A two-party protocol in which the sender holds a key kk, the receiver holds an input xx, and after the protocol the receiver learns Fk(x)F_k(x) while the sender learns nothing about xx. 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.

In 2016, Vladimir Kolesnikov, Ranjit Kumaresan, Mike Rosulek, and Ni Trieu published "Efficient Batched Oblivious PRF with Applications to Private Set Intersection" at CCS 2016 [18]. The paper builds a batched OPRF directly on top of KOS-style OT extension. The reported benchmark: intersecting two 2202^{20}-element sets on a LAN took about 3.8 seconds total. For several years, KKRT16 was the deployment-grade symmetric-PSI protocol.

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 asymmetric PSI, the OT-extension lineage hits a wall the next generation has to climb.

Ctrl + scroll to zoom
OT extension as the substrate that all modern PSI rides on. Public-key base OTs are amplified by symmetric crypto into millions of effective OTs; OPRF-PSI (KKRT16) and HE-PSI (CLR17, CHLR18) both layer on top.

5. The breakthrough: HE-based PSI

Asymmetric PSI requires that the server's heavy compute stays on the server, and that the client send only a tiny encrypted query whose size is independent of SB|S_B|. That is exactly what fully homomorphic encryption -- or, more precisely, somewhat-homomorphic encryption -- can offer.

Homomorphic encryption (HE), SWHE, FHE

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 [19], is the SWHE variant Edge Password Monitor uses; FHE is the popular term but the actual deployed circuit depth fits comfortably within SWHE.

CLR17: the cost curve flips

In 2017, Hao Chen, Kim Laine, and Peter Rindal published "Fast Private Set Intersection from Homomorphic Encryption" at CCS 2017 [13]. The construction is a clean revival of FNP04's polynomial-roots idea, with three engineering moves that fix every reason FNP04 was infeasible.Move 1: SWHE instead of Paillier. 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.

Move 2: Cuckoo hash partitioning. The receiver Cuckoo-hashes its set SRS_R into bins. The sender hashes each element of SSS_S to the same set of bins. Instead of one giant polynomial whose roots are all of SSS_S, the sender builds one small polynomial per bin -- typically a few thousand bins, each holding a few hundred elements.

Cuckoo hashing

A hashing scheme that uses kk hash functions and inserts each element into one of kk candidate bins, displacing existing occupants if necessary (the displaced element finds another of its candidate bins). Cuckoo hashing achieves O(1)O(1) worst-case lookup; the achievable load factor depends on the number of hash functions and the bucket size -- roughly 49% with k=2k=2 (the original Pagh-Rodler 2001 construction [20]), roughly 91% with k=3k=3, and higher with a stash of evicted elements or k4k \geq 4. CLR17 and CHLR18 use parameter choices in the high-load regime. In CLR17, Cuckoo hashing pairs the receiver's set with the sender's set so that two equal elements end up in the same bin with overwhelming probability.

Move 3: Partition-and-evaluate. The receiver encrypts its bins under BFV and sends them. The sender homomorphically evaluates its per-bin polynomial at the encrypted receiver's bin. Because of SIMD slot packing, each bin's polynomial is evaluated in parallel across all slots, and the sender's total work is O(SSlogSR)O(|S_S| \log |S_R|) FHE operations instead of FNP04's O(SRSS)O(|S_R| \cdot |S_S|).

The headline benchmark from the paper, on the MSR publication page: "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" [21]. Communication scales linearly in the small set and logarithmically in the large set. The cost curve is finally right.

Ctrl + scroll to zoom
Edge Password Monitor's on-the-wire dance: an OPRF preprocessing round binds the client's query to the server's secret key, then the BFV ciphertext flies one-way for sub-linear homomorphic matching against a sharded breach corpus.

CHLR18: labeled, malicious, deployable

The next year, the same authors plus Zhicong Huang published "Labeled PSI from Fully Homomorphic Encryption with Malicious Security" at CCS 2018 [22]. The paper adds three production-grade properties.

Labels. Each element in the server's set can carry an associated label (which breach, when, severity). When the receiver finds a match, they also recover the label.

Malicious security. 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's corpus offline (the client cannot evaluate Fk()F_k(\cdot) without server interaction) and provides the malicious-security guarantee.

Arbitrary-length items. The protocol handles long inputs (full URLs plus usernames, in the breach-checking case), not just short fixed-width keys.

The headline benchmark: "for an intersection of 2202^{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" [23]. A larger benchmark of 2282^{28} and 1024 takes 12 seconds multithreaded with less than 18 MB of communication.

Cong et al. 2021: the production-grade successor

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: "Labeled PSI from Homomorphic Encryption with Reduced Computation and Communication" [24]. The paper is the basis for Microsoft's open-source APSI library [25], whose README states verbatim that it "provides a PSI functionality for asymmetric set sizes based on the protocol described in eprint.iacr.org/2021/1116" and that it "uses the BFV encryption scheme implemented in the Microsoft SEAL library."

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 [24].

The OPRF wrapping and corpus sharding

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 [1].

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's corpus. With it, every client query passes through Fk()F_k(\cdot) where kk is a server secret. The MSR blog states: "the client communicates with the server to obtain a hash HH of the credential, where HH 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" [1].

Second, corpus sharding. The MSR blog notes that the corpus is sharded by the first two bytes of a username-hash. The blog's verbatim example: "Suppose the database DD consists of 4 billion credentials, then after sharding each subset, it will contain about 60,000 credentials on average." At the article's 2026 5-billion projection the math is the same -- corpus divided by 2162^{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's 15-bit bucketing -- a small information leak (the client reveals which shard their query lives in) in exchange for tractable per-query compute.

Data Protection API (DPAPI)

A Windows facility, introduced in Windows 2000, that encrypts arbitrary blobs under a user-derived key chain (ultimately rooted in the user's password, with hardware-bound variants under DPAPI-NG) and exposes a simple CryptProtectData / CryptUnprotectData API [26]. 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 [1]

The administrator-visible group policy that controls this feature is PasswordMonitorAllowed, documented on Microsoft Learn [27].

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's CPU. The cryptographic case for Edge Password Monitor is auditable down to the published papers and unequivocally well-engineered.

Microsoft has shipped the first production consumer homomorphic-encryption deployment in a browser, against the threat "server-side breach corpus leakage," 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.

6. State of the art: four deployed compromised-credential services

PSI on paper is one thing. PSI in production is another. The "pure PSI" ideal -- both parties learn the intersection and nothing else, no information leaks on either side -- is impractical at planetary scale. Every deployed compromised-credential service in 2026 makes a concession somewhere.

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 "we used a TEE instead of pure crypto" data point.

ServiceProtocol familyWhat's revealed on the wireServer trustBandwidth at scaleDictionary-attack hardening
HIBP Pwned Passwords v3 [28]Pure SHA-1 5-hex-char k-anonymityA 20-bit hash prefix per queryNone (zero-trust API)Trivial (a few KB per query)None on the wire; SHA-1 hash makes corpus searchable
Google Password Checkup [29]k-anonymity + blinded-hash OPRFA small hash prefix per queryHonest-but-curiousTens of KB per queryOPRF prevents corpus enumeration by the client
Apple Password Monitoring [30]EC-based PSM on NIST P-256 + 15-bit bucketA 15-bit prefix + double-blinded EC pointHonest-but-curiousA few hundred KB per query (padded)OPRF + double-blinding + padding-to-fixed-count
Signal contact discovery (2017) [31]SGX enclave + ORAM (no pure crypto)Nothing visible to Signal staffTEE attestationNegligible (single SGX RPC)Enclave isolation rather than crypto hardening
Microsoft Edge Password Monitor [1]HE-PSI on Microsoft SEAL + OPRF + 2-byte shard2-byte username-hash prefix + BFV ciphertextHonest-but-curiousSingle MB-range round tripOPRF binds queries to server key; HE prevents transcript leaks

HIBP Pwned Passwords v3: the k-anonymity baseline

Troy Hunt's "Have I Been Pwned" launched in 2018 with the help of Junade Ali at Cloudflare; the design is published in two posts, Hunt's "I've Just Launched Pwned Passwords Version 2" and Ali's "Validating Leaked Passwords with k-Anonymity" [10][32]. 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.

k-anonymity (in password monitoring)

A privacy property: each query produces output that is consistent with at least kk other potential queries the client could have made. In the HIBP context, kk 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 "the user has password X" from "the user has password Y" if X and Y share the prefix.

The HIBP corpus serves "18B+ Monthly Requests" against roughly a billion hashes [33]. 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's password if the attacker has independent information narrowing the candidate space.

JavaScript k-anonymity bucket simulator: see what a 20-bit prefix actually leaks
async function sha1Hex(s) {
const buf = new TextEncoder().encode(s);
const hash = await crypto.subtle.digest("SHA-1", buf);
return [...new Uint8Array(hash)].map(b => b.toString(16).padStart(2, "0")).join("").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("Password:", password);
console.log("SHA-1:   ", h);
console.log("Prefix (leaves your device):", prefix);
console.log("Suffix (compared locally):  ", suffix);
console.log("Approx bucket size: ~", Math.round(847_223_402 / (1<<20)), "entries");
}
showBucket("hunter2");

Press Run to execute.

The mental model the runnable above gives is the precise shape of the trade. Every HIBP query says "I am asking about a password whose SHA-1 starts with these 20 bits." There are roughly 2201,048,5762^{20} \approx 1{,}048{,}576 possible prefixes, so each query narrows the server's posterior over your password by exactly that much.

Google Password Checkup: k-anonymity with an OPRF on top

In August 2019, Kurt Thomas and colleagues at Google published "Protecting Accounts from Credential Stuffing with Password Breach Alerting" at USENIX Security [29]. The accompanying blog post on the Google Security Blog announces the deployment [34]. The numbers are familiar at this point: "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" [29].

The protocol upgrades HIBP's k-anonymity baseline with an OPRF preprocessing round: instead of hashing under SHA-1 locally and sending the prefix, the client first obtains Fk(password)F_k(\text{password}) via an OPRF interaction, where kk is a Google-held key. The OPRF output is then bucketed and matched against Google's corpus. The OPRF prevents the client from enumerating Google's corpus offline; the bucketing limits per-query server work.

Apple Password Monitoring: PSM with double-blinding

Apple's protocol is the most cryptographically elaborate of the four. The Apple Platform Security guide is unusually explicit [30][35]. From the guide, verbatim: "a form of cryptographic private set intersection is deployed that compares the users' passwords against a large set of leaked passwords"; the corpus is "approximately 1.5 billion passwords... into 2152^{15} different buckets"; and the protocol uses elliptic-curve PSM on NIST P-256 with a double-blinded structure.

The math, slightly compressed. Let HSWUH_{\text{SWU}} be the Shallue-van de Woestijne-Ulas hash-to-curve.

Google publishes an open-source PSM construction at google/private-membership [36]; Apple's protocol shares the EC double-blinding skeleton. Apple computes a per-corpus-element representation:

Ppw=αHSWU(pw)P_{pw} = \alpha \cdot H_{\text{SWU}}(pw)

where α\alpha is a secret random key known only to Apple. The client computes its query:

Pc=βHSWU(upw)P_c = \beta \cdot H_{\text{SWU}}(u \| pw)

with β\beta chosen randomly per-query. The interaction lets the client recover αHSWU(upw)\alpha \cdot H_{\text{SWU}}(u \| pw) and check it against a 15-bit bucket of PpwP_{pw} values. The double-blinding is the point: α\alpha stays Apple's secret (so the client cannot enumerate); β\beta stays per-query random (so Apple cannot link two queries from the same client).

Apple's PSM defends also against the server learning how many unique passwords a user has, by padding-to-fixed-count with random queries: "if a user has fewer than this number, random passwords are generated and added to the queries to make up the difference" [30]. None of the other four services deploys this defence. The padding cost is the price.

Signal contact discovery: the TEE outlier

In September 2017, Moxie Marlinspike published "Technology Preview: Private Contact Discovery" on Signal's blog [31]. The post is candid about the cost calculation that drove Signal toward Intel SGX rather than pure cryptographic PSI:

"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 [31]

Marlinspike is explicit about the cost calculation: "Doing better is difficult. There are a range of options that don't work... like using bloom filters, encrypted bloom filters, sharded bloom filters." 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 [37].

Microsoft Edge Password Monitor

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:

  1. Two-byte username-hash shard selection (corpus partitioned, sender does work only against tens of thousands of elements per query -- the MSR blog's 2021 example uses 4 billion / 2162^{16} \approx 60,000; the article's 2026 5-billion projection yields \approx 76,000).
  2. OPRF preprocessing (binds queries to a server secret; prevents client-side enumeration).
  3. BFV-encrypted query, evaluated against the Cuckoo-hashed per-bin polynomials, returned as a single ciphertext per shard.
  4. Client decrypts; if matched, decrypts the associated label (the breach metadata).

All four moving parts are described in the MSR blog, the Cong et al. 2021 paper, and the open-source APSI library [1][24][25]. Communication scales with the small client set; sender compute scales with the (sharded) server set. The Microsoft Edge enterprise documentation says the feature "helps Microsoft Edge users protect their online accounts by informing them if any of their passwords are found in an online leak" [27].

Four products, four concessions

ServicePrimary concessionWhat it defends againstWhat it does not
HIBP20-bit prefix leak per queryServer learning the passwordA linkage attack on repeated queries
Google PCUOPRF transcript + prefixClient-side corpus enumerationServer-side query inference if the prefix is rare
Apple PSM15-bit bucket + double-blinding overheadBoth client and server enumeration; query linkageSide-channels on the EC implementation
Signal CDSTEE attestation trustServer-side mass-data exfiltrationSGX side-channel attacks
Edge PM2-byte shard leak + OPRF transcriptAnything short of breach corpus leakage from inside MicrosoftEndpoint compromise -- see §7

Four products. Four different concessions. Each is internally coherent. None of them solves a problem that Tom Joran Sonstebyseter Ronning's PoC will turn out to make trivial.

7. The other half: plaintext RAM "by design"

Now we turn the article inside out.

Everything we have built so far -- IKNP, KOS, KKRT, CLR17, CHLR18, Cong et al., Apple's PSM, Google's k-anonymity wrapping, the entire CCS-grade cryptographic stack inside Edge -- assumes the endpoint is trustworthy. The question Ronning asked on May 4, 2026 is what happens when it is not.

The disclosure

The X post arrived at 14:29:51 UTC on May 4, 2026 [2]: "Microsoft Edge loads all your saved passwords into memory in cleartext -- even when you're not using them." Five hours later the GitHub repository went public, with a complete C# proof-of-concept and a long README [3]. PCWorld picked up the story two days later under the byline of Laura Pippig, summarising Microsoft's response in English [42]. The Norwegian origin, ITavisen, carried the verbatim "by design" rendering and named Ronning's affiliation with the transmission-system operator Statnett [43]. Davey Winder at Forbes reached Microsoft and obtained the official spokesperson statement on May 6, 2026 [4].

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 [43]. The X bio describes "#PenetrationTesting using only tools that are already on the system."

What the PoC does

The C# program is short. OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, ...) against the parent msedge.exe. A walk over committed memory regions via VirtualQueryEx. ReadProcessMemory reads of every region. Pattern matching for stored credential structures. Output: every saved Edge password as plaintext.

The README is explicit on the constraints. "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' Edge processes on the same machine" [3]. 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 msedge.exe's heap ever since.

The tested target is Edge 147.0.3912.98, but the README explicitly generalises: "Any Edge versions that's Chromium based (from version 79 and newer, including 147.0.3912.98 and any future version, as Microsoft won't change this feature)" [3].

What the architectural choice is

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.

Ctrl + scroll to zoom
Edge process memory architecture: DPAPI-encrypted on disk, unwrapped into process heap on launch, readable by any same-user process via ReadProcessMemory.

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 [44]. PCWorld corroborates: "Other password managers, including those that are built into browsers, don't operate in this way -- Ronning says Edge is the only Chromium-based browser he's tested with this behavior" [42].

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's data even if it runs as the same user [45]. Microsoft has the same DPAPI substrate; Edge has not adopted the equivalent control.

The .NET runtime tie-in to AMSI

The PoC's original implementation language is a noteworthy detail. Ronning's README states: ".NET Framework 4.8.1 (changed from 3.5 originally)" [3]. The original .NET 3.5 choice was deliberate. The Antimalware Scan Interface (AMSI) [46] scans .NET 4.8+ assemblies before execution; .NET 3.5 predates AMSI's Amsi* API surface entirely [47].

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.

Microsoft's response, verbatim

"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 [4]

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's machine. In MSRC's published servicing criteria [48], "exploitation requires local code execution" 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. The "by design" framing is consistent with a decade of precedent.

Edge does not have a credential-storage vulnerability. Edge has a credential-storage architectural choice. The choice is to spend the entire browser session'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.

Microsoft'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.

8. Competing approaches: where should the secret store live?

Three architectural positions present themselves, as siblings rather than as a generational ladder:

  1. Browser-as-secret-store, decrypt-on-launch (Edge today). Plaintext-in-RAM window: the entire session. Autofill latency: a memcpy.
  2. Browser-as-secret-store, decrypt-on-autofill (Chrome, Brave). Plaintext-in-RAM window: the autofill RPC. Autofill latency: one DPAPI unwrap per fill (microseconds).
  3. OS-as-secret-broker (the design the Windows Credential Manager and DPAPI-NG already implement for native apps). Plaintext never crosses into the browser's process; a higher-privileged broker holds the plaintext at autofill time and the browser receives a handle, not the secret.
Ctrl + scroll to zoom
Three credential-storage architectures: decrypt-on-launch (Edge), decrypt-on-autofill (Chrome, Brave), and OS-broker (the native Windows Credential Manager pattern). The plaintext-in-RAM window shrinks as the architecture moves right.

Six-axis comparison

AxisDecrypt-on-launch (Edge)Decrypt-on-autofill (Chrome, Brave)OS-as-broker
Plaintext-in-RAM windowFull sessionAutofill RPC (~ms)Never, in the browser process
Autofill latencyMemcpy (nanoseconds)DPAPI unwrap (~10s of microseconds)IPC + broker policy check (~ms)
Same-user-LCE attack surfaceHigh (ReadProcessMemory exposes all)Low (must catch the RPC window)Negligible (no plaintext in the browser)
Memory-scraping forensicsTrivial (any same-user dump works)Hard (must dump during fill)Impossible (no plaintext to dump)
Sync UX with cloud accountStandardStandardStandard (broker handles sync)
Engineering cost to shipAlready shippedAlready shipped (Chromium baseline)High (broker IPC, signed code path, extension renegotiation)

The OS-broker position is not hypothetical. The Windows Credential Manager already provides this property for Windows-app credentials. WebAuthn and passkeys provide it for sites that have adopted the standard. The DPAPI-NG protection descriptors include a WEBCREDENTIALS= variant [26][49]. Pluton-anchored vTPM key unwrap provides a hardware-rooted broker substrate [50]. Credential Guard's LSAISO trustlet is architecturally an isolated secret-broker for LSASS-derived secrets [51].

None of these primitives are wired into Edge'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'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 [45].

What "by design" means structurally

Microsoft can take the "by design" position because they are not wrong about cryptography. They are right about the bound. No protocol can autofill plaintext into a child renderer without some process in the chain holding plaintext at the moment of fill. The architectural question is which process and for how long.

Edge's answer: "the parent browser process, for the entire session." Chrome and Brave's answer: "the parent browser process, for the autofill RPC." The broker design's answer: "a separate, higher-privileged process, for the autofill RPC, and never the browser at all."

All three are valid points in the design space. The question is not "which is right" -- the answer depends on the user's environment -- but "what should the default be for a 2026 consumer browser." 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.

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.

9. Theoretical limits

Two lower bounds, in parallel: one cryptographic (the PSI side), one architectural (the endpoint side).

PSI side: communication and computation lower bounds

The communication lower bound for PSI is folklore, used as the comparison baseline in Pinkas-Schneider-Zohner at USENIX Security 2014 [52]. Informally: any PSI protocol must transmit at least Ω(min(nA,nB)κ)\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(nA,nB)\min(n_A, n_B), and each element identifier needs Ω(κ)\Omega(\kappa) bits of representation to avoid collisions.

Silent OT [16] meets this lower bound up to polylogarithmic factors in the symmetric balanced setting. HE-PSI in the asymmetric setting gets to O(nRlognS)O(n_R \cdot \log n_S) ciphertexts via CLR17's partition-and-evaluate construction [13], which is sublinear in nSn_S -- the breakthrough that makes Edge Password Monitor practical.

The computation lower bound on the sender side is Ω(nS)\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 "cheats" by reducing the effective nSn_S: their 15-bit bucket cuts the per-query work to roughly 1.5B/21546,0001.5\text{B} / 2^{15} \approx 46{,}000 elements. Microsoft's two-byte shard cuts to roughly 5B/21676,0005\text{B} / 2^{16} \approx 76{,}000 elements. The lower bound applies per shard, not per total corpus.

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.

Endpoint side: the "no plaintext in process" lower bound

The cryptographic side is comfortably tight. The endpoint side is much weirder.For a process PP to autofill a credential into a child form, some component in the trust chain must hold the plaintext at the moment of fill. There are exactly three possible holders:

  1. PP itself. The Edge design. Plaintext lives in the parent browser process throughout the session.
  2. A child renderer QQ. The Chrome / Brave design. Plaintext crosses the parent-renderer boundary for the duration of the autofill RPC and gets zeroed.
  3. A separate higher-privileged broker BB. 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).

No general cryptographic primitive lets a process use a plaintext credential without ever holding 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 "use."

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 architectural: a hardware-isolated broker process. Pluton-anchored vTPM key unwrap [50], Credential Guard's LSAISO pattern [51], DPAPI-NG with the right protection descriptor [49] -- the OS primitives all exist.

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.

The aha moment the rest of the article was built to deliver: the Ronning PoC is not a "bug" 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's password store. The "by design" response is technically true and politically convenient simultaneously. Both are correct readings.

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.

10. Open problems

Four open problems, framed as research directions Microsoft, Apple, and Google have not jointly committed to.

Open problem 1: post-quantum PSI and OT extension

Every deployed breach-checking protocol today rests on assumptions Shor's algorithm 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.

Lattice-based OT extension exists at currently-secure parameters, at roughly 10×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.

Open problem 2: multi-party breach corpora

No production deployment of a >2>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's match metadata without any one provider learning more than their own corpus contributed -- would meaningfully improve detection.

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.

Open problem 3: sub-linear sender-side amortisation

The Ω(nS)\Omega(n_S) sender-side computation lower bound is per query. For a service serving billions of queries against a static SSS_S, can per-query cost be amortised across queries via a preprocessing step the sender pays once?

Cong et al. 2021 [24] reduces constants substantially and pushes the practical envelope. Sub-linear asymptotic sender-side cost is open. The information-theoretic barrier is real -- the sender must touch any element that could be in the receiver's query -- but the expected cost over many queries against a static corpus admits a more aggressive analysis under the right access patterns.

Open problem 4: hardware-broker browser secret stores

The endpoint architectural problem. Migrate Edge, Chrome, and Brave from "process-RAM plaintext" to "OS-broker (plaintext never crosses into the browser)" using DPAPI-NG with a broker-PPL protection descriptor or a Credential Guard-style trustlet.

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.

The Windows Credential Manager offers the broker property for Windows-app credentials -- but it is not wired into Chromium for browser 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.

Open problemWhat's been triedCurrent bestWhy it matters
Post-quantum PSILattice-based OT, ring-LWE OPRFsPrototype-grade; 10x classical at ~secure parametersHarvest-now-decrypt-later on PSI transcripts
Multi-party breach corporaMulti-party PSI literature (e.g., Kolesnikov et al. CCS 2017)Academic constructions; no production deployEach provider's corpus has unique recall
Sub-linear sender costCong et al. 2021 constants reductionLinear Ω(nS)\Omega(n_S) per query5×1095 \times 10^9 corpus, billions of queries
Hardware-broker secret storesWebAuthn / passkeys; DPAPI-NG, Credential GuardStandards exist; wiring into browsers is missingThe Ronning PoC threat model
A simple Chrome App-Bound Encryption check on your machine

Open Chromium'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's the parent. App-Bound Encryption binds the DPAPI unwrap to that exact parent process's signature, so a same-user attacker masquerading as Chrome cannot ask DPAPI to unwrap Chrome's data even with the right user identity. The architectural primitive is sitting in Chrome's source tree as of July 2024 [45]; the equivalent control for Edge's password store has not shipped.

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.

11. Practical guide

What should you do this week?

Users

If your Edge browser is your password manager and you are on a single-user laptop you control end-to-end, the Ronning PoC's threat model is "an attacker who can run code as you on your own machine." 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.

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's "Administrator can access other users' Edge processes" mode). The case for moving saved credentials out of Edge into a dedicated password manager (1Password, Bitwarden, KeePass) is structurally stronger here.

A dedicated password manager usually still keeps plaintext in its 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's window is the entire browser session.

Windows admins

The two relevant Edge enterprise policies are documented on Microsoft Learn:

  • PasswordManagerEnabled [53] -- turns Edge's saved-passwords feature on or off entirely. On a multi-user host with sensitive data, the right value is 0.
  • PasswordMonitorAllowed [27] -- controls whether Password Monitor's breach-checking PSI runs at all. The default is "user-controlled"; 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).

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 processes are not isolated against an administrator. The PoC's "Administrator privileges can access other users' Edge processes" mode is exactly the privilege available to a session-host administrator who has been compromised, or to a malicious tenant who escalates locally.

Developers

If you ship a component that handles credentials, the design lesson from §9 is not "never hold plaintext" -- you cannot avoid it without an OS-level broker -- but "minimise the plaintext-in-RAM window."

The Chrome App-Bound Encryption pattern from July 2024 [45] 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.

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.

12. Frequently asked questions

Frequently asked questions about Edge's two password cryptographies

Doesn't DPAPI protect the saved passwords?

Yes, at rest on disk. DPAPI wraps the symmetric key that encrypts Edge's Login Data SQLite file under a key chain rooted in the user'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'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'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.

Couldn't Protected Process Light (PPL) or RunAsPPL fix this?

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'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.

Doesn't Credential Guard cover browser credentials?

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's heap, not in LSASS, and Credential Guard does not extend protection to arbitrary user-mode application secret stores.

Is k-anonymity 'real' PSI?

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 "a small leak in exchange for vast practical efficiency"; the cost is documented and bounded, and that is why every deployed service uses some variant of it. But it is not zero-leak.

Why didn't Microsoft use SGX like Signal?

Threat-model differences and SGX's well-documented side-channel literature (see the §6 Aside for the four-attack chronology). For a breach-checking service whose threat model is "the corpus must not leak from inside Microsoft," HE-PSI offers a clean cryptographic argument that does not depend on any TEE'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 [1].

Why was the PoC originally in .NET 3.5?

AMSI evasion. The Antimalware Scan Interface scans .NET 4.8+ assemblies before execution; .NET 3.5 predates AMSI'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 ".NET Framework 4.8.1 (changed from 3.5 originally)" [3] -- 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.

Does Chrome or Brave have the same problem?

Per the researcher's claim and the PCWorld relay, no -- see §7 for the decrypt-on-autofill contrast and Chrome's App-Bound Encryption hardening [42][45]. 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.

Is 'by design' a reasonable response?

Yes (with caveats). See §7's MSRC-servicing-criteria Aside for the full framing [48]: 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's machine. The architectural primitive that would close the gap (an OS broker) exists on Windows but is not wired into Chromium.

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.

Study guide

Key terms

Private Set Intersection (PSI)
A two-party cryptographic protocol that computes the intersection of two sets without revealing anything else.
Oblivious Transfer (OT)
A primitive in which a sender holds two messages, a receiver picks one, and neither learns the other's choice or the unsent message.
OT extension
Two-phase protocol that turns kappa public-key OTs into m symmetric-cost OTs, collapsing per-OT cost by orders of magnitude.
Oblivious Pseudorandom Function (OPRF)
Two-party protocol where the receiver learns F_k(x) without revealing x to the sender or learning k.
Pseudorandom Correlation Generator (PCG)
Primitive that locally expands a short shared seed into long correlated random strings, used to make Silent OT communication-free post-seed.
Homomorphic encryption (HE / SWHE / FHE)
Encryption supporting operations on ciphertexts that decrypt to operations on plaintexts; SWHE is bounded depth, FHE is unbounded via bootstrapping.
Cuckoo hashing
Hashing with k candidate bins per element and displacement, achieving O(1) lookup at high load -- the partitioning trick under CLR17 and CHLR18.
k-anonymity (password monitoring)
A precise small information leak: each query is consistent with at least k possible passwords sharing the bucket prefix.
Data Protection API (DPAPI)
Windows facility that wraps blobs under user-derived keys; an at-rest control, not an in-process-memory control.
App-Bound Encryption (Chrome, July 2024)
Chrome control that binds DPAPI unwrap of saved data to the verified Chrome process identity, blocking same-user impersonation attacks.

Comprehension questions

  1. Why does the DH meet-in-the-middle PSI protocol fail at breach-checking scale?

    It costs O(|S_B|) group exponentiations per query, leaks set cardinality on both sides, and provides no labeled-PSI variant.

  2. What three engineering moves let CLR17 revive FNP04's polynomial-roots PSI?

    (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|).

  3. What does the OPRF preprocessing layer add to Edge Password Monitor's bare HE-PSI?

    It prevents a malicious client from brute-forcing the server's corpus offline; the client cannot evaluate F_k(x) without server interaction.

  4. What does the EdgeSavedPasswordsDumper PoC require to read Edge passwords as cleartext?

    Same-user OpenProcess + ReadProcessMemory on the parent msedge.exe. No kernel exploit, no admin (against same-user processes), no DPAPI bypass.

  5. Why is 'no cryptographic primitive closes the plaintext-RAM gap' the structural claim of section 9?

    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.

---WRITER METRICS---
Word count: 12625
Citations: 104 inline `@id`-style references across 53 unique sources (frontmatter expanded with PSZ14, four SGX disclosure pages, MSRC servicing criteria, three Microsoft Learn OS-broker primitives, Paillier 1999, Pagh-Rodler 2001, AMSI .NET 4.8, and Wikipedia TLS in Stage 11 iter-1 resolution)
Mermaid diagrams: 6
Definitions: 9
Sidenotes: 8
FAQ questions: 8
---END WRITER METRICS---

References

  1. Microsoft Research (2021). Password Monitor: Safeguarding passwords in Microsoft Edge. https://www.microsoft.com/en-us/research/blog/password-monitor-safeguarding-passwords-in-microsoft-edge/
  2. Tom Joran Sonstebyseter Ronning (2026). X post disclosing EdgeSavedPasswordsDumper. https://x.com/L1v1ng0ffTh3L4N/status/2051308329880719730
  3. Tom Joran Sonstebyseter Ronning (2026). EdgeSavedPasswordsDumper. https://github.com/L1v1ng0ffTh3L4N/EdgeSavedPasswordsDumper
  4. Davey Winder (2026). Microsoft Says Edge Password Security Vulnerability Is 'By Design'. https://www.forbes.com/sites/daveywinder/2026/05/06/microsoft-says-edge-password-security-vulnerability-is-by-design-is-it-time-to-switch-to-chrome/
  5. Catherine Meadows (1986). A More Efficient Cryptographic Matchmaking Protocol for Use in the Absence of a Continuously Available Third Party. https://dblp.org/rec/conf/sp/Meadows86.bib - IEEE Symposium on Security and Privacy, pp. 134-137
  6. IEEE Xplore record for Meadows 1986. https://ieeexplore.ieee.org/document/6234864
  7. Transport Layer Security (Wikipedia). https://en.wikipedia.org/wiki/Transport_Layer_Security
  8. Bernardo A. Huberman, Matthew K. Franklin, & Tad Hogg (1999). Enhancing Privacy and Trust in Electronic Communities. https://dblp.org/rec/conf/sigecom/HubermanFH99.bib - First ACM Conference on Electronic Commerce (EC-99), pp. 78-86
  9. DBLP record for Huberman-Franklin-Hogg 1999. https://dblp.org/rec/conf/sigecom/HubermanFH99.html
  10. Troy Hunt (2018). I've Just Launched Pwned Passwords Version 2. https://www.troyhunt.com/ive-just-launched-pwned-passwords-version-2/
  11. Michael Freedman, Kobbi Nissim, & Benny Pinkas (2004). Efficient Private Matching and Set Intersection. https://link.springer.com/chapter/10.1007/978-3-540-24676-3_1 - EUROCRYPT 2004
  12. Pascal Paillier (1999). Public-Key Cryptosystems Based on Composite Degree Residuosity Classes. https://link.springer.com/chapter/10.1007/3-540-48910-X_16 - EUROCRYPT 1999, LNCS 1592, pp. 223-238
  13. Hao Chen, Kim Laine, & Peter Rindal (2017). Fast Private Set Intersection from Homomorphic Encryption. https://eprint.iacr.org/2017/299 - CCS 2017
  14. Yuval Ishai, Joe Kilian, Kobbi Nissim, & Erez Petrank (2003). Extending Oblivious Transfers Efficiently. https://link.springer.com/chapter/10.1007/978-3-540-45146-4_9 - CRYPTO 2003
  15. Marcel Keller, Emmanuela Orsini, & Peter Scholl (2015). Actively Secure OT Extension with Optimal Overhead. https://eprint.iacr.org/2015/546 - CRYPTO 2015
  16. Elette Boyle, Geoffroy Couteau, Niv Gilboa, Yuval Ishai, Lisa Kohl, & Peter Scholl (2019). Efficient Pseudorandom Correlation Generators: Silent OT Extension and More. https://eprint.iacr.org/2019/448 - CRYPTO 2019
  17. Elette Boyle, Geoffroy Couteau, Niv Gilboa, & Yuval Ishai (2019). Compressing Vector OLE. https://eprint.iacr.org/2019/273 - CCS 2018 PCG/VOLE precursor
  18. Vladimir Kolesnikov, Ranjit Kumaresan, Mike Rosulek, & Ni Trieu (2016). Efficient Batched Oblivious PRF with Applications to Private Set Intersection. https://eprint.iacr.org/2016/799 - CCS 2016
  19. Microsoft SEAL. https://www.microsoft.com/en-us/research/project/microsoft-seal/
  20. Rasmus Pagh & Flemming Friche Rodler (2001). Cuckoo Hashing. https://www.itu.dk/people/pagh/papers/cuckoo-jour.pdf - ESA 2001 (conference); J. Algorithms 51(2):122-144, 2004 (journal)
  21. Fast Private Set Intersection from Homomorphic Encryption (Microsoft Research publication page). https://www.microsoft.com/en-us/research/publication/fast-private-set-intersection-homomorphic-encryption/
  22. Hao Chen, Zhicong Huang, Kim Laine, & Peter Rindal (2018). Labeled PSI from Fully Homomorphic Encryption with Malicious Security. https://eprint.iacr.org/2018/787 - CCS 2018
  23. Labeled PSI from Fully Homomorphic Encryption with Malicious Security (Microsoft Research publication page). https://www.microsoft.com/en-us/research/publication/labeled-psi-from-fully-homomorphic-encryption-with-malicious-security/
  24. Kelong Cong, Radames Cruz Moreno, Mariana Botelho da Gama, Wei Dai, Ilia Iliashenko, Kim Laine, & Michael Rosenberg (2021). Labeled PSI from Homomorphic Encryption with Reduced Computation and Communication. https://eprint.iacr.org/2021/1116 - CCS 2021
  25. Microsoft APSI (Asymmetric PSI) library. https://github.com/microsoft/APSI
  26. CNG DPAPI (DPAPI-NG) and Protection Descriptors. https://learn.microsoft.com/en-us/windows/win32/seccng/cng-dpapi
  27. Microsoft Edge Security: Password Monitor. https://learn.microsoft.com/en-us/deployedge/microsoft-edge-security-password-monitor
  28. Have I Been Pwned API v3. https://haveibeenpwned.com/API/v3
  29. Kurt Thomas & et al. (2019). Protecting accounts from credential stuffing with password breach alerting. https://www.usenix.org/conference/usenixsecurity19/presentation/thomas - USENIX Security 2019
  30. Apple Platform Security: Password Monitoring. https://support.apple.com/guide/security/password-monitoring-sec78e79fc3b/web
  31. Moxie Marlinspike (2017). Technology Preview: Private Contact Discovery. https://signal.org/blog/private-contact-discovery/
  32. Junade Ali (2018). Validating Leaked Passwords with k-Anonymity. https://blog.cloudflare.com/validating-leaked-passwords-with-k-anonymity/
  33. Have I Been Pwned: Pwned Passwords. https://haveibeenpwned.com/Passwords
  34. (2019). Protect your accounts from data breaches with Password Checkup. https://security.googleblog.com/2019/02/protect-your-accounts-from-data.html
  35. Apple Platform Security Guide (PDF). https://help.apple.com/pdf/security/en_US/apple-platform-security-guide.pdf
  36. Google private-membership (PSM) open-source library. https://github.com/google/private-membership
  37. Signal ContactDiscoveryService (SGX reference implementation). https://github.com/signalapp/ContactDiscoveryService
  38. Jo Van Bulck, Marina Minkin, Ofir Weisse, Daniel Genkin, Baris Kasikci, Frank Piessens, Mark Silberstein, Thomas F. Wenisch, Yuval Yarom, & Raoul Strackx (2018). Foreshadow: Extracting the Keys to the Intel SGX Kingdom with Transient Out-of-Order Execution. https://foreshadowattack.eu/ - 27th USENIX Security Symposium, August 2018
  39. Guoxing Chen, Sanchuan Chen, Yuan Xiao, Yinqian Zhang, Zhiqiang Lin, & Ten H. Lai (2018). SgxPectre Attacks: Stealing Intel Secrets from SGX Enclaves via Speculative Execution. https://arxiv.org/abs/1802.09085 - arXiv:1802.09085 (Feb 2018); IEEE EuroS&P 2019
  40. Stephan van Schaik, Andrew Kwong, Daniel Genkin, & Yuval Yarom (2020). SGAxe: How SGX Fails in Practice. https://sgaxe.com
  41. Pietro Borrello, Andreas Kogler, Martin Schwarzl, Moritz Lipp, Daniel Gruss, & Michael Schwarz (2022). ÆPIC Leak: Architecturally Leaking Uninitialized Data from the Microarchitecture. https://aepicleak.com - 31st USENIX Security Symposium, 2022
  42. Laura Pippig (2026). Edge plaintext passwords in memory (PCWorld). https://www.pcworld.com/article/3131805/
  43. (2026). Microsoft Edge passord i klartekst i minnet (ITavisen). https://itavisen.no/2026/05/04/microsoft-edge-passord-klartekst-minne/
  44. Chromium os_crypt source (decrypt-on-autofill code path). https://source.chromium.org/chromium/chromium/src/+/main:components/os_crypt/sync/os_crypt_win.cc
  45. (2024). Improving the security of Chrome cookies on Windows (App-Bound Encryption). https://security.googleblog.com/2024/07/improving-security-of-chrome-cookies-on.html
  46. Antimalware Scan Interface (AMSI) portal. https://learn.microsoft.com/en-us/windows/win32/amsi/antimalware-scan-interface-portal
  47. .NET Framework: What's New (AMSI integration introduced in .NET Framework 4.8). https://learn.microsoft.com/en-us/dotnet/framework/whats-new/
  48. Microsoft Security Servicing Criteria for Windows. https://www.microsoft.com/msrc/windows-security-servicing-criteria
  49. Protection descriptors (DPAPI-NG NCRYPT). https://learn.microsoft.com/en-us/windows/win32/seccng/protection-descriptors
  50. Microsoft Pluton security processor. https://learn.microsoft.com/en-us/windows/security/hardware-security/pluton/microsoft-pluton-security-processor
  51. Credential Guard overview (VBS, LSAISO). https://learn.microsoft.com/en-us/windows/security/identity-protection/credential-guard/
  52. Benny Pinkas, Thomas Schneider, & Michael Zohner (2014). Faster Private Set Intersection Based on OT Extension. https://www.usenix.org/conference/usenixsecurity14/technical-sessions/presentation/pinkas - USENIX Security 2014, pp. 797-812
  53. Microsoft Edge policy: PasswordManagerEnabled. https://learn.microsoft.com/en-us/deployedge/microsoft-edge-browser-policies/passwordmanagerenabled