registry  /  haltija  /  1.3.2

haltija@1.3.2

Browser control for AI agents - query DOM, click, type, run JS, watch mutations

AI Security Review

scanned 2h ago · by lpm-firewall-ai

Review flagged AI-agent configuration or capability changes. This remains warn-only unless evidence shows foreign-agent hijack through preinstall/install/postinstall, hidden persistence, exfiltration, remote code execution, or other concrete malicious behavior.

Static reason
High-risk behavior combination matched malicious policy.
Trigger
User runs haltija/hj server commands or haltija-mcp-setup/--setup-mcp.
Impact
Agent can control connected browser tabs and invoke configured local tools; explicit setup can register Haltija with Claude MCP.
Mechanism
user-invoked local browser automation and MCP configuration
Policy narrative
A user can explicitly launch Haltija or run its MCP setup commands, which may write Claude/Haltija configuration and expose browser-control tools over localhost. I found no lifecycle hook, silent foreign-agent control-surface mutation, credential harvesting, remote payload execution, or exfiltration path activated by install or import.
Rationale
The risky primitives are aligned with the package's documented browser-control/agent-integration purpose and are user-invoked rather than lifecycle-triggered. Residual risk remains because the package intentionally exposes agent-facing browser eval, local REST/WebSocket control, and MCP setup capability.
Evidence
package.jsonbin/tosijs-dev.mjsbin/mcp-setup.mjsbin/hj.mjsbin/cli-subcommand.mjsdist/index.jsdist/server.jsdist/client.jsapps/desktop/main.js.mcp.json~/.claude.json~/Library/Application Support/Claude/claude_desktop_config.json~/.config/claude/claude_desktop_config.json~/.haltija/servers/*.json
Network endpoints3
localhost:8700localhost:8701ws://localhost:8700/ws/browser

Decision evidence

public snapshot
AI called this Suspicious at 82.0% confidence as Dangerous Capability with medium false-positive risk.
Evidence for warning
  • bin/mcp-setup.mjs can create project .mcp.json or run `claude mcp add` only when its setup CLI is invoked.
  • dist/index.js and dist/server.js expose agent/browser control primitives including browser-context eval and local REST/WebSocket commands.
  • dist/index.js can spawn shell commands from haltija.json tool config and write screenshots/files under requested server features.
Evidence against
  • package.json has no preinstall/install/postinstall lifecycle hooks.
  • MCP/Claude config writes are tied to explicit flags or setup binaries, not install-time execution.
  • Network use is local/package-aligned: localhost ports 8700/8701 and ws://localhost browser bridge.
  • bin/tosijs-dev.mjs runtime install behavior is Electron fallback via npx after user launches CLI, not import/install-time payload execution.
  • dist/hj.js obfuscation-like content appears bundled CodeMirror/minified parser data, not hidden package bootstrap code.
Behavioral surface
Source
ChildProcessCryptoEnvironmentVarsEvalFilesystemNetworkShellWebSocket
Supply chain
HighEntropyStringsMinifiedObfuscatedUrlStrings
ManifestNo manifest risk signals triggered.
scanned 36 file(s), 3.49 MB of source, external domains: bun.sh, claude.ai, example.com, github.com, haltija-test.example, www.google.com, www.w3.org

Source & flagged code

9 flagged · loading source
bin/tosijs-dev.mjsView file
14L15: import { spawn, execSync as execSyncImported } from 'child_process' L16: import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs' ... L20: L21: const __dirname = dirname(fileURLToPath(import.meta.url)) L22: const serverPath = join(__dirname, '../dist/server.js') ... L55: --https-port <n> Set HTTPS port (default: 8701) L56: --token <value> Require X-Haltija-Token header on REST and ?token= on WebSocket L57: (default: off; sets HALTIJA_TOKEN) ... L146: try { L147: const config = JSON.parse(readFileSync(configPath, 'utf8')) L148: if (config.mcpServers?.haltija) {
Critical
Download Execute

Source downloads or fetches remote code and executes it.

bin/tosijs-dev.mjsView on unpkg · L14
14L15: import { spawn, execSync as execSyncImported } from 'child_process' L16: import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs'
High
Child Process

Package source references child process execution.

bin/tosijs-dev.mjsView on unpkg · L14
14Cross-file remote execution chain: bin/tosijs-dev.mjs spawns dist/server.js; helper contains network access plus dynamic code execution. L14: L15: import { spawn, execSync as execSyncImported } from 'child_process' L16: import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs' ... L20: L21: const __dirname = dirname(fileURLToPath(import.meta.url)) L22: const serverPath = join(__dirname, '../dist/server.js') ... L55: --https-port <n> Set HTTPS port (default: 8701) L56: --token <value> Require X-Haltija-Token header on REST and ?token= on WebSocket L57: (default: off; sets HALTIJA_TOKEN) ... L146: try { L147: const config = JSON.parse(readFileSync(configPath, 'utf8')) L148: if (config.mcpServers?.haltija) {
High
Cross File Remote Execution Context

Source spawns a local helper that also contains network and dynamic execution context; review data flow before blocking.

bin/tosijs-dev.mjsView on unpkg · L14
5* Usage: L6: * npx haltija # Launch desktop app (or server if electron unavailable) L7: * npx haltija --server # Server only (for CI, headless, bookmarklet usage) ... L14: L15: import { spawn, execSync as execSyncImported } from 'child_process' L16: import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs'
High
Runtime Package Install

Package source invokes a package manager install command at runtime.

bin/tosijs-dev.mjsView on unpkg · L5
dist/client.jsView file
70} L71: async eval(code) { L72: const res = await fetch(`${this.baseUrl}/eval`, {
High
Eval

Package source references dynamic code evaluation.

dist/client.jsView on unpkg · L70
apps/desktop/main.jsView file
23const os = require('os') L24: const { spawn } = require('child_process') L25: const http = require('http') L26: const { attachNetwork, detachNetwork, getNetworkLog, getNetworkStats, clearNetwork, isMonitoring } = require('./cdp-network.js') ... L32: // Haltija server config L33: const HALTIJA_PORT = parseInt(process.env.HALTIJA_PORT || '8700') L34: const HALTIJA_SERVER = `http://localhost:${HALTIJA_PORT}`
High
Same File Env Network Execution

A single source file combines environment access, network access, and code or shell execution; review context before blocking.

apps/desktop/main.jsView on unpkg · L23
dist/index.jsView file
49Trigger-reachable chain: manifest.main -> dist/index.js L49: import { join as join2 } from "path"; L50: import { spawn } from "child_process"; L51: function createTerminalState(maxPushBuffer = 100) { ... L72: ws, L73: cwd: defaultCwd || process.env.HOME || process.cwd() L74: }; ... L171: const raw = readFileSync2(configPath, "utf-8"); L172: const parsed = JSON.parse(raw); L173: if (parsed && typeof parsed === "object" && parsed.tools) { ... L265: }); L266: let stdout = ""; L267: let stderr = "";
Critical
Trigger Reachable Dangerous Capability

A package entrypoint or install-time lifecycle script reaches a source file with blocking dangerous behavior.

dist/index.jsView on unpkg · L49
49import { join as join2 } from "path"; L50: import { spawn } from "child_process"; L51: function createTerminalState(maxPushBuffer = 100) { ... L72: ws, L73: cwd: defaultCwd || process.env.HOME || process.cwd() L74: }; ... L171: const raw = readFileSync2(configPath, "utf-8"); L172: const parsed = JSON.parse(raw); L173: if (parsed && typeof parsed === "object" && parsed.tools) { ... L265: }); L266: let stdout = ""; L267: let stderr = "";
High
Obfuscated Payload Loader

Source contains an obfuscator-style string-array loader that reconstructs and executes hidden code.

dist/index.jsView on unpkg · L49
dist/hj.jsView file
558contains invisible/control Unicode U+202E (right-to-left override) "<U+202E>Reverse",
Critical
Trojan Source Unicode

Source contains bidi control or invisible Unicode characters associated with Trojan Source attacks.

dist/hj.jsView on unpkg · L558

Findings

3 Critical7 High3 Medium5 Low
CriticalDownload Executebin/tosijs-dev.mjs
CriticalTrojan Source Unicodedist/hj.js
CriticalTrigger Reachable Dangerous Capabilitydist/index.js
HighChild Processbin/tosijs-dev.mjs
HighShell
HighEvaldist/client.js
HighSame File Env Network Executionapps/desktop/main.js
HighObfuscated Payload Loaderdist/index.js
HighCross File Remote Execution Contextbin/tosijs-dev.mjs
HighRuntime Package Installbin/tosijs-dev.mjs
MediumNetwork
MediumEnvironment Vars
MediumStructural Risk Force Deep Review
LowScripts Present
LowFilesystem
LowObfuscated
LowHigh Entropy Strings
LowUrl Strings