Is EasyClaw Browser Assistant safe?

Medium risk

EasyClaw Browser Assistant lets a localhost relay send Chrome DevTools commands through the extension.

The extension scans fixed localhost WebSocket ports and accepts a relay that proves knowledge of a secret embedded in the extension. Once connected, that relay can create or close tabs, query debugger targets, and send debugger commands that may access URLs, page titles, tab details, and DOM content.

DOCUAGILE PTE. LTD.v1.1.1Chrome Web Store
45Risk
Who publishes it

DOCUAGILE PTE. LTD. - no other listings under this identity

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

Publisher
DOCUAGILE PTE. LTD.

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

Publishers can request a review.

Findings

Extension can blank another installed extension's browser UI

We observed the extension detect another installed extension's iframe on a page and blank it within about 20 milliseconds, with no prompt, whenever the tab already had the extension's own automation session attached.

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

You browse to a page in a tab this extension has already attached its own automation session to.

That automation session is established through the extension's own local relay handshake feature.

The extension did this

The extension scans every frame on the page and blanks any other installed extension's interface it finds there.

No prompt, notice, or allowlist controls which foreign extension gets targeted.

Page DOM modified

The iframe's srcdoc attribute is set to an empty string and the element is cloned and swapped in, which cancels the foreign extension's page load. The src attribute is left unchanged, so the change is not visible from that attribute alone.

Target
A foreign extension's chrome-extension:// iframe embedded in a tab under the extension's own automation session
Before
<iframe src="chrome-extension://hbiplnpjibfglelkgaohcagcacaeijkd/panel.html" style="border:0;width:320px;height:480px"></iframe>
After the extension changed it
<iframe src="chrome-extension://hbiplnpjibfglelkgaohcagcacaeijkd/panel.html" srcdoc="" style="border:0;width:320px;height:480px"></iframe>
The code that does this

Detecting and blanking a foreign extension's iframe

Readable version

Readable source for the foreign-URL check and neutralization

foreign-frame-monitor.js:116-183
const isForeignExtensionUrl = (value) => {  if (typeof value !== 'string' || !value.startsWith('chrome-extension://')) {    return false  }  try {    const extensionId = new URL(value).host    return extensionId.length > 0 && extensionId !== ownExtensionId  } catch {    return false  }}const readFrameSources = (element) => {  const attributeSource = element.getAttribute('src')?.trim() ?? ''  return element instanceof HTMLIFrameElement    ? {        attributeSource,        propertySource: element.src?.trim() ?? '',      }    : { attributeSource, propertySource: '' }}const readShadowRoot = (element) => {  if (!(element instanceof HTMLElement)) {    return null  }  if (typeof getOpenOrClosedShadowRoot === 'function') {    try {      return getOpenOrClosedShadowRoot(element)    } catch {      // Fall back to the public open-shadow-root property.    }  }  return element.shadowRoot}const recreateBrowsingContext = (element) => {  const parent = element.parentNode  if (!parent) {    trackNeutralizationLoad(element)    return element  }  const replacement = element.cloneNode(true)  trackNeutralizationLoad(replacement)  parent.replaceChild(replacement, element)  return replacement}const neutralizeFrame = (element) => {  const shadowRoot = readShadowRoot(element)  if (element.tagName === 'IFRAME' || element.tagName === 'FRAME') {    const { attributeSource, propertySource } = readFrameSources(element)    if (      isForeignExtensionUrl(attributeSource) ||      isForeignExtensionUrl(propertySource)    ) {      if (element instanceof HTMLIFrameElement) {        if (element.getAttribute('srcdoc') !== '') {          element.setAttribute('srcdoc', '')          recreateBrowsingContext(element)          recordNeutralization()        }      } else if (element.getAttribute('src') !== 'about:blank') {        trackNeutralizationLoad(element)        element.setAttribute('src', 'about:blank')        recordNeutralization()      }

Readable source for injecting the monitor into every frame

foreign-frame-monitor-controller.js:230-235
const injectionPromise = scripting.executeScript({  target: target(tabId),  files: FOREIGN_FRAME_MONITOR_INJECTION_FILES,  injectImmediately: true,  world: 'ISOLATED',})
Check if you're affected

Prints whether the foreign-frame monitor is active in the current tab and how many foreign iframes it has blanked.

Requires
  • Chrome DevTools
  • A tab the extension has an active session on
check-foreign-frame-monitor.js · js
// Run this in the DevTools Console of a tab, using "Inspect" from// chrome://extensions on the extension itself, or a page's own DevTools// if the extension has an active session on that tab.const marker = '__easyclawForeignExtensionFrameMonitor';const monitor = window[marker];if (!monitor) {  console.log('Foreign-frame monitor is not installed in this tab.');} else {  console.log('Monitor installed. Frames blanked so far:', monitor.stats.neutralizedFrames);  console.log(    'Last blanked at:',    monitor.stats.lastNeutralizedAt ? new Date(monitor.stats.lastNeutralizedAt) : 'never'  );}
How to run it
  1. 1Open DevTools on the tab.
  2. 2Paste this script into the Console.
  3. 3Embed another extension's chrome-extension:// page as an iframe and re-run to see neutralizedFrames increase.

Where it sends data

Destinations our analysis observed EasyClaw Browser Assistant 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.

  • 127.0.0.1:39654-39656/extension

    EasyClaw Browser Assistant sends data to 127.0.0.1:39654-39656/extension. No other extension we have analysed sends data here.

Updated 30 September 2026gapnolepnkifjliffcifdlmmnlfcicnf