# Searchjacking

> Searchjacking is the takeover of a browser's default search engine, usually by an extension, so every query passes through an operator's server first.

Also known as: Search hijacking, Browser search hijacking, Search hijacker, Search engine hijacking

Source: https://socket.dev/glossary/searchjacking

Last updated: 2026-11-09

Searchjacking, also called search hijacking, is the takeover of a browser's default search engine, usually by an extension, so every query reaches an operator's server before a real search engine. The operator logs the query, appends a Yahoo or Bing partner ID to earn syndication revenue, and decides per request where the user lands.

The most important fact about searchjacking is that it needs no code. In our [Searchjacked](https://socket.dev/blog/searchjacked) investigation, published in October 2026, we tracked 319 extensions, installed by roughly 13.4 million users since 2016, that exist only to capture search queries. Many are a manifest.json file and three icons. Chrome treats that shape as the least risky kind of search extension: the install prompt names a domain, and Chromium skips its later "Change back to Google Search?" dialog for it.

Our position: an extension whose only function is to route your searches through an operator's server, hidden from store search and pushed through junk ads, is [malware](https://socket.dev/glossary/malware), not a merely unwanted program. A permission review scores it as harmless, because the harm lives on the server, where the destination of every query is decided after install and after store review. Browsers should tell users where their searches end up, not just which domain receives them first.

## How does a browser decide where a search goes?

A browser decides where a search goes by filling a URL template. When you type words that are not a URL into the address bar, the browser substitutes them for `{searchTerms}` in the default engine's template and navigates there. The search engine is just that string.

Partner deals ride inside the template. A [2015 Mozilla bug](https://bugzilla.mozilla.org/show_bug.cgi?id=1147147) that updated the Yahoo partner build of Firefox set this search URL:

```text
https://search.yahoo.com/yhs/search?ei=UTF-8&fr=chrf-yff37&hspart=mozilla&hsimp=yhs-002&p={query}
```

`hspart=mozilla` and `hsimp=yhs-002` identify the partner that delivered the search, so Yahoo knows whom to pay. Keep those two fields in mind. Searchjackers use exactly the same ones.

Chrome resolves the effective engine from layers. Chromium's search engine code names five sources: a country fallback, the user's choice, an extension override, mandatory enterprise policy, and recommended enterprise policy. An extension override beats the user's choice, and mandatory policy beats the extension.

Browsers defend the user's stored choice against tampering. Chromium signs sensitive preferences with HMACs in its Secure Preferences file. As of November 2026, Chromium's source also keeps a mirrored copy of the default engine and [resets a tampered one](https://chromium.googlesource.com/chromium/src/+/main/components/search_engines/default_search_manager.cc) on Windows and macOS, a feature named `kResetTamperedDefaultSearchEngine` that is enabled by default. That is why older hijackers had to work hard. Microsoft's [analysis of Adrozek](https://www.microsoft.com/en-us/security/blog/2020/12/10/widespread-malware-campaign-seeks-to-silently-inject-ads-into-search-results-affects-multiple-browsers/) in December 2020 found it patching the browser's integrity check with a two-byte change, and it hit over 30,000 devices a day at its August 2020 peak.

Searchjacking skips every one of those defenses. Chrome's [extension quality guidelines](https://developer.chrome.com/docs/extensions/mv3/quality_guidelines) say it plainly: "The only supported way to change the default web search settings using an extension is via the Settings Overrides API." The integrity checks guard the user's own setting. The extension layer above it is the sanctioned path, and it needs no forgery.

## How do browser extensions hijack searches?

Browser extensions hijack searches by declaring a `search_provider` block under `chrome_settings_overrides` in manifest.json, with `is_default` set to `true`. Apart from three icon files, this manifest is the entire [Safe Game Search](https://socket.dev/blog/searchjacked) extension from our research:

```json
{
  "update_url": "https://clients2.google.com/service/update2/crx",
  "manifest_version": 3,
  "version": "1.1",
  "name": "Safe Game Search",
  "short_name": "Game Safe Search",
  "description": "Real-time safety alerts for game searches and risky game websites",
  "default_locale": "en",
  "icons": {
    "16": "icon16.png",
    "48": "icon48.png",
    "128": "icon128.png"
  },
  "chrome_settings_overrides": {
    "search_provider": {
      "name": "Safe Game",
      "keyword": "Safe Game Search",
      "is_default": true,
      "encoding": "UTF-8",
      "favicon_url": "https://safesearchgame.com/favicon.ico",
      "search_url": "https://search.safesearchgame.com/query?q={searchTerms}",
      "suggest_url": "https://suggest.safesearchgame.com/querying/autocomplete?query={searchTerms}"
    }
  }
}
```

There are no permissions, no service worker, no content scripts, and no UI. Nothing in the package executes. The browser does all the work, and the operator's server does the rest. That is why [browser extension security](https://socket.dev/glossary/browser-extension-security) reviews that start from the permission list find nothing to flag.

Chrome checks a search override at three points. Each check is weaker than it looks.

**The install prompt names a host, not a destination.** Chrome converts the override into an internal permission whose warning reads "Change your search settings to:" followed by the host from `search_url`, minus any `www.` prefix. For Safe Game Search the user sees `search.safesearchgame.com`, which looks like a search engine. Nothing says the server forwards queries to Yahoo, records them, or can send them anywhere else.

**Domain verification proves ownership, not behavior.** Chrome's [settings override documentation](https://developer.chrome.com/docs/extensions/mv3/settings_override/) requires the publisher to verify the `search_url` domain in Google Search Console. That shows the publisher controls the proxy. It says nothing about what the proxy does with a query.

**The post-install dialog exempts exactly this shape.** Chrome can ask "Change back to Google Search?" after an extension takes over search. Chromium skips that dialog for a "simple override" extension, one whose manifest contains only keys from a [fixed allowlist](https://chromium.googlesource.com/chromium/src/+/main/chrome/browser/ui/extensions/extensions_overrides/simple_overrides.cc) such as `name`, `icons`, `default_locale`, `update_url`, and `chrome_settings_overrides`. The source comment says those keys must not give the extension "*any* additional capability" beyond what the site would have if the user changed search by hand. A Chromium [browser test](https://chromium.googlesource.com/chromium/src/+/main/chrome/browser/ui/extensions/settings_overridden_params_providers_browsertest.cc) spells out the consequence: a manifest-only override gets no dialog, and an update that adds `"permissions": ["storage"]` makes the dialog appear.

That allowlist is where the trust assumption breaks. It treats the search host as a site the user picked. In searchjacking, the user picked a "PDF finder" from a pop-under ad, and the host is a redirector run by someone else. Applying the [least privilege principle](https://socket.dev/glossary/least-privilege-principle) to the browser makes the extension look ideal, because it can do almost nothing locally. All of its power is on the server.

You can check any manifest against Chrome's rules. This script reproduces the install warning and the simple-override test from Chromium's source:

```python
#!/usr/bin/env python3
"""Report what Chrome will show for an extension that overrides default search."""
import json, sys
from urllib.parse import urlsplit

# Keys Chromium accepts in a "simple override" extension, from
# chrome/browser/ui/extensions/extensions_overrides/simple_overrides.cc
SIMPLE_OVERRIDE_KEYS = {
    "author", "about_page", "current_locale", "default_locale", "description",
    "differential_fingerprint", "homepage_url", "icons", "icon_variants", "key",
    "manifest_version", "minimum_chrome_version", "name", "offline_enabled",
    "options_page", "options_ui", "chrome_settings_overrides", "short_name",
    "update_url", "version", "version_name", "incognito",
}

manifest = json.load(open(sys.argv[1], encoding="utf-8-sig"))
sp = manifest.get("chrome_settings_overrides", {}).get("search_provider")
if not sp:
    sys.exit("no search_provider override")

host = urlsplit(sp["search_url"]).hostname.removeprefix("www.")
extra = sorted(set(manifest) - SIMPLE_OVERRIDE_KEYS)

print(f"search_url:      {sp['search_url']}")
print(f"is_default:      {sp.get('is_default')}")
print(f"install warning: Change your search settings to: {host}")
print(f"permissions:     {manifest.get('permissions', [])}")
print(f"simple override: {not extra}" + (f" (extra keys: {extra})" if extra else ""))
```

Run against Safe Game Search, and against the same manifest with one permission added:

```console
$ python3 check_search_override.py safe-game-search/manifest.json
search_url:      https://search.safesearchgame.com/query?q={searchTerms}
is_default:      True
install warning: Change your search settings to: search.safesearchgame.com
permissions:     []
simple override: True

$ python3 check_search_override.py with-storage/manifest.json
search_url:      https://search.safesearchgame.com/query?q={searchTerms}
is_default:      True
install warning: Change your search settings to: search.safesearchgame.com
permissions:     ['storage']
simple override: False (extra keys: ['permissions'])
```

Chromium is removing the exemption, slowly. The dialog code now reads: "Historically, 'Simple Overrides' were exempt from this dialog. We are removing that exemption." The change sits behind a feature named `kSearchEngineUnconditionalDialog`. As of November 2026, that feature is disabled by default in Chromium's main branch, and the [code](https://chromium.googlesource.com/chromium/src/+/main/chrome/browser/ui/extensions/extension_settings_overridden_dialog.cc) grandfathers extensions installed before enforcement begins.

Firefox draws the line differently. [MDN](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/chrome_settings_overrides) says `is_default` "is opt-in and the user will only be asked the first time the extension is installed," and Firefox requires `search_url` to use HTTPS. Chrome's manifest parser accepts `http` or `https`. Chrome documents the settings override API as available on Windows and Mac.

## Why do searchjackers route queries through a proxy?

Searchjackers route queries through a proxy because the proxy is where the money, the data, and the control sit. Yahoo and Microsoft run search syndication programs that share ad revenue with partners who bring them searches. Yahoo identifies the partner with `hspart` and `hsimp`, the same fields in Firefox's 2015 template. Bing uses a `PC` partner code and a `PTAG` sub-ID.

An extension could put its partner tags straight into `search_url`. The operators we tracked point `search_url` at their own server instead, which then redirects. That indirection buys three things:

- **An accounting record.** The operator can reconcile its own count of searches against what Yahoo or Bing pays.
- **A complete capture point.** Every query passes through the operator's server, often tied to a unique identifier. That is [telemetry](https://socket.dev/glossary/telemetry) whose payload is the user's full search history.
- **A programmable redirect.** The destination is chosen on the server, per request, after install and after review.

[Predator Search](https://socket.dev/blog/searchjacked), an extension with 50,000 users, shows the third point in practice. We sent six identical searches through its proxy, and they ended in four different places.

> Figure 1. The extension never changed between searches. The proxy chose each destination as the query arrived.
>
> How a searchjacking proxy decides, per request, where a search ends up

Figure 1 in text: a query typed in the address bar goes first to the operator's proxy, which logs it, often tied to a unique identifier, and redirects it to a destination chosen for that request. For Predator Search, six identical searches produced four outcomes: Yahoo results tagged `hspart=sz&hsimp=yhs-026`, a landing page on searchlio.net, a hop through searchtosearch.com to a second results domain, mcftink.com, and then Yahoo, and a Cloudflare non-responsive error page. The extension never changed between searches. The same mechanism could serve a phishing page or malware lure for chosen queries, regions, or users; we did not observe that in this set.

The redirect is the dangerous part. A proxy that sends almost every search to real Yahoo results can send one chosen query, or every query from one IP range, to a [phishing](https://socket.dev/glossary/phishing) page. That works like a traffic distribution system, and it needs no extension update, so no store review or update check ever sees it. In our Searchjacked research, most redirects only appended partner tags. We also saw a repeated search redirected to Google's homepage without partner tags, while other searches still went to Bing. Selection per request is already happening.

## How searchjacking extensions get installed and stay hidden

Searchjacking extensions are pushed, not found. Most of the ones we tracked are unlisted in the Chrome Web Store, so anyone with the link can install them but store search never shows them. Users arrive through low-quality pop-over and pop-under ads that promise to "Search PDFs" or "Find Manuals," land on a branded page with one install button, and sometimes get redirected to the listing automatically.

The operators work at volume. [Intango LTD](https://socket.dev/blog/searchjacked) has published about 111 extensions since 2018, reaching roughly 2.2 million installs across about 279 domains. Each extension got its own domain and its own admin@ mailbox, so every listing looked like an independent small publisher. The 2024 [SecuryBrowse wave](https://socket.dev/blog/searchjacked), first documented by [Secure Annex](https://secureannex.com/blog/searching-for-something-unknow), accounts for 58 extensions and about 4.9 million users, with security brands such as "Fire Shield" and "WatchTower." Counted as one extension, the 319 we tracked would rank among the top 25 Chrome extensions by users.

Takedowns do not end a campaign. Domains often stay live after their extensions are removed, and new lures appear quickly. Finding the operators is a [threat intelligence](https://socket.dev/glossary/threat-intelligence) problem: we pivot from the extension ID in the store URL to the company named in its privacy policy, then to Google Ads Transparency to see every ad that advertiser buys, and use Censys and urlscan queries to fingerprint landing pages at scale.

The most durable [indicators of compromise](https://socket.dev/glossary/indicators-of-compromise-ioc) are partner IDs, not domains. Domains rotate per extension, while a syndication account is what gets paid. `hspart=iba` marks Intango's Yahoo account, and Bing `PC=3QCV` and `PC=3CGP` mark the SecuryBrowse cluster. One partner ID can tie dozens of unrelated-looking listings to one operator.

## Searchjacking vs. SEO poisoning, affiliate hijacking, and browser hijackers

Searchjacking is often confused with neighboring techniques that also abuse search or browsing for money. The difference is what the attacker controls and whether anything runs in the browser.

| Technique | What the attacker controls | How it works | Code in the victim's browser | Example |
| --- | --- | --- | --- | --- |
| Searchjacking | The default search engine | A chrome\_settings\_overrides entry points search at a proxy that logs each query and redirects it | None needed | 319 Searchjacked extensions, about 13.4 million users |
| SEO poisoning | Where attacker pages rank in genuine search results | Manipulating the signals search engines use to rank pages | None; nothing is installed | Catalogued as MITRE ATT&CK T1608.006 |
| Affiliate hijacking | The commission on a purchase | A content script rewrites shopping links to carry the operator's affiliate tag | Content scripts and host permissions | Amazon Ads Blocker injected the tag 10xprofit-20 |
| Browser modifier malware | Browser settings, files, and binaries | Native malware edits preference files and patches integrity checks | Native malware on the machine | Adrozek, over 30,000 devices a day in August 2020 |

The affiliate hijacking row comes from our analysis of [Amazon Ads Blocker](https://socket.dev/blog/malicious-chrome-extension-performs-hidden-affiliate-hijacking), which rewrote Amazon links to carry its own tag. It needed content scripts and host permissions. A searchjacker needs neither.

Two named reports share the root word, and neither is the technique itself. SearchJack is [MalExt Sentry's June 9, 2026 report](https://malext.io/reports/SearchJack/) on 23 Chrome extensions from 22 publishers with about 758,000 users. Searchjacked is our October 2026 report on 319 extensions. Both describe searchjacking campaigns.

A new-tab extension with a search box is not automatically searchjacking. In the [152 live wallpaper extensions](https://socket.dev/blog/152-chrome-live-wallpaper-extensions-hid-ad-tracking) we analyzed, the search box called `chrome.search.query` with no engine override, which sends the query to whatever engine the user already set.

## How do you detect and remove searchjacking?

You detect searchjacking by checking who controls the default search engine, and you remove it by removing that extension. In Chrome, open Settings and look for a box that reads "An extension, \[extension name\], is controlling this setting." Google's [help page](https://support.google.com/chrome/answer/6029416) says that when you remove the extension, your settings return to how they were before you installed it. You cannot keep the extension and refuse its change.

Then confirm the fix by searching and watching the first URL. If the first hop is not your engine, something else still controls search. Treat the extension as a breach of your search history, not a preference glitch: every address-bar search you made while it was installed went to its operator.

To find search overrides across a machine, grep the installed manifests. On macOS, Chrome keeps one directory per extension version under each profile:

```bash
grep -l '"search_provider"' \
  ~/Library/Application\ Support/Google/Chrome/*/Extensions/*/*/manifest.json
```

On Windows, the same tree is under `%LOCALAPPDATA%\Google\Chrome\User Data`. Any hit deserves a look at its `search_url` host and at where that host redirects.

On a managed fleet, lock the engine with policy. Setting `DefaultSearchProviderEnabled` to true and `DefaultSearchProviderSearchURL` to an approved HTTPS template makes policy the controlling source. Chromium's [own code](https://chromium.googlesource.com/chromium/src/+/main/chrome/browser/ui/extensions/settings_overridden_params_providers.cc) says a default engine "set (or disabled) by mandatory enterprise policy takes precedence over the extension's."

Every control has a cost and a blind spot:

| Control | What it catches | What it misses |
| --- | --- | --- |
| Chrome install warning | Names the search host the extension will use | Where that host forwards queries, and who operates it |
| "Change back?" dialog | Search overrides bundled with other capabilities | Simple overrides, unless kSearchEngineUnconditionalDialog is enabled; extensions installed before enforcement |
| Permission review | Extensions that request risky browser APIs | Searchjackers, which request none |
| Store review and Search Console verification | Policy violations at submission, and who owns the search domain | Server-side behavior after approval |
| DefaultSearchProviderSearchURL policy | Every extension override on managed browsers | Unmanaged browsers and personal profiles; users lose engine choice |
| Static analysis of the package | The search host and any hard-coded partner tags | Which destination the proxy picks for each query |
| Live redirect testing | Partner IDs and destinations the proxy actually serves | Destinations served only to chosen users, regions, or queries |

Verdict: on a managed fleet, set the search policy, because it is the only control that makes every override irrelevant. Everywhere else, judge a search extension by where its `search_url` redirects, not by its permission list.

Static analysis has a limit too, including ours. Socket's [Chrome extension analysis](https://socket.dev/blog/socket-now-protects-the-chrome-extension-ecosystem) reads an extension's manifest and code and flags risky updates. That shows the `search_url` host and any partner tags hard-coded in the package. It cannot show which destination the proxy picks for a given query. In the Searchjacked research, that took sending live searches through each proxy.

## The fix belongs in the browser

Chromium's planned dialog would still name the extension's search host, the same host the install prompt shows. Neither tells the user whether a host like `search.safesearchgame.com` is a search engine or a redirector that resells each query under someone else's partner ID. The browser is the one party that sees the whole chain on every search, because it follows each redirect. Until it shows users where their searches actually end up, and treats a search host that redirects as behavior worth judging, searchjacking stays a manifest away.
