Malicious Extensions - What They Are And How To Fight Them

Introduction Link to heading

According to DebugBear, there were about 1.7 billion users with installed Chrome extensions in 2020, out of more than 2.5 billion users of Chrome. Those browser extensions exist on every operating system and are available in almost any web browser. Browser extensions have vast numbers of users because they enhance the browsing experience, fill gaps, and offer functionalities that support everyday tasks.

Behind the scenes, different types of groups put enormous effort into convincing users to install extensions. Some are companies that base their businesses on extensions, and some are developers that just want to share their new product features. In between, there are a lot of groups that either try to make money by hijacking search or displaying ads, and others that actually use the platform to steal sensitive user information. Extensions can access many user resources, so imagination is almost the only limitation for sensitive data theft.

In this article, we will demonstrate how dangerous extensions can be, and describe the different means of delivering extensions to users, and most importantly, how blue teams can hunt and investigate malicious extensions.

What are browser extensions? Link to heading

Extensions are small programs installed on web browsers that customize the browsing experience. Extensions can add varied functionalities, alter the page view and provide information—almost anything within the boundaries of JavaScript, HTML and CSS.

Extensions are available both on Windows and on Mac, as they are OS-independent—they rely on the browser to run them. While they possess a number of functionalities meant to provide normal helpful user experience to apps, they have been used by numerous threat groups to collect and steal user information and data, exfiltrate data, mine crypto currency, hijack search, hijack ads, present ads and alter page objects.

Accessing Browser Resources Link to heading

In modern operating systems, it is hard to get inside (process injection or running code for example) the web browser space, due to many restrictions and defenses built up over the years, such as process isolation and memory management. In short, the idea of process isolation is to segregate processes from accessing memory space they do not own and to keep programs with different privileges isolated to their own virtual address space. Web browsers also implement internal security mechanisms such as:

  • same-origin policy – critical security mechanism that restricts how a document or script loaded by one origin can interact with a resource from another origin. Two URLs have the same origin if the protocol, port (if specified), and host are the same for both.
  • Site Isolation – separating web content and loading each site in its own operating system process. The goal is to defend against malicious sites trying to access sensitive information from other sites you access.
  • Integrated sandbox, and more.

By design, extensions have the power to access browser resources, which can be accessed by the extension if the specific permissions are listed in the extension’s manifest file. An extension can steal information from users as well as any other executable info-stealer, so it is important to take them very seriously.

Permissions Link to heading

There is a wide variety of permissions that an extension can ask for in order to gain access to non-default items such as:

  • Identity of the logged-in user
  • Oauth Tokens – use of your signed-in Google account
  • Cookies, history, browsing data, geolocation
  • Interception of web requests
  • Whole-screen screenshots
  • Clipboard data and keyboard capture (keylogging)
  • Notifications
  • Altering page view and injecting code to all browsing pages (through controlling the DOM) The following example is taken from a malware that injects ads to the page, so whenever a user searches for something, the extension injects fraud pages to the top of the page. It is highly likely the user will not notice and click on one of them, thus downloading software or entering payment details.

Taken from

Extension Structure Link to heading

Before we continue we want to backtrack a bit and explain how extensions work. When we talk about extensions, we need to remember that extensions are available not only on Chrome, but also in all other Chromium-based browsers such as Edge, Opera, Brave, and in non-Chromium browsers such as Firefox. All of the browsers have a fixed location for the extensions and their code: Chrome (or Chromium-based):

  • %user%\AppData\Local\Google\Chrome\User Data\Default\Extensions
  • “.crx” file extension (zip file)
  • Each extension has a unique 32-character long ID name


  • AppData\Roaming\Mozilla\Firefox\Profiles\xxx.default-release\extensions
  • “.xpi” file extension

An extension folder will contain all of the code necessary to its operation, including JavaScript files, a manifest file, CSS and HTML files as needed.

A manifest file defines the extension’s purpose and contains valuable information about the extension, including which scripts it runs and whether it uses remote scripts, what permissions it needs, and description of its purpose. It looks something like this:

Background scripts (the “backend” part) are executed immediately after the browser starts and listens for events. Usually the main script will be mentioned here, while other scripts imported and used by the main script may not appear in this section.

Another important part of the manifest file is the “Permissions”—some methods and resources are only available to the extension if it requests the right permissions, and some permissions will show a warning notification to the user upon the first installation. Also note that there is an “Update URL” —keep in mind that extensions can update themselves, so even if you go over all of the source code, it could change in a version update. This means that an attacker can create nice-looking extensions with no malicious parts, but a malicious code could possibly run on a future update.

Content scripts are injected into web pages (defined in the manifest file) and can run their code in the pages as soon as the pages are opened. The script is now part of the page and can communicate with its DOM objects.

There are more adjustments that can be made with scripts to control the popup (click on the icon of the extension to use suggested actions) and options menus (an option to take action when right-clicking on a page).

How Malicious Extensions Find Their Way to Your Browser Link to heading

Over the years, many malicious extensions have been discovered, and many of them have fooled users into installing them, or, there’s the chance they were installed by undetected malware. There are many ways for users to find themselves installing sketchy extensions or waking up to an extension they did not choose.

Extention Spoofing Link to heading

The first tactic is to trick users into installing malicious extensions by impersonating an official or known extension. In these cases, the extension’s name, description and domains would look like a known extension, making the users believe that they’re installing something trustworthy and beneficial.

Extensions such as these can be found in the Extension Store (until they are detected and removed), in forums, on sketchy websites or even fake social media accounts that publish and promote them to unwitting victims. For example:

Pop-ups / Pop-unders Link to heading

When browsing sketchy websites, it is common for random pages to pop up on the screen (or under the screen, when it is a pop-under), covering the main webpage with ads, or suggestions to install extensions. Usually there will be a green arrow that points to a link and even with fake good reviews, or there will be a scary message that will persuade the user to immediately install a software that will solve their operating system’s alleged problems. They use eye-catching animations, colors and shapes to attract the user’s attention, and convince them to act rapidly to install the extension.

Pop-ups cost more money to the publishers because they immediately take over the screen whether the user likes it or not, while pop-unders cost less because they remain under the rest of the browser windows, until they are discovered by chance when the user closes the windows. Pop-unders might be less costly but they are shadier because it usually takes the user significantly time to become aware of it, so that the source of the pop-under is hidden.

Notifications Link to heading

Notifications are not extensions, and cannot be installed directly. They function as “the step before,” interacting with the user via computer notifications, and then suggesting they install extensions, or even programs.

Notifications appear as pop-ups on the top of the screen, asking the user to click allow so the site is able send notifications directly to the user via the operating system, even when the user is no longer surfing the website. Then the notifications pop-up on the user’s computer, outside of the browser context.

Malicious notifications will suggest sketchy links and advertisements to the user, and eventually, the user might click on one of them, unknowingly installing malware. The notifications make it harder to understand which website was the source, because they can keep popping up even after the user closes the specific page.

Behind the Scenes Link to heading

The methods reviewed so far rely on actively tricking the user to install an extension. Another option is to deliver a malicious extension to the user, from a malicious or potentially unwanted program downloaded by the user. Because the extension does not come from the extension store, it does not go through any compliance process. This makes it even more dangerous, because it has no restrictions or limitations on what it does. It can be installed via registry, using the browser process with certain command line parameters, or even by tampering with browser executables or dlls.

Using Browser Arguments Link to heading

Loading unpacked extensions locally: it is possible to install an extension by placing its files on the disc, and by using a simple command line “start chrome –load-extension="$extPath”. An extension can be stored in an extension format, which can be either “.crx” (for chromium) or “.xpi” (for Firefox).

Limitations: when the user opens the browser for the first time after extension installation, the browser prompts the user to acknowledge the changes. Advantages: if acknowledged, the extensions receive full permissions to whatever they need.

This method also works in Firefox: firefox.exe -install-global-extension extension.xpi

Using Browser lnk Files Link to heading

This method has been used also on “.lnk” files of browsers. Attackers changed the target and added the parameter of “–load-extension,” so that every time the user clicks on the browser shortcut, it loads the malicious extension.

Using the registry Link to heading

Another way to install extensions is by creating a registry key of the extension ID under:

HKLM\Software\WOW6432Node\Google\Chrome\Extensions or


Setting those registry keys forces Chrome to download it from the store (but for that, the extension needs to be approved on the store first) and then to enable it.

One method that was common in the past was for threat actors to buy existing legitimate extensions. There are successful, legitimate and efficient extensions in the store, that have a large userbase with many good reviews. This is very important for two reasons. The first is that anyone who sees those reviews and good status will not be suspicious of the extension, making them more likely to install it. The second is that if threat actors buy such extensions from the original, clean developer, they immediately get access to the code, and can update it with malicious scripts. Then the existing pool of users will get the update and execute the malicious code without knowing what occurred behind the scenes.

Note: today, if the updated extension requires more permissions than it had, the extension will automatically be disabled until the user accepts the required permissions. This is a good thing, but still users tend to accept anything anyway. And, if the extension already had those permissions in the first place but all that changed was the code and how maliciously it uses those permissions, the extension will not be disabled.

How to Investigate? Link to heading

Whether you are a suspecting user or investigating a specific extension or an incident, you can get information about the extension in several ways.

The first and easiest is to look up the extension in the Extension Store. You only need the extension ID or the extension name, which can then be searched for in the store. The extension ID is preferable because it eliminates the chance of finding two extensions with similar names and having to choose between them. If an extension ID is not at hand, search for the name instead. In the event that the extension is not found, this is the first warning sign—it means that it either was removed from the store, or that it was not installed from the official store in the first place.

Even if it is found in the store, it doesn’t mean it’s 100% percent safe, despite the compliance process it had to go through to get there. To get an idea about an extension it is important to check the user reviews on the page in the store, check the number of users, and the identity of the publisher.

After the online review, it is time to investigate the extension’s files. The most important one to begin with is the manifest file, followed by examining all of the code in the JavaScript and HTML files.

  • When you’re examining the manifest, always check the permissions that it requests and see if they match the service that is being offered. For example, if you installed an extension that takes screenshots, it makes sense that it will request the ScreenRecord permission. In other cases, it probably does not make sense.
  • The permissions are important, but not as important as how they’re used in the code. Go over all of the code carefully and make sure you understand each function.
  • Check the URLs and domains, and see what they’re used for and where they are used. Most often they will be obfuscated or scattered around the code.
  • When you go over the “content_security_policy” field, if you see “script src” and “unsafe eval,”–it’s already a bad sign. This indicates the extension can execute code from remote URLs— code that is not present locally in the extension code and that you cannot see.
  • ‘unsafe-eval’ allows the application to use the eval() JavaScript function. This reduces the protection against certain types of DOM-based XSS bugs
  • Also, content_script is important: it means that a script will run each time a page starts, a kind of JavaScript injection to the page.
  • A common method for malicious extensions is to obfuscate and uglify the code, so the user or researcher does not know what is happening. This is against the Google Chrome security process, so if you ever examine an extension and see something like this—know that something is not right.
  • Attackers don’t want to be discovered, so evasion techniques are implemented: some extensions check if the user is examining the extension, or what other extensions the user has, in order to make a profile of the user and decide whether or not to execute the malicious code
  • Some extensions also stay dormant for a couple of days before they update or execute malicious code. One way to find that out is by checking date functions that make calculations.
  • Even if everything looks legitimate, attackers can find ways to hide their malicious code between thousands of lines of legitimate code (example of modified jquery.js.

A very important and useful website that helps with extension examination is “CRXCavator.” CRXCavator stores every piece of information about extensions, including version history, permissions and their risk score, manifest file and code. It is a great tool to understand what an extension does and needs, and how risky it might be. It marks suspicious parts, and enables you to see changes between the versions and also informs you if known vulnerabilities are found within the used libraries.

Permissions 101 Link to heading

It takes time to get familiar with extensions’ permissions and their usage, not only if you are new to JavaScript but also because of the uninformative descriptions provided by Google.

To make your life easier, we prepared some helpful information on the most commonly used permissions:

Identity Link to heading

What they mean: “Use the chrome.identity API to get OAuth2 access tokens.”

With this valuable permission, an extension can get your email address, icon, contacts (to get a list, to add a new contact, or to delete), and authentication token.

If the user is already signed in to Chrome, it is also possible to use the parameter of “interactive: false” so the authentication will not prompt the sign-in window. However, what is not made clear to average readers, is that if the extension gets the token, it can also generate requests to Google APIs at for information from mail, calendar, drive and more:

It is important to know the extension can get access to those APIs even without requesting the identity permission, but simply through host permission with the URLs of those services.

"permissions": [
   "webRequestBlocking"  ],

nativeMessaging and messaging Link to heading

Extensions can talk between themselves by using “connect” and “sendMessage” methods by specifying the extensionID. This allows for a situation in which an attacker can provide more than one extension and distribute its malicious activity between extensions, while still being able to synchronize information among them.

By using the nativeMessaging, an extension can talk with an installed Chrome app and retrieve information or send commands, such as using the filesystem app ability. Another possible scenario is one in which the attacker spots a legitimate benign extension that doesn’t follow security practices. They can then deploy a different extension that uses the messaging mechanism to send messages containing script blocks to the legitimate extension, which in turn executes them:

From (


From Google’s documentation: Gives your extension access to the chrome.alarms API.

What they mean: use the chrome.alarms API to schedule code to run periodically or at a specified time in the future.

By using alarms, the extension can schedule specific functions to run at specific times, which means that the extension can choose to delay its malicious activity to a different day, or to make sure that it runs functions at regular intervals. ChromeBack malware used this to sync information with the controller, and to continuously display ads. (

Management Link to heading

With the management permission, the extension is able to view all of the existing extensions and apps that are installed and running, and to even install and launch apps. Two interesting things that can be done with this permission. One is to redefine the “new tab” page (the first page that opens when the browser starts). Many extensions fight over the privilege to be displayed on the new tab page—as this leads to more purchases. The second is the ability to delete other extensions. This is beneficial if an extension wants to make sure it is the single recipient of funds from your data or searches or CPU, or if the extension wants to make sure there is no AV extension installed to block and report its activity.

Host permissions <all_urls> , https:/// Link to heading

this is the worst permission you can see

"http://*/*", "https://*/*" , "*://*/*", "<all_urls>"

(or: it is even possible to encode the string to bypass static analysis-instead of “<all_urls>”: "\u003call\u005furls\u003e")

From Google’s documentation: Grants the extension access to all hosts (domains). It may be possible to avoid declaring any host permissions by using the activeTab permission.

What they mean:

This permission—combined with other permission or content scripts—is the highway to a security disaster, and basically grants the extension the permission to run its code on each and every site you visit. It can read and edit sensitive information, gain access to DOM elements as password boxes, and steal passwords before they are sent encrypted. It is very common in malicious extensions and you should never take this permission lightly. Another type of URL that can be entered is local file URL, such as: "file:///*". Using this URL to create web requests using local web socket can allow interaction with your local files ( More about it in examples below.

Storage Link to heading

From Google’s documentation: gives your extension access to the API.

What they mean:

syncing user data, a convenient way to let extensions talk between themselves, or accessing other extensions resources if they are not encrypted. Storage can be used by the extension as a temporary database, from which it can read and write values, and do whatever it needs, such as send them to the C&C. All of this information can be synced to the user’s Google cloud, by calling the “” method (this is not the same as Google Drive). If your account has been compromised and the attacker is able to connect to your account, they could get information saved on storage, as described on an interesting incident investigation by Bojan Zdrnja.

When using storage.sync, the stored data will automatically be synced to any Chrome browser the user is logged into, provided the user has sync enabled. When using storage.sync, the stored data will automatically be synced to any Chrome browser that the user is logged into, provided the user has sync enabled. When Chrome is offline, Chrome stores the data locally. The next time the browser is online, Chrome syncs the data. Even if a user disables syncing, storage.sync will still work. In this case, it will behave identically to storage.local.

Warning: Confidential user information should not be stored! The storage area isn’t encrypted.

DesktopCapture Link to heading

Triggers warning: using this function also allows to audio to be recorded Desktop Capture API that can be used to capture content of screen, individual windows or tabs.

Screenshots can be beneficial in spying on users, getting immediate view to what they are doing or typing, including passwords or other personal information For example as shown by Talos, Magnat malware campaign delivered both a backdoor and a banking trojan extension that steals user data in order to get bank credentials via screenshots, form grabbing and keylogging. As we can see in the pictures, the screenshots are meant to only be taken on payment websites such as paypal, binance or coinbase.

(pictures taken from

webRequest Link to heading

Intercept and modify outgoing web requests

The combination of the webRequest and the <all_urls> permissions is very powerful. Together, these two permissions make it possible for the extension to intercept any web request and could enable methods for a bot or infostealing.

In the code above, a listener is added to “webRequest.onBeforeRequest” to get the request body, so the contents of it can be parsed and fields extracted.

chrome.webRequest.onBeforeRequest.addListener This can be used to parse all web requests, apply filters, and access information on them—before they are encrypted and sent over https. (For example, this could mean stealing passwords as they are entered in login pages: )

This JavaScript has the ability to parse the page presented on the current active tab, and access the DOM objects on it. Such objects include fields used for entering personal information and username and password.

This example is taken from an extension that built parsing to login pages of Google, eBay, Walmart, and other. The extension steals login details and then sends them back to the attacker with a POST message with their postData function (in this case the “themes” variable holds the passwords and username).

Another interesting capability of “webRequest” permission is accesing the URL of the current tab, and changing its parameters or even redirecting it to a different URL. This can used to inject parameters to the URL—for example affiliate tags in ecommerce websites—or to redirect from a legitimate site to a phishing page where credit card data is vulnerable.

Updating the URL looks something like this:

Blocking: interestingly, “blocking,” though it seems it would be beneficial, is just a parameter that can be added to the “webRequest.addListener”, and it means that the request is blocked until the function of the listener completes its task.

This can also be used to remove security headers (which are security defenses in web browsers) from the web requests, before the request is sent—allowing the malicious extension to grab all of the passwords a user enters in any website in plaintext. The user will not see that anything has changed, and the green lock icon next to the https will remain untouched.

Demonstration of removing security headers, by Lilly Chalupowski:

Tabs Link to heading

From Google’s documentation:: gives your extension access to privileged fields of the Tab objects used by several APIs including chrome.tabs and In many circumstances, your extension will not need to declare the “tabs” permission to make use of these APIs.

What they actually mean: a lot of “tab” functions are available to use even without specifying the “Tabs” permission in the manifest file. So, when is it actually necessary to declare this permission?

When using more sensitive methods, such as: tabs.query against four sensitive properties on tabs.Tab instances: url, pendingUrl, title, and favIconUrl. tabs.captureVisibleTab (take a screenshot of your open tab), tabs.executeScript, tabs.insertCSS, and tabs.removeCSS As an example, this is how Magnat uses webRequest & tabs permissions (from Talos blog):

ActiveTab Permission Link to heading

activeTab does not trigger any warnings. It basically has the ability to do whatever “tabs” can do, but is distinguished by the fact that it can only do that in the current active tab. Otherwise it should have asked for explicit permission to execute on specific/all URLs and execute itself on each tab.

In the documentation, it appears to be a positive thing, because with “only” the activeTab permission, the extension isn’t able to automatically access all URLs all of the time. When using “activeTab,” it only gets access when a user actively uses the given tab, and the permission is valid only until the tab is closed or navigated.

The problem is that activeTab has all the same capabilities as Tabs, and by using questionable actions every tab can become an active tab. Moreover, there are no warnings about this permission.

From Google’s documentation: “Tabs” could also control what happens when a user opens specific tabs, like the extension management tab. Attackers can abuse this by checking the tab’s URL in order to prevent users from ever reaching this tab—and deny them from the option to uninstall the extension, by closing the tab or by redirecting to a different URL (for example, “chrome://settings”).

Infostealing – example Link to heading

It is very simple to build a scraper for chosen websites, and then to track the username and password fields, and add an event listener that waits on “click” on the login button, at which point the credentials would already be present in the boxes. Then the attacker can grab those values and send them to the command and control server.

clipboardRead & clipboardWrite Link to heading

Required if the extension uses document.execCommand(‘paste’)or document.execCommand(‘copy’) or document.execCommand(‘cut’). As the name suggests, it is possible to take clipboard data. There are many more permissions to learn about, but they will be covered in another post.

Interesting methods beyond permissions Link to heading

Alter page view & modify content presented on the page:

document.addEventListener(..,function(e)) { ..
chrome.runtime.sendMessage( ..
e.srcElement.innerHTML = e.srcElement.innerHTML.replace() .. )}):
window.getSelection() - what the user marked and selected on the tab

It is possible to steal form data without even using permissions, just by running content scripts on all URLs

Manifest file:

Listen to form submit and send user password to telegram bot (this is the entirety of the code):

Keylogger Link to heading

also only based on content scripts using “document.onkeypress”, “get.keyCode”

Different ways to execute code that are not “eval()” Link to heading

  • chrome['tabs']['executeScript']({code: xhr_obj['responseText']})
    • chrome.tabs.executeScript({file: "script.js"})
  • url:“javascript:” + code (for example: “javascript:alert(‘a’)” )
  • document.createElement("script")
  • using old vulnerable JavaScript libraries, with known vulnerabilities that can be exploited (example of exploiting AVG browser extension on XSS found in it:

How To Detect Link to heading

We hope by now you realize the huge risk that lies within browser extensions. If you want to control or disable them in your organization – know that you can! There are a couple of ways to do so.

  • If you use Google Workspace- you can block extensions for all users in the organization or create a whitelist with only specific trusted (by you) extensions.
  • For Microsoft users go to Microsoft Endpoint Manager admin center console to create a profile to deploy group policy with restrictions.
  • You can also scan with scripts the computers in the organization to hunt local non-store extensions and identify which extensions are installed and where. Extensions that are installed from the chrome store are always under the same path, depends on the browser (for example in Chrome AppData\Local\Google\Chrome\User Data\Default\Extensions). Each extension has a unique extension ID that you can identify in the Chrome Web Store.
  • Firefox allows administrators to disable the installation of any extensions via the Windows registry and group policy. Mozilla publishes group policy templates for setting a variety of Firefox settings.
  • An admin can block all extensions, use a blacklist to block known malicious extensions, or use a whitelist approach or force the installation of required extensions. The use of group policy is the best approach for Edge.

If your AV or EDR solution sends an alert about commandline with “–load-extension”, you now know what’s behind it. IOCs and installation tracks can be found at:



File system:

AppData\Local\Google\Chrome\User Data\Default\Extensions
AppData\Local\Microsoft\Edge\User Data\Default\Extensions
AppData\Local\Google\*_Chromium_based_*\User Data\Default\Extensions

unofficial extensions would be found outside of the default browser directories: .crx,.xpi or fully unpacked with manifest file and javascripts in the same folder

Group policy:

  • Computer Configuration > Administrative Templates > Google > Google Chrome > Extensions
    • look for or create: “Extension management settings.” If “Configure the list of force-installed apps and extensions” is enabled and there is data on it (extensions IDs), it means that the group policy was used to force-install extensions. The action does not require user interaction or consent.
  • Also chrome.adm - it is possible to install group policy templates, which come in the format of “.adm” files. Those policies can change a lot of settings on the computer, including the extensions policy and forced-installation or allow-list. Applying the policy might produce commandline of “enable local gpo” or “secedit /configure”.