Is Bardeen: Automate Browser Apps with AI safe?

Medium risk

Bardeen is medium risk. Bardeen requests <all_urls> and tracks tab creation, switch, close, navigation, focus change across your whole session, not just automated pages. DA confirmed this live. Full tab history is held in memory for automation; no exfil seen.

Bardeenv5.0.0Chrome Web Store
45Risk
Who publishes it

Bardeen Inc - no other listings under this identity, 1 shared hostname

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

Publisher
Bardeen
Declared legal entity
Bardeen Inc
Registered address
236 Roosevelt Way, San Francisco, CA 94114, US
Registered contact
Bardeen Inc

Shared hosts - 1 hostname

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.

assetsconfigcdn.org
Also called by 5 other listings, including Crystal Knows, Guppy - Collect smarter with AI.

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

Publishers can request a review.

Findings

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-200
SourceAI SANDBOX

Background Worker Tracks Every Tab's URL and Address-Bar Navigation

Bardeen requests <all_urls> and tracks tab creation, switch, close, navigation, focus change across your whole session, not just automated pages.

DA confirmed this live.

Full tab history is held in memory for automation; no exfil seen.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You navigate between pages, switch tabs, or type a URL into the address bar, anywhere on any website.

This includes ordinary browsing that has nothing to do with running an automation.

The extension did this

The background service worker records the full URL, transition type, and tab/window state for every tab in an in-memory session map.

Navigations typed directly into the address bar are explicitly flagged and distinguished from other transition types.

02EvidenceTEMPORAL PATTERN
When this fires
On every browser startup

Tab, window, and navigation listeners are attached once when the background service worker starts and remain active for the whole browsing session -- tracking continues on every site regardless of whether an automation is currently running.

03EvidenceFIELD TABLE
Fields held in each tracked tab session
FieldValueWhy it matters
Full page URL
https://accounts.google.com/signin/v2/identifierEvery page you navigate to, including the exact URL, is captured for every open tab, not just the active one.
Address-bar transition type
typed (from_address_bar)The extension records whether a URL was typed directly into the address bar, reached by a reload, or reached another way.
Tab and window state
active: true, pinned: false, windowId: 912Whether the tab is active, pinned, highlighted, or incognito is tracked alongside its URL.
Tab identifier
1585209824A numeric ID ties every tracked event back to the same browser tab across its lifetime.
04EvidenceCODE COMPARE
The code that does this

Tab/navigation listeners and per-tab session handler, shipped vs. deobfuscated

What it actually does
Unconditional listener registration at service-worker startupbackground.js:6837-6874
chrome.tabs.onActivated.addListener((...args) => {
  return eventQueue.push({ type: "tabs.onActivated", args });
});
chrome.tabs.onUpdated.addListener((...args) => {
  return eventQueue.push({ type: "tabs.onUpdated", args });
});
chrome.tabs.onRemoved.addListener((...args) => {
  return eventQueue.push({ type: "tabs.onRemoved", args });
});
chrome.tabs.onCreated.addListener((...args) => {
  return eventQueue.push({ type: "tabs.onCreated", args });
});
chrome.windows.onRemoved.addListener((...args) => {
  return eventQueue.push({ type: "windows.onRemoved", args });
});
chrome.windows.onFocusChanged.addListener((...args) => {
  return eventQueue.push({ type: "windows.onFocusChanged", args });
});
handleBrowserEvent + handleWebNavigationCommittedbackground.js:7484-7536
this.handleBrowserEvent = (event) => {
  switch (event.type) {
    case "tabs.onRemoved": {
      let [tabId] = event.args;
      this.untrackTab(tabId);
      this.uimodules.handleTabRemoved(tabId);
      this.emit("tab_closed", tabId);
      break;
    }
    case "tabs.onCreated": {
      let [tab] = event.args;
      let session = this.trackTab(tab);
      session && this.emit("tab_created", session.getTabItem());
      break;
    }
    case "tabs.onUpdated": {
      let [tabId, , tab] = event.args;
      let session = this.tabSessions.get(tabId);
      if (session) {
        let newState = session.handleStateChange(tab);
        newState.active && this.emit("active_tab_change", toTabItem(newState, newState.windowId));
      } else {
        this.trackTab(tab);
        tab.active && this.emit("active_tab_change", toTabItem(tab, tab.windowId));
      }
      break;
    }
    case "tabs.onActivated": {
      let [{ tabId }] = event.args;
      let session = this.tabSessions.get(tabId);
      this.activeTab && this.activeTab.handleStateChange({ active: false });
      if (session) {
        this.activeTab = session;
        session.handleStateChange({ active: true });
        this.emit("active_tab_change", session.getTabItem());
      } else {
        this.activeTab = null;
        getTab(tabId).then((tab) => {
          this.activeTab = this.trackTab(tab);
          this.emit("active_tab_change", toTabItem(tab, tab.windowId));
        }, () => {});
      }
      break;
    }
    case "webNavigation.onCommitted": {
      let [details] = event.args;
      this.handleWebNavigationCommitted(details);
    }
  }
};
this.handleWebNavigationCommitted = async (details) => {
  let { tabId, transitionType, transitionQualifiers, url } = details;
  if (details.frameId !== 0) return;
  let session = this.tabSessions.get(tabId);
  if (session && ((await session.getURL() === url && transitionType === "typed" && transitionQualifiers.includes("from_address_bar")) || transitionType === "reload")) {
    this.log.silly("Redirect detected", { tabId, url, transitionType, transitionQualifiers });
    session.emit("navigate", url, url);
  }
};
05EvidencePLAIN NOTE
What we observed, and what we didn't

Dynamic analysis confirmed the tracking machinery is live during real browsing: the background service worker issued repeated chrome.tabs.get calls immediately after each navigation, and its own "BrowserTabSession" log entries fired throughout a multi-site browsing session. We did not capture this URL/tab data being transmitted off the device in the same test session -- the confirmed behavior is that the extension holds a live, full-navigation session map in the background service worker's memory, available to its automation engine, for every open tab.

Updated 30 September 2026ihhkmalpkhkoedlmcnilbbhhbhnicjga