registry  /  haltija  /  1.3.4

haltija@1.3.4

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` to start the service, or explicitly runs `haltija-mcp-setup` or `haltija --setup-mcp`.
Impact
A connected AI agent or local caller can control a browser and execute page-context JavaScript; this is a broad intended capability rather than a covert payload.
Mechanism
Local browser-agent RPC with page eval, fetch, and explicit MCP registration.
Rationale
Source inspection contradicts the scanner's claimed download/execute behavior and finds no concrete malicious chain. Its intentional local agent/browser-control surface and explicit MCP setup remain a warn-level dangerous capability.
Evidence
package.jsonbin/tosijs-dev.mjsbin/mcp-setup.mjsdist/server.jsdist/index.jsdist/hj.js.mcp.json
Network endpoints2
localhost:8700/statuslocalhost:${port}

Decision evidence

public snapshot
AI called this Suspicious at 88.0% confidence as Dangerous Capability with low false-positive risk.
Evidence for warning
  • `dist/server.js` starts a browser-control HTTP/HTTPS service and exposes arbitrary page-context `/eval`.
  • `dist/server.js` implements agent-side arbitrary URL fetching after an authenticated browser/agent request.
  • `bin/mcp-setup.mjs` explicitly creates or modifies project `.mcp.json`; `--global` invokes `claude mcp add`.
  • `bin/tosijs-dev.mjs` explicitly configures a `haltija` Claude Desktop MCP entry when passed `--setup-mcp`.
  • `dist/hj.js` bidi/invisible Unicode literals are test/display data, not hidden control flow.
Evidence against
  • `package.json` contains no `preinstall`, `install`, or `postinstall` lifecycle hook.
  • No inspected executable source downloads and executes a remote payload; scanner's install finding maps to `npm root -g` discovery only.
  • No credential harvesting or outbound exfiltration endpoint was found in inspected entrypoints.
  • MCP configuration writes occur only behind explicit user CLI flags, not during installation or import.
Behavioral surface
Source
ChildProcessCryptoEnvironmentVarsEvalFilesystemNetworkShellWebSocket
Supply chain
HighEntropyStringsMinifiedObfuscatedUrlStrings
ManifestNo manifest risk signals triggered.
scanned 36 file(s), 3.50 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