Is Browser History Plus safe?

High risk

Browser History Plus is high risk. After a consent prompt, AI search collects your 100 most recent history entries (URL, title, visit time) and sends them to browserhistory.net with a persistent user ID and tracking token. The same IDs are reused on every later search.…

BrowserHistory+v1.0.6Chrome Web Store
77Risk

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

Publishers can request a review.

Findings

AI Search Sends Full Browsing History to Remote Server

After a consent prompt, AI search collects your 100 most recent history entries (URL, title, visit time) and sends them to browserhistory.net with a persistent user ID and tracking token.

The same IDs are reused on every later search.

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

You click the AI search button after accepting the consent prompt.

A one-time consent modal must be accepted before the first AI search fires.

The extension did this

Retrieves your 100 most recent history entries and POSTs them, with URLs, titles, visit times, a persistent user ID, and a server-assigned hash, to browserhistory.net/api/generate.

The request body can exceed 21 KB and is sent in plaintext JSON.

Captured request
POSThttps://browserhistory.net/api/generate

Returns array of integer indices into indexed_history identifying relevant entries. DA confirmed: POST body was 21,180 bytes and contained 63 real browsing history items plus a planted marker entry.

Headers
Content-Type
application/json
Body
{  "model": "gemma3",  "indexed_history": [    {      "index": 0,      "title": "GitHub",      "url": "https://github.com",      "hostname": "github.com",      "lastVisitTime": 1749081000000    },    {      "index": 1,      "title": "Stack Overflow",      "url": "https://stackoverflow.com/questions/12345",      "hostname": "stackoverflow.com",      "lastVisitTime": 1749080900000    }  ],  "query": "a planted marker value",  "userId": "b85c489c-b404-4992-b6a2-e8703beb4783",  "userHash": "eyJ1c2VySWQiOiJiODVjNDg5Yy1iNDA0LTQ5OTItYjZhMi1lODcwM2JlYjQ3ODMifQ==",  "version": "1.0",  "stream": false,  "options": {    "temperature": 0.3,    "top_p": 0.9  }}
Fields sent in every AI search request
  • History (URL, title, timestamp)
    {index:0, url:'https://github.com', title:'GitHub', hostname:'github.com', lastVisitTime:1749081000000}

    Up to 100 of your recent browser history entries, with every URL visited, the page title, and the exact time of each visit.

  • Persistent user ID
    b85c489c-b404-4992-b6a2-e8703beb4783

    A randomly generated ID created on install that never changes. It ties every AI search, now and future, to the same server identity.

  • User hash (server-assigned token)
    eyJ1c2VySWQiOiJiODVjNDg5Yy1iNDA0LTQ5OTItYjZhMi1lODcwM2JlYjQ3ODMifQ==

    A secondary token assigned by the server during first-run setup. Sent alongside the userId in every AI search request.

  • Search query
    github account security settings

    The text you typed into the AI search box.

  • Extension version
    1.0

    The installed version number, sent with every request.

The code that does this

executeAiSearch(), how the history is collected and sent

Readable version

getAllHistoryItems — readable form

history.js
function getAllHistoryItems() {  return new Promise(function(resolve) {    chrome.history.search({      text: "",      startTime: 0,      endTime: Date.now(),      maxResults: 100    }, function(items) {      resolve(items || []);    });  });}

sendToAiServer — readable form

history.js
async function sendToAiServer(query, indexedHistory, userId, userHash) {  const response = await axios.post(`${baseUrl}api/generate`, {    model: "gemma3",    indexed_history: indexedHistory,  // full history array    query: query,    userId: userId,       // persistent local ID    userHash: userHash,   // server-assigned token    version: "1.0",    stream: false,    options: { temperature: 0.3, top_p: 0.9 }  });  return response.data;}
Where your browsing history is sent
    • browserhistory.net

    Receives full browsing history arrays, search queries, and persistent user/tracking identifiers. Operates a Gemma3 LLM instance that processes history contents server-side.

Extension Registers Persistent Tracking ID with Remote Server on Install

On install, and weekly after, the extension contacts browserhistory.net and registers a persistent identifier tied to your browser.

The server returns a userId and tracking token, stored locally and sent with every AI search.

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

You install the extension.

No further interaction is required, the tracking registration fires automatically.

The extension did this

The service worker POSTs a persistent browser identifier to browserhistory.net/init and stores the server-assigned userId and userHash returned in the response.

This call also repeats automatically once per week, keeping the server record active.

Captured request
POSThttps://browserhistory.net/init

200 OK, server returns {userId, userHash, installDate}. DA confirmed 2 GET/POST requests to /init immediately on extension activation (during dynamic analysis). The assigned userId subsequently appeared in 3 GET requests to /api/tags.

Headers
Content-Type
application/json
Body
{  "userId": "4c9d96be-6ae0-4f00-976c-5ac903b7628d"}
The code that does this

FETCH_INSTALL_DATE, automatic init call on install and weekly thereafter

Readable version

FETCH_INSTALL_DATE — readable form

background.js
async function FETCH_INSTALL_DATE({ state, commit }) {  const installDate = state.storage.user.installDate;  const now = new Date();  const isStale = !installDate || (now - new Date(installDate)) > 6048000; // 7 days  if (state.storage.user.installDate && !isStale) return;  try {    const manifest = chrome.runtime.getManifest();    const initUrl = `${manifest.homepage_url}init`; // https://browserhistory.net/init    const body = {};    if (state.storage.user.id) body.userId = state.storage.user.id;    const response = await axios.post(initUrl, body);    if (response.status === 200) {      const data = response.data;      if (data.installDate) {        let installDate = data.installDate;        if (typeof data.installDate === 'number') {          installDate = new Date(data.installDate * 1000).toISOString();        }        commit('SET_INSTALL_DATE_SYNC', installDate);        commit('SET_INSTALL_DATE', new Date().toISOString());      }      if (data.userId)   commit('SET_USER_ID', data.userId);      if (data.userHash) commit('SET_USER_HASH', data.userHash);    }  } catch (e) { /* silently ignored */ }}

initStorage — userId generation on first install

background.js
initStorage() {  // Fires immediately on construction (before onInstalled)  store.state.loaded.then(() => {    if (!store.state.storage.user.id) {      // Math.random().toString(36) + Date.now().toString(36)      store.commit('SET_USER_ID', generateRandomId());    }  });}
What's stored on your device

Written to storage on install; persists across restarts. userId/userHash reach the server every search, linking future ones to this ID.

Location
chrome.storage (Vuex persisted state, user namespace)
Contents
{  "user.id": "4c9d96be-6ae0-4f00-976c-5ac903b7628d",  "user.userHash": "<server-assigned token>",  "user.installDate": "2026-06-04T23:33:53.000Z",  "user.installDateSync": "2026-06-04T23:33:53.000Z"}
Destination for the registration request
    • browserhistory.net

    Receives the browser's persistent userId on install and weekly after. Returns a userId, userHash, and installDate used to track this browser across future AI search requests.

What it can do

Permissions this extension asks for, as declared in version 1.0.6. 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 every site you visit

    <all_urls>

  • Store data in your browser

    storage

  • Read and change your full browsing history

    history

  • Clear your browsing history, cache and cookies

    browsingData

  • Start, monitor and manage your downloads

    downloads

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

    cookies

  • Schedule its own background tasks

    alarms

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

    tabs

Updated 21 September 2026adjifobelhoemalljgnjdlockheiacmc