registry  /  @linsoai/browser-relay  /  1.1.0

@linsoai/browser-relay@1.1.0

Universal browser relay — control your Chrome from any AI agent via HTTP API or MCP. No auth, no cloud.

AI Security Review

scanned 4d ago · by lpm-firewall-ai

The package intentionally provides a local browser automation relay and optional remote relay. This is high-capability but package-aligned, documented, and not confirmed malicious by source inspection.

Static reason
High-risk behavior combination matched malicious policy.
Trigger
global npm install for autostart; user runs CLI/MCP/server; user enables Chrome extension remote mode
Impact
Trusted local agents or holders of a remote device secret can control the user's Chrome session.
Mechanism
localhost HTTP/WebSocket relay forwarding CDP/browser commands
Rationale
Static inspection found powerful browser-control and install persistence behavior, but it is consistent with the advertised browser relay product, gated to global installs or explicit user actions, and lacks concrete credential theft, stealth exfiltration, destructive behavior, or unconsented AI-agent control-surface mutation. Scanner AI-agent hijack and persistence labels are noisy because the installer only warns about stale copied skills and registers a documented local service.
Evidence
package.jsonserver/install.jsserver/uninstall.jsserver/relay-server.jsserver/mcp-server.jsserver/cli.jsserver/remote-protocol.jshub/src/worker.jsextension/manifest.jsonextension/background.jsskill/SKILL.mdREADME.md~/Library/LaunchAgents/org.browser-relay.service.plist~/.config/systemd/user/browser-relay.service~/.browser-relay/remotes.json/tmp/browser-relay.log/tmp/browser-relay.error.log
Network endpoints4
127.0.0.1:18795ws://127.0.0.1:18795/extensionrelay.linso.aiwss://relay.linso.ai/v1/device/connect

Decision evidence

public snapshot
AI called this Clean at 86.0% confidence as Benign with medium false-positive risk.
Evidence for block
  • package.json runs postinstall and postuninstall lifecycle scripts.
  • server/install.js registers launchd/systemd background service only when npm_config_global is true.
  • server/relay-server.js exposes no-auth localhost browser control APIs including /api/eval, /api/click, /api/type.
  • extension/manifest.json requests debugger/tabs/downloads permissions.
Evidence against
  • server/install.js skips service registration on local installs and does not write agent skill/control files.
  • server/install.js only reads existing agent skill copies to warn if stale; it does not overwrite them.
  • README.md documents localhost binding, service files, debugger permission, and remote-mode risk.
  • server/relay-server.js binds to 127.0.0.1 by default via BROWSER_RELAY_HOST.
  • Remote control uses user-enabled extension config and bearer/secret capability through relay.linso.ai.
  • Network capture redacts Authorization/Cookie/Set-Cookie headers and no credential harvesting/exfil loop was found.
Behavioral surface
Source
ChildProcessCryptoEnvironmentVarsFilesystemNetworkShellWebSocket
Supply chain
HighEntropyStringsUrlStrings
ManifestNo manifest risk signals triggered.
scanned 14 file(s), 229 KB of source, external domains: 127.0.0.1, deploy.workers.cloudflare.com, device.local, example.com, github.com, relay.linso.ai, relay.local, www.apple.com, www.npmjs.com

Source & flagged code

4 flagged · loading source
package.jsonView file
scripts.postinstall = node server/install.js
High
Install Time Lifecycle Scripts

Package defines install-time lifecycle scripts.

package.jsonView on unpkg
scripts.postinstall = node server/install.js
Medium
Ambiguous Install Lifecycle Script

Install-time lifecycle script is not statically allowlisted and needs review.

package.jsonView on unpkg
server/install.jsView file
1Install-time AI-agent control hijack evidence: L1: #!/usr/bin/env node L2: import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; L3: import { dirname, join } from "node:path"; ... L64: L65: mkdirSync(dirname(plistDst), { recursive: true }); L66: writeFileSync(plistDst, plistContent); L67: ... L100: L101: mkdirSync(dirname(serviceDst), { recursive: true }); L102: writeFileSync(serviceDst, serviceContent); L103: ... L123: const AGENT_SKILL_ROOTS = [ Payload evidence from skill/SKILL.md: L32: ``` L33: Relay URL: http://127.0.0.1:18795 L34: WebSocket: ws://127.0.0.1:18795/extension ... L118: Header: Content-Type: application/json L119: Body: { "url": "https://example.com", "tabId?": "optional-target-id" } L120: ``` ... L187: ### 8. browser_screenshot L188: Capture a PNG screenshot (base64). L189: ```
Critical
Ai Agent Control Hijack

Install-time source drops package-supplied AI-agent/MCP control files or instructions.

server/install.jsView on unpkg · L1
5import { homedir, platform } from "node:os"; L6: import { execSync } from "node:child_process"; L7: L8: const __dirname = dirname(fileURLToPath(import.meta.url)); L9: const RELAY_DIR = dirname(__dirname); ... L67: L68: // Use bootstrap/bootout — `launchctl load/unload` is the legacy API and L69: // often silently fails or returns EBADEXEC on macOS 13+. bootout first for ... L153: // a daemon hijacking their machine. L154: const isGlobal = process.env.npm[redacted] === "true"; L155: if (!isGlobal) { ... L182: try {
Medium
Install Persistence

Source writes installer persistence such as shell profile or service configuration.

server/install.jsView on unpkg · L5

Findings

1 Critical1 High5 Medium5 Low
CriticalAi Agent Control Hijackserver/install.js
HighInstall Time Lifecycle Scriptspackage.json
MediumAmbiguous Install Lifecycle Scriptpackage.json
MediumNetwork
MediumEnvironment Vars
MediumInstall Persistenceserver/install.js
MediumStructural Risk Force Deep Review
LowNon Install Lifecycle Scripts
LowScripts Present
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings