Is Bing Search and Homepage safe?

High risk

Sets the browser homepage to Bing.com and adds one-click Bing search for highlighted text.

This extension sets your homepage to Bing.com so you can access Bing content such as news, entertainment, and sports. It also lets you highlight text on any website and search that text on Microsoft Bing with one click.

Microsoft Corporationv1.0.0.2Chrome Web Store
78Risk
Who publishes it

Microsoft Corporation - 3 other listings from the same operator, none carrying a finding

What this publisher told the store about itself, and the other listings that told it the same thing.

Publisher
Microsoft Corporation
Declared legal entity
Microsoft Corporation
Registered address
One Microsoft Way, Redmond, WA 98052-8300, US
Registered contact
Microsoft Corporation

Same operator - 3 listings

Published under a different store account, but sharing the registered address, contact or declared legal entity this one gave the store.

Shared hosts - 2 hostnames

Hostnames hardcoded in this extension that few other listings call. That can mean one operator behind both, and it can equally mean a small shared vendor, so it is context rather than a conclusion. Hosts that many listings call are left out: they are services, not connections.

browserdefaults.chinacloudsites.cn
Also called by 2 other listings: Microsoft Bing Search with Rewards, Microsoft Bing Search for Chrome
services.bingapis.com
Also called by 2 other listings, including Microsoft Bing Search with Rewards

AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.

Publishers can request a review.

Findings

Server-Controlled QuickSearch Template Fetched and Rendered Into Pages

On install and every ~4h, the extension fetches a config from go.microsoft.com/fwlink setting QS_TEMPLATE_URL, then renders HTML from that URL on QuickSearch pages.

Two installs showed it pointing to bgextnfal.azurewebsites.net in 30s.

Severity
High unwanted
Type
Unexpected
CWE
CWE-829
Source
Dynamic sandbox
What actually happens
You did this

You install the extension (or four hours pass since the last config refresh).

The 'GetExtensionConfig' alarm is registered with periodInMinutes set from the server response (default 240 minutes) and re-runs the same fetch.

The extension did this

The extension downloads a config from a Microsoft fwlink redirect, then downloads HTML from the URL that config names, and stores it for QuickSearch to render.

The fwlink URL redirects to a settings server. The response is parsed into an ExtensionSettings object whose QuickSearchSetting.TemplateUrl becomes QS_TEMPLATE_URL in chrome.storage.local. A subsequent fetch retrieves HTML from that URL with no allowlist restricting the host.

Values written to chrome.storage.local from the server's config (two fresh-profile DA runs)
  • QuickSearch template URL
    https://bgextnfal.azurewebsites.net/quicksearch/extension/DarkTheme

    The URL the extension downloads HTML from and renders inside pages. Whoever controls the config response controls which host this points at.

  • QuickSearch enabled flag
    true

    Whether the QuickSearch overlay activates on supported sites. Server-toggled.

  • QuickSearch domain blacklist
    bing.com, microsoft.com, login.live.com, ...

    Sites where QuickSearch will NOT inject. Server-supplied; 12 entries observed including bing.com.

  • Aria telemetry API key
    0d332259610f4882936afe711f6ec9e9-...

    API key the extension uses to authenticate Aria/Bond telemetry uploads to pipe.aria.microsoft.com.

  • App Insights instrumentation key
    0d332259-610f-4882-936a-fe711f6ec9e9

    Identifier the extension attaches to Application Insights telemetry events.

The code that does this

The config fetch and HTML-render path, from background.bundle.js.

Readable version

Config fetch URL

// Server-controlled config endpoint. linkid=2247613 redirects to the// current Microsoft settings server.const TRIGGERCONFIGURL =  'https://go.microsoft.com/fwlink/?linkid=2247613' +  '&br={browser}&env={env}&extname={extname}&features={features}';

Periodic config refresh

// Runs on install and again whenever the GetExtensionConfig alarm fires.function initTriggerConfig(extname, hostOverride, features) {  const url = formatTriggerConfigUrl(extname, hostOverride, features);  fetch(url, { method: 'GET' })    .then(r => { if (!r.ok) throw new Error(r.statusText); return r.json(); })    .then(json => {      TriggerConfig = new ExtensionSettings(json);      TriggerConfig.initializeStorage();          // writes every server field      chrome.storage.local.get([ARIA_KEY, SIGNIN_STATUS], () => { /* ... */ });    });  // Re-run every API_DELAY_TIMER_IN_MINS minutes (default 240).  chrome.alarms.create('GetExtensionConfig', {    periodInMinutes: storedDelay ?? 240,  });  chrome.alarms.onAlarm.addListener(a => {    if (a.name === 'GetExtensionConfig') initTriggerConfig(extname, hostOverride, features);  });}

QuickSearch settings persist the server-supplied template URL

// Inside QuickSearchSettings.initializeStorage:setLocalStorage('QS_ENABLED',      this.EnableQuickSearch);setLocalStorage('VS_ENABLED',      this.EnableVisualSearch);setLocalStorage('QS_TEMPLATE_URL', this.TemplateUrl); // <-- whatever URL the server returned

readHtmlContent: fetch and cache the template HTML

// Called whenever QS_TEMPLATE_URL is set or its cached copy is older than 24h.// No allowlist on `url` — whatever the config response said is what gets fetched.function readHtmlContent(url, replacements) {  fetch(url)    .then(r => r.text())    .then(html => {      const filled = applyReplacements(html, replacements);      setLocalStorage('QuickSearchTemplateKey', filled);      setLocalStorage('QuickSearchTemplateTimestamp', Date.now());    });}
What's stored on your device

These keys appear in storage within ~30s of install, not in the bundle, evidence the fwlink fetch ran and was parsed.

Location
chrome.storage.local (populated within ~30s of install on a fresh profile)
Contents
{  "ARIA_KEY": "0d332259610f4882936afe711f6ec9e9-3a1b2c4d-...",  "QS_ENABLED": true,  "QS_TEMPLATE_URL": "https://bgextnfal.azurewebsites.net/quicksearch/extension/DarkTheme",  "InstallTimestamp": "Tue, 14 Apr 2026 23:07:29 GMT",  "instrumentationKey": "0d332259-610f-4882-936a-fe711f6ec9e9",  "QS_BLACKLIST_DOMAINS": "bing.com,microsoft.com,login.live.com,outlook.com,office.com,live.com,msn.com,xbox.com,skype.com,linkedin.com,github.com,azure.com",  "API_DELAY_TIMER_IN_MINS": 240}
Hosts involved in this config + render path
    • go.microsoft.com

    Microsoft fwlink redirector. linkid=2247613 resolves to whichever host Microsoft currently serves the extension settings JSON from.

    • bgextnfal.azurewebsites.net

    Azure App Service host returned in QS_TEMPLATE_URL during test runs. Serves the QuickSearch HTML the extension fetches and renders. Hostname is in host_permissions.

    • services.bingapis.com

    Returns the Application Insights instrumentation key used by scripts/telemetry.js (separate from the fwlink config).

Reproduce it yourself

Paste this into the service-worker DevTools console for the extension on a fresh profile. It dumps the keys the remote-config flow writes (QS_TEMPLATE_URL, QS_ENABLED, QS_BLACKLIST_DOMAINS, ARIA_KEY, instrumentationKey) and re-prints them whenever they change, so you can observe the server response landing in storage and confirm what URL the extension would fetch HTML from next.

Requires
  • Chrome with Developer mode enabled
  • Bing Search and Homepage extension installed
watch-bing-config.js · js
// watch-bing-config.js// Run inside the Bing Search and Homepage service-worker DevTools console.// chrome://extensions -> Developer mode -> 'service worker' link for this extension.const KEYS = [  'QS_TEMPLATE_URL', 'QS_ENABLED', 'QS_BLACKLIST_DOMAINS',  'ARIA_KEY', 'instrumentationKey', 'API_DELAY_TIMER_IN_MINS',  'InstallTimestamp', 'XID',];function dump(label) {  chrome.storage.local.get(KEYS, (obj) => {    console.log('[' + label + '] ' + new Date().toISOString());    for (const k of KEYS) console.log('  ' + k + ' =', obj[k]);  });}dump('initial');chrome.storage.onChanged.addListener((changes, area) => {  if (area !== 'local') return;  const touched = Object.keys(changes).filter(k => KEYS.includes(k));  if (touched.length) {    console.log('[changed]', touched);    dump('after-change');  }});// Force the config refresh now instead of waiting 240 minutes.chrome.alarms.create('GetExtensionConfig', { delayInMinutes: 0.05, periodInMinutes: 240 });console.log('Re-armed GetExtensionConfig alarm to fire in ~3s.');
How to run it
  1. 1Install on a fresh profile.
  2. 2Open chrome://extensions, Developer mode, click 'service worker'.
  3. 3Paste the script into DevTools Console.
  4. 4Watch the initial and 3s-later dumps.
  5. 5QS_TEMPLATE_URL is the next fetch URL.

Install flow reads Chrome Web Store attribution cookie

On install, when the channel is 'organic' (default), the extension reads the __utmz cookie from chrome.google.com and parses UTM params for a Google Ads source ('bgads'); if found, an ad channel string is stored for telemetry.

Severity
Medium unwanted
Type
Unexpected
CWE
CWE-200
Source
Dynamic sandbox
What actually happens
You did this

You install the extension from the Chrome Web Store via an organic (non-referred) channel.

The default channel value is 'organic', so this applies to most installs.

The extension did this

The extension reads the __utmz Google Analytics cookie from chrome.google.com to extract install attribution details.

If the UTM source is 'bgads', the campaign parameters are assembled into a channel string and stored locally.

The code that does this

Cookie read and UTM parsing

Readable version

Cookie read — ping.js:226-235

scripts/ping.js:226
if (n.channel === 'organic') {  chrome.cookies.get({ url: chromeWS, name: '__utmz' }, function(cookie) {    if (cookie) {      const channel = getChromeWSChannel(cookie.value);      if (channel !== '') n.channel = channel;    }    resolve();  });} else {  resolve();}

UTM parser — ping.js:303-316

scripts/ping.js:303
function getChromeWSChannel(cookieValue) {  let utmcsr = '', utmccn = '', utmcmd = '', utmcct = '', result = '';  const parts = cookieValue.split('.');  const lastPart = parts[parts.length - 1];  if (lastPart !== '') {    const pairs = lastPart.split('|');    for (const pair of pairs) {      const [key, val] = pair.split('=');      if (key === 'utmcsr') utmcsr = val;      else if (key === 'utmccn') utmccn = val;      else if (key === 'utmcmd') utmcmd = val;      else if (key === 'utmcct') utmcct = val;    }    if (utmcsr === 'bgads') {      result = utmcsr;      if (!['(not%20set)', '(direct)', '(organic)'].includes(utmcmd)) result += '_' + utmcmd;      if (!['(not%20set)', '(direct)', '(organic)'].includes(utmccn)) result += '_' + utmccn;      if (!['(not%20set)', '(direct)', '(organic)', ''].includes(utmcct)) result += '_' + utmcct;    }  }  return result;}
Data extracted from __utmz cookie
  • Campaign source
    bgads

    Identifies which advertising network referred you to the Chrome Web Store (e.g. 'bgads' for Microsoft Bing Ads).

  • Campaign medium
    cpc

    The type of advertising medium used (e.g. 'cpc' for cost-per-click).

  • Campaign name
    BingSearchDefaults_EN

    The name of the advertising campaign that directed you to install the extension.

  • Campaign content
    ad-variant-1

    The specific ad variant or landing page that was clicked.

What's stored on your device

The assembled advertising channel string is stored locally and included in later install and ping telemetry sent to Microsoft.

Location
chrome.storage.local key 'Channel'
Contents
bgads_cpc_BingSearchDefaults_EN

First Bing Search Triggers a Persistent Machine ID Cookie

The first time you use the Bing shortcut, the background script writes a device ID (set once at install) as a Secure, SameSite=None cookie on browserdefaults.microsoft.com.

Confirmed live; no expiration means this happens only once.

Severity
Medium unwanted
Type
Unexpected
CWE
CWE-359
Source
Dynamic sandbox
What actually happens
You did this

You perform your first search through this extension's installed default search provider.

The extension watches for the resulting Bing search-results URL via a tabs.onUpdated listener.

The extension did this

The extension writes the device identifier it generated at install as a cookie on browserdefaults.microsoft.com, a Microsoft domain, not the Bing page you're viewing.

This write happens once: the content script that sends the trigger message is only injected the first time this condition is met after install.

The code that does this

The first-search message triggers the cookie write

Readable version

Trigger: message sent on first qualifying search

scripts/firstSearchNotificationContent.js
chrome.runtime.sendMessage("setMachineID");

Handler: writes the cookie to browserdefaults.microsoft.com

scripts/ping.js
chrome.runtime.onMessage.addListener((function(e) {  "setMachineID" == e && chrome.storage.local.get([MACHINE_ID], (e => {    chrome.cookies.set({      url: browserDefaultsUrl,      domain: ".browserdefaults.microsoft.com",      name: "MachineID",      value: e[MACHINE_ID],      sameSite: "no_restriction",      secure: !0    }, (function(e) {}))  }))}));
What lands in the browserdefaults.microsoft.com cookie
  • Device identifier
    9904285EBF68AF68C18FC8E3651FBA8B

    A random ID generated once when the extension is installed and cached on your device. It stays the same for the life of the install.

  • Cookie domain
    .browserdefaults.microsoft.com

    The identifier is scoped to a Microsoft domain used for browser-default configuration, separate from the Bing search page you're using.

  • Cookie attributes
    secure=true; sameSite=no_restriction

    Secure and SameSite=None mean the cookie is only sent over HTTPS but can still be attached to cross-site requests to that domain.

Where the identifier is readable
    • browserdefaults.microsoft.com

    Microsoft-operated domain used by browser/default-settings flows; can read the MachineID cookie this extension sets on any subsequent request it receives.

What we did and didn't verify

The chrome.cookies.set call does not include an expirationDate, so under Chrome's default cookie behavior this is a session cookie rather than one with an explicit multi-year lifetime. We confirmed the write and the live cookie within a single dynamic-analysis session; we did not test whether it survives a browser restart. The underlying device identifier itself is cached in chrome.storage.local and does not change across restarts, but our code review found only this one call site that writes it to browserdefaults.microsoft.com, and it fires at most once per install.

+2 more findings not shown

What it can do

Permissions this extension asks for, as declared in version 1.0.0.2. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.

  • Read and change your data on www.bing.com

    https://www.bing.com/*

  • Read and change your data on browserdefaults.microsoft.com

    https://browserdefaults.microsoft.com/*

  • Read and change your data on go.microsoft.com

    https://go.microsoft.com/*

  • Read and change your data on dc.services.visualstudio.com

    https://dc.services.visualstudio.com/*

  • Read and change your data on services.bingapis.com

    https://services.bingapis.com/*

  • Read and change your data on chrome.google.com

    https://chrome.google.com/*

  • Read and change your data on browserdefaults.chinacloudsites.cn

    https://browserdefaults.chinacloudsites.cn/*

  • Read and change your data on bgextnfal.azurewebsites.net

    https://bgextnfal.azurewebsites.net/*

  • Read and change your data on browser.pipe.aria.microsoft.com

    https://browser.pipe.aria.microsoft.com/*

  • Read and change your data on us.pipe.aria.microsoft.com

    https://us.pipe.aria.microsoft.com/*

  • Read and change your data on de.pipe.aria.microsoft.com

    https://de.pipe.aria.microsoft.com/*

  • Read and change your data on jp.pipe.aria.microsoft.com

    https://jp.pipe.aria.microsoft.com/*

  • Read and change your data on au.pipe.aria.microsoft.com

    https://au.pipe.aria.microsoft.com/*

  • Read and change your data on eu.pipe.aria.microsoft.com

    https://eu.pipe.aria.microsoft.com/*

  • Read and change your data on pf.pipe.aria.microsoft.com

    https://pf.pipe.aria.microsoft.com/*

  • Read and change your data on tb.pipe.aria.microsoft.com

    https://tb.pipe.aria.microsoft.com/*

  • Read and change cookies, including the ones that keep you signed in

    cookies

  • Block and redirect the requests your browser makes

    declarativeNetRequest

  • See the address and title of every tab you have open

    tabs

  • Schedule its own background tasks

    alarms

  • Store data in your browser

    storage

  • Add items to the right-click menu

    contextMenus

  • Show you desktop notifications

    notifications

  • Run its own code inside the pages you visit

    scripting

  • Talk to a program installed on your computer, outside the browser's sandbox

    nativeMessaging

Where it sends data

Destinations our analysis observed Bing Search contacting. Sending data somewhere is not a finding on its own - an extension that syncs your settings has to talk to its own server - but it is where your data can go, and who else it goes to.

  • bing.com

    Bing Search sends data to bing.com. 4 other extensions we have analysed send data here.

  • Microsoft Bing

    Bing Search sends data to Microsoft Bing. Named as a recipient by 2 other extensions we have analysed.

Updated 30 September 2026dbjdfcppoldjlhknlcolmbockijbfomd