registry  /  mulmoterminal  /  0.6.2

mulmoterminal@0.6.2

MulmoTerminal — browser terminal + GUI panel for Claude Code. One command to start.

AI Security Review

scanned 2h ago · by lpm-firewall-ai

LPM treats this as warn-only first-party agent extension lifecycle risk. User-invoked AI terminal platform with package-controlled Claude hooks, localhost MCP tools, and guarded workspace skill seeding. This is dangerous agent-facing capability, but the inspected install hook does not perform unconsented foreign agent control-surface mutation.

Static reason
High-risk behavior combination matched malicious policy.
Trigger
User runs the mulmoterminal CLI and opens/uses the localhost app.
Impact
Package/plugin tools can be auto-allowed inside launched Claude sessions; managed-workspace preset skills may be refreshed under the platform workspace.
Mechanism
Claude PTY launcher with in-process localhost MCP broker and guarded first-party workspace setup
Policy narrative
On explicit CLI launch, mulmoterminal starts a localhost server and spawns Claude with package-provided hook settings and a strict localhost MCP config. It auto-allows its GUI/plugin tools and may seed preset skills only inside the managed mulmoclaude workspace. The install hook itself only fixes node-pty helper permissions, so the high-risk agent behavior is user-invoked and platform-aligned rather than an install-time hijack.
Rationale
The package has real agent-extension lifecycle and capability risk because it wires auto-allowed MCP tools and guarded Claude-visible skills into its own platform runtime. Static inspection does not show install-time foreign agent control hijack, credential exfiltration, remote payload execution, or destructive behavior, so this should warn rather than block.
Evidence
package.jsonserver/fix-pty-perms.jsbin/mulmoterminal.jsbin/update-check.jsserver/index.tsserver/claude-args.tsserver/mcp/broker.tsserver/host-tools.tsserver/backends/workspaceSetup.tsnode-pty/prebuilds/*/spawn-helper~/.mulmoterminal/dev-terminal-sessions.json~/.mulmoterminal/toolresults/<sessionId>.json~/.mulmoterminal/toolcalls/<sessionId>.json~/mulmoclaude/.claude/skills~/mulmoclaude/config/helps~/mulmoclaude/data/skills/catalog/preset
Network endpoints3
registry.npmjs.orglocalhost:<PORT>/api/hook127.0.0.1:<PORT>/api/mcp/<sessionId>

Decision evidence

public snapshot
AI called this Suspicious at 86.0% confidence as Dangerous Capability with medium false-positive risk.
Evidence for warning
  • server/index.ts spawns Claude PTYs with package-supplied --settings hooks, --mcp-config, --strict-mcp-config, and auto-allowed GUI MCP tools.
  • server/mcp/broker.ts exposes package/plugin MCP tools over localhost and dispatches tool calls to /api/plugin/<toolName>.
  • server/host-tools.ts and server/index.ts define spawnBackgroundChat, an auto-allowed agent tool that starts parallel Claude sessions.
  • server/backends/workspaceSetup.ts can sync preset skills into <managed workspace>/.claude/skills when CLAUDE_CWD is the managed mulmoclaude workspace.
  • server/index.ts uses tmux for persistent terminal sessions when available.
Evidence against
  • package.json postinstall only runs server/fix-pty-perms.js, which chmods node-pty prebuilds/*/spawn-helper; it does not write Claude/Codex/MCP config.
  • bin/mulmoterminal.js activates server behavior only when the user runs the CLI, not on import/install.
  • workspaceSetup.ts explicitly skips seeding unless workspace equals ~/mulmoclaude or MULMOCLAUDE_WORKSPACE_PATH.
  • server/index.ts restricts browser socket origins to localhost/127.0.0.1/::1.
  • No credential harvesting or external exfiltration endpoint found; update check only queries npm registry latest metadata.
Behavioral surface
Source
ChildProcessCryptoDynamicRequireEnvironmentVarsFilesystemNetworkShellWebSocket
Supply chain
HighEntropyStringsMinifiedObfuscatedProtestwareUrlStrings
ManifestNo manifest risk signals triggered.
scanned 176 file(s), 4.14 MB of source, external domains: 127.0.0.1, bitbucket.org, cdn.jsdelivr.net, cdn.plot.ly, cdnjs.cloudflare.com, chevrotain.io, en.wikipedia.org, evil.example, fonts.bunny.net, fonts.googleapis.com, fonts.gstatic.com, github.com, langium.org, registry.npmjs.org, unpkg.com, www.w3.org
Oversized source lightweight scan
dist/assets/index-BycNzdB5.js3.16 MB file, sampled 256 KB
NetworkChildProcessHighEntropyStringsMinifiedProtestware
dist/assets/marp-BlNCU8cR.js3.39 MB file, sampled 256 KB
ChildProcessObfuscatedHighEntropyStringsUrlStringscdn.jsdelivr.netfonts.bunny.netwww.w3.org

Source & flagged code

10 flagged · loading source
package.jsonView file
scripts.postinstall = node server/fix-pty-perms.js
High
Install Time Lifecycle Scripts

Package defines install-time lifecycle scripts.

package.jsonView on unpkg
bin/mulmoterminal.jsView file
7L8: import { execSync, spawn } from "node:child_process"; L9: import { existsSync, statSync } from "node:fs";
High
Child Process

Package source references child process execution.

bin/mulmoterminal.jsView on unpkg · L7
7Manifest entrypoint (manifest.bin) carries capability families absent from dist/build output: environment+network, execution+network L7: L8: import { execSync, spawn } from "node:child_process"; L9: import { existsSync, statSync } from "node:fs"; L10: import { get as httpGet } from "node:http"; L11: import { createRequire } from "node:module"; ... L16: L17: const __dirname = dirname(fileURLToPath(import.meta.url)); L18: const PKG_DIR = join(__dirname, ".."); ... L22: const MAX_BIND_RETRIES = 5; L23: // Server exit code meaning "port taken at bind time" — keep in sync with L24: // server/index.ts (PORT_IN_USE_EXIT_CODE). ... L26:
High
Entrypoint Build Divergence

Manifest entrypoint contains risky behavior absent from dist/build output.

bin/mulmoterminal.jsView on unpkg · L7
193log(`Starting MulmoTerminal on port ${port}...`); L194: const server = spawn(process.execPath, ["--import", "tsx", SERVER_ENTRY], { L195: cwd: PKG_DIR, L196: env: { ...process.env, NODE_ENV: "production", PORT: String(port), CLAUDE_CWD: cwd }, L197: stdio: "inherit", ... L200: L201: const url = `http://localhost:${port}`; L202: const cancelReady = waitUntilReady(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.

bin/mulmoterminal.jsView on unpkg · L193
server/pick-file.tsView file
33return { L34: cmd: "powershell", L35: args: [
High
Shell

Package source references shell execution.

server/pick-file.tsView on unpkg · L33
server/plugins-registry.tsView file
65async function loadPackage(name: string) { L66: const mod = await import(name); L67: const definition = mod.TOOL_DEFINITION ?? mod.pluginCore?.toolDefinition;
Medium
Dynamic Require

Package source references dynamic require/import behavior.

server/plugins-registry.tsView on unpkg · L65
server/worktrees.tsView file
6// parse / paths) are split out for unit tests; the rest shell out to git. L7: import { spawn } from "node:child_process"; L8: import { createHash } from "node:crypto"; ... L15: // realpath so it matches the realpaths `git worktree list` reports (e.g. macOS L16: // /tmp -> /private/tmp), which the isManagedWorktree filter relies on. L17: function worktreesBase(): string { L18: const base = process.env.MULMOTERMINAL_HOME || path.join(os.homedir(), ".mulmoterminal"); L19: try { ... L101: L102: // Run git with argv (no shell) in `cwd`; resolve { ok, stdout } — never reject, so L103: // a missing git / non-repo dir is just `ok:false` and the caller falls back.
Low
Weak Crypto

Package source references weak cryptographic algorithms.

server/worktrees.tsView on unpkg · L6
dist/assets/mermaid-parser.core-DC7NPJ_M-ylD2dn6D.jsView file
46contains invisible/control Unicode U+FEFF (zero width no-break space) \r \v \xA0            \u2028\u2029   <U+FEFF>`.split(``);function ka(e){let t=typeof e==`string`?new RegExp(e):e;return Oa.some(e=>t.test(e))}s(ka,`isWhitespace`);function Aa(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}s(Aa,`escapeReg
Critical
Trojan Source Unicode

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

dist/assets/mermaid-parser.core-DC7NPJ_M-ylD2dn6D.jsView on unpkg · L46
dist/assets/material-symbols-outlined-DKJDg2oJ.woff2View file
path = dist/assets/material-symbols-outlined-DKJDg2oJ.woff2 kind = high_entropy_blob sizeBytes = 3960064 magicHex = [redacted]
High
Ships High Entropy Blob

Package ships high-entropy non-source blobs.

dist/assets/material-symbols-outlined-DKJDg2oJ.woff2View on unpkg
dist/assets/marp-BlNCU8cR.jsView file
path = dist/assets/marp-BlNCU8cR.js kind = oversized_source_file sizeBytes = 3555296 magicHex = [redacted]
High
Oversized Source File

Package contains source files above the static scanner size ceiling.

dist/assets/marp-BlNCU8cR.jsView on unpkg

Findings

1 Critical7 High5 Medium6 Low
CriticalTrojan Source Unicodedist/assets/mermaid-parser.core-DC7NPJ_M-ylD2dn6D.js
HighInstall Time Lifecycle Scriptspackage.json
HighChild Processbin/mulmoterminal.js
HighShellserver/pick-file.ts
HighEntrypoint Build Divergencebin/mulmoterminal.js
HighSame File Env Network Executionbin/mulmoterminal.js
HighShips High Entropy Blobdist/assets/material-symbols-outlined-DKJDg2oJ.woff2
HighOversized Source Filedist/assets/marp-BlNCU8cR.js
MediumDynamic Requireserver/plugins-registry.ts
MediumNetwork
MediumEnvironment Vars
MediumProtestware
MediumStructural Risk Force Deep Review
LowScripts Present
LowWeak Cryptoserver/worktrees.ts
LowFilesystem
LowObfuscated
LowHigh Entropy Strings
LowUrl Strings