KREMLIN forges Chrome's integrity check to load an extension the user never approved
Elastic Security Labs found banking malware that recreates Chrome's own tamper seals to load a hidden extension. It defeats the approval prompt, not the enterprise allowlist, and it leaves a footprint.
By Parminder Kumar Sharma · · 11 min read

One public seed, five years old
One hard-coded value decides whether Chrome trusts its own list of installed extensions. It is a 64-byte seed baked into a single file inside resources.pak, first described in an academic paper in 2020, and Synacktiv confirmed it was still valid in Chromium 139 in September 2025, five years on. On Microsoft Edge, the researchers report, that seed is empty. Recreate the seed's signatures and the browser will load whatever extension you name as though a person had clicked yes.
That is the mechanism behind KREMLIN, a Brazilian banking operation that Elastic Security Labs published on 14 September 2026 and that BleepingComputer reported two days later. What the seed does not establish is a remote break. Reading it and rebuilding the signatures needs code already running on the machine, in the victim's own account. This is a post-compromise move, not an internet-facing vulnerability, and that distinction is the whole story for anyone who read our earlier note on locking extensions down.
On 16 September we recommended moving browser extensions to an allowlist through Chrome's ExtensionSettings policy, using blocked_permissions and runtime_blocked_hosts, after the BragJack research showed a single extension could hijack a built-in AI assistant. The honest follow-up question is the one a security lead should ask of any control: does it still hold once malware is already on the endpoint? For KREMLIN the answer is layered, and worth getting right.
What Elastic actually found
Elastic tracks the operation as REF9334 and the toolkit as KREMLIN, a name its own author chose. Nothing about it is Russian: the lures impersonate twelve Brazilian banks, the error messages and code comments are in Portuguese, and the operators' Ethereum transactions cluster in Sao Paulo working hours. Over what Elastic calls more than 15 months and seven campaigns, the actors built a browser extension that installs itself into Chrome and Edge, and the browser then loads it as if the user approved it.
The chain starts when a target opens a JavaScript file dressed as a bank receipt, invoice or payment record. After anti-sandbox checks, it downloads Node.js, sets a scheduled task named MicrosoftNodeRuntimeUpdater for persistence, and pulls its next stage from an Ethereum smart contract used as a dead-drop resolver. Later stages sideload the payload through a legitimate signed SentinelOne binary. The banking side of the toolkit deployed the PULSAR remote access tool in earlier campaigns and switched to REMCOS in newer ones.
The installer is the interesting part. It waits until the browser is closed or the user has been idle for at least two minutes, then copies the extension into the profile directories, turns on developer mode, and registers the extension under extensions.settings. Because Chromium protects those entries with integrity checks, the malware recovers the keys it needs and regenerates the signatures itself. Elastic describes it plainly.
Once loaded, the extension masquerades as software called AVSync and asks for access to tabs, cookies, storage and the webRequest API. It steals cookies and local and session storage, keylogs form fields including passwords, captures screenshots and page source, enumerates tabs and history, intercepts request bodies and headers, injects attacker-controlled HTML, redirects clicks, and takes commands over a WebSocket. Alongside it, KREMLIN exfiltrates the browser's credential databases together with the App-Bound keys needed to decrypt them.
How the forged load works, and where the seam is
The technique KREMLIN borrows was written up by Synacktiv in September 2025 as "The Phantom Extension". Chromium records installed extensions in a preferences file inside the user's profile: Secure Preferences on machines that are not domain-joined, and Preferences on domain-joined ones. Each extension entry, and the developer-mode toggle, is protected by a message authentication code so that an outside process cannot simply edit the file. The Secure Preferences variant adds an aggregate super_mac over the whole set.
The catch is that the HMAC seed is not a secret. It is static, shipped inside resources.pak, unchanged for years, and null on Edge and Brave. So a process running as the user can read the seed, compute the correct MAC for an extension entry it invents, flip developer_mode to true and sign that too, and rewrite super_mac. Newer Chromium builds, from version 144, add a second layer: an OSCrypt App-Bound encrypted hash next to each legacy MAC. KREMLIN handles that by launching the browser under a debugger to read the App-Bound key out of memory, then encrypting the hashes the same way Chrome would.
Read the two columns and the seam is clear. The approved path proves that a person or a policy said yes, and Chrome does the signing from inside its own trusted process. The forged path never asks anyone: it reconstructs the same proof from the outside using values a local process can obtain. The integrity check was designed to stop a foreign process editing the file. It was never a defence against a process that runs as the user and can therefore read everything the user can.
Does this defeat the allowlist we recommended?
Here is where precision matters, because the BleepingComputer headline says "force install" and the enterprise world has a specific meaning for that phrase. Forging Secure Preferences defeats the approval decision: the record that says a human chose this extension. In the consumer machines KREMLIN hit, that was the only control in the way, so the forged load was game over silently.
An ExtensionSettings allowlist is a different control. Chrome reads it from the registry at load time and refuses to run anything not permitted, regardless of what the preferences file claims. Elastic did not observe KREMLIN touching that policy at all. So the forging alone does not walk past an allowlist that blocks unknown extensions by default. To get an unapproved extension to load under such a policy, an attacker needs a second step, and Synacktiv documents two.
The first is to spoof the identity of an already-allowlisted extension. Because a Chromium extension ID is derived deterministically from a public key in the manifest, an attacker who obtains the public key of an approved extension can reproduce its ID and load a modified unpacked version under it. Synacktiv found that when IDs collide, the browser favours the locally loaded copy, quietly overriding the trusted one. The second is cruder: the policy keys live under HKCU\Software\Policies and HKLM, and a user with administrative rights can simply delete or rewrite them, and the restriction is gone.
What the ExtensionSettings allowlist stops, and what it does not (from Elastic's KREMLIN findings and Synacktiv's Phantom Extension research)
| Attacker position | Does the allowlist hold? | What it takes to defeat it |
|---|---|---|
| A web page or a user tries to install | Yes | Nothing gets past a default-deny allowlist |
| Malware as the user, no admin | Largely, yes | Must spoof the key of an allowlisted extension |
| Malware as the user, with admin | No | Delete or rewrite the policy registry keys, then forge |
So the allowlist is not a comfort blanket, but nor is it defeated by KREMLIN as observed. It does exactly what we said it does: it stops a user or a web page installing an extension, and it raises the bar sharply against local malware, which must now either steal an approved extension's key material or hold administrative rights and tamper with policy. The threat model has simply changed. An allowlist answers "who may install". It was never designed to answer "has a program with my privileges rewritten the record of what I installed".
What defenders can actually see
The good news is that a forged load is noisy if you know where to look, and the tells are supported by the research and by Google's own policy documentation rather than by hope. The central one is definitional. A genuine managed extension pushed through ExtensionSettings or ExtensionInstallForcelist shows in chrome://extensions as installed by your administrator, with a toggle the user cannot switch off, and it appears in the policy you deployed. KREMLIN's extension shows the opposite: developer mode enabled, loaded unpacked, present in the profile but absent from your managed policy. An extension that looks force-installed but is not in your policy is the anomaly.
Synacktiv's blue-team guidance names the file-level signals: unauthorised changes to Preferences or Secure Preferences, especially by a process that is not the browser, and unexpected extension registrations. Add the changes to HKCU or HKLM policy keys that the admin-rights bypass requires. Elastic's chain adds host-level markers you can hunt on directly.
Take this with you
Hunt and harden this week
- Inventory every browser extension across the fleet and flag any that are enabled with developer mode on, or loaded unpacked, that you did not push by policy.
- Alert when a non-browser process writes to Preferences or Secure Preferences in any Chrome or Edge profile.
- Monitor HKCU and HKLM Software Policies keys for Chrome and Edge for deletion or modification of the extension allowlist and blocklist.
- Keep the ExtensionSettings allowlist set to block by default, deny sensitive permissions such as debugger and declarativeNetRequest, and approve extensions individually.
- Reduce standing local administrator rights, since the clean policy bypass depends on them.
- Hunt for the scheduled task MicrosoftNodeRuntimeUpdater and for conhost.exe launching node.exe with the headless flag from a user directory.
- Watch for a browser process being launched with a debugger or the no-startup-window flag by an unexpected parent, the step used to read the App-Bound key.
- Load Elastic's published KREMLIN indicators into your detection tooling and treat AVSync as a hunting string.
Two caveats keep this honest. The extension name AVSync and the specific scheduled-task and infrastructure indicators belong to the campaigns Elastic observed and will change; the structural tells, developer mode on and a preferences file edited by something other than the browser, will not. And session-token theft means a stolen sign-in survives a password reset, so treat a confirmed infection as a reason to revoke sessions, not just rotate credentials.
The question that exposes the gap
The comforting reading of this research is that it only matters if malware is already running as the user, which is true. The uncomfortable reading is that browsers now hold the session tokens and cloud access that used to sit behind a login, and the file that records which extensions may read all of that is protected by a seed anyone can extract. The control we recommended still stands, on its own terms. It is worth asking a sharper question of it.
If a program running in one of your users' accounts rewrote the browser's own record of which extensions are trusted tonight, which alert would fire, and who would read it before the session tokens left the building?
Sources
- PrimaryPrimary research: KREMLIN / REF9334 analysis, the forced-load technique, capabilities, campaigns, wallet trail and the canary kill switchElastic Security Labsaccessed 2026-09-17
- PrimaryPrimary research the technique is drawn from: Secure Preferences forging, the resources.pak HMAC seed, developer-mode MAC and the GPO allowlist bypassesSynacktivaccessed 2026-09-17
- PrimaryPolicy reference used to describe force-installed extensions and the ExtensionInstallForcelist registry mechanismGoogle Chrome Enterpriseaccessed 2026-09-17
- PrimaryExtensionSettings and installation_mode force_installed reference used for the allowlist and detection pointsGoogle Chrome Enterprise and Education Helpaccessed 2026-09-17
- Reported byNews pointer to the Elastic research; used only to locate the primary sourceBleepingComputeraccessed 2026-09-17
- Reported byOur earlier briefing recommending extension allowlisting through ExtensionSettings, which this piece revisitspk-sharma.comaccessed 2026-09-17


