registry  /  switchroom  /  0.17.3

switchroom@0.17.3

Run Claude Code 24/7 on your Claude Pro/Max subscription over Telegram. Open-source alternative to OpenClaw and NanoClaw — no API keys.

AI Security Review

scanned 47m ago · by lpm-firewall-ai

LPM treats this as warn-only first-party agent extension lifecycle risk. No malicious install-time behavior was confirmed. The remaining risk is first-party agent lifecycle setup that mutates Claude agent config, trust state, skills, and optional permission mode only through user-invoked commands.

Static reason
High-risk behavior combination matched malicious policy.
Trigger
User runs switchroom setup/apply/skill commands or starts bundled services.
Impact
Can create/manage Switchroom-owned Claude agent workspaces and enable MCP servers/skills; optional dangerous_mode reduces prompts when user opts in.
Mechanism
explicit agent scaffold and extension/config writer
Rationale
Source inspection does not support a malicious verdict or publish block. Because the package performs first-party Claude agent setup and trust/skill mutations, downgrade to a warning rather than mark fully clean.
Evidence
package.jsondist/cli/switchroom.jsdist/host-control/main.jstelegram-plugin/start.jstelegram-plugin/shared/bot-runtime.tsvendor/hindsight-memory/tests/conftest.py~/.claude.json~/.claude/.claude.json~/.claude-home/.claude.json<agentDir>/.claude/.claude.json<agentDir>/.claude/skills/personal-<name><agentDir>/telegram/.envswitchroom.yaml
Network endpoints1
us.i.posthog.com

Decision evidence

public snapshot
AI called this Suspicious at 82.0% confidence as Dangerous Capability with medium false-positive risk.
Evidence for warning
  • dist/cli/switchroom.js scaffolds agent Claude config and sets hasTrustDialogAccepted/enabledMcpjsonServers during explicit setup/apply.
  • dist/cli/switchroom.js can write personal skills under agent .claude/skills via explicit skill commands.
  • dist/cli/switchroom.js has an optional setup path that writes dangerous_mode to switchroom.yaml after prompt/env opt-in.
  • dist/host-control/main.js initializes PostHog telemetry to https://us.i.posthog.com unless disabled.
Evidence against
  • package.json has no preinstall/install/postinstall hook; only prepublishOnly for maintainer build/lint/test.
  • dist/cli/switchroom.js crypto/decrypt logic is a local vault feature, not an embedded payload execution chain.
  • telegram-plugin/start.js only imports bundled dist/server.js or local server.ts fallback.
  • telegram-plugin/shared/bot-runtime.ts uses execFileSync/spawnSync argv arrays to call switchroom CLI, not shell eval.
  • vendor/hindsight-memory/tests/conftest.py is a pytest fixture, not an executable payload.
  • No bidi/default-ignorable characters found in telegram-plugin/shared/bot-runtime.ts by source inspection.
Behavioral surface
Source
ChildProcessCryptoDynamicRequireEnvironmentVarsEvalFilesystemNetworkShell
Supply chain
HighEntropyStringsTelemetryUrlStrings
ManifestNo manifest risk signals triggered.
scanned 718 file(s), 14.3 MB of source, external domains: 127.0.0.1, a.b, a.example, api.anthropic.com, api.example.com, api.github.com, api.linear.app, api.notion.com, api.openai.com, api.telegra.ph, api.telegram.org, b.example, bun.sh, claude.ai, claude.com, console.anthropic.com, docs.com, docs.google.com, docs.googleapis.com, drive.google.com, e.com, eu-assets.i.posthog.com, eu.i.posthog.com, ex.io, example.com, example.org, github.com, gitlab.com, hooks.slack.com, json-schema.org, linear.app, login.microsoftonline.com, media.giphy.com, microsoft.com, oauth2.googleapis.com, onedrive.live.com, posthog.com, quotes.toscrape.com, raw.githubusercontent.com, sentry.io, switchroom.ai, switchroom.dev, t.me, telegra.ph, u.co, us-assets.i.posthog.com, us.i.posthog.com, www.example.com, www.example.org, www.typescriptlang.org
Oversized source lightweight scan
dist/cli/switchroom.js3.35 MB file, sampled 256 KB
FilesystemChildProcessEnvironmentVarsShellHighEntropyStringsUrlStringsgithub.com
telegram-plugin/dist/gateway/gateway.js2.66 MB file, sampled 256 KB
NetworkChildProcessEnvironmentVarsHighEntropyStringsUrlStringsapi.telegram.orgt.mewww.typescriptlang.org

Source & flagged code

14 flagged · loading source
dist/host-control/main.jsView file
10429var EventEmitter2 = __require("node:events").EventEmitter; L10430: var childProcess = __require("node:child_process"); L10431: var path2 = __require("node:path");
High
Child Process

Package source references child process execution.

dist/host-control/main.jsView on unpkg · L10429
10875} L10876: const execArgv = process2.execArgv ?? []; L10877: if (execArgv.includes("-e") || execArgv.includes("--eval") || execArgv.includes("-p") || execArgv.includes("--print")) {
High
Shell

Package source references shell execution.

dist/host-control/main.jsView on unpkg · L10875
2457if (typeof node_buffer.Buffer === "function") { L2458: return node_buffer.Buffer.from(src, "base64"); L2459: } else if (typeof atob === "function") { ... L4916: yield* this.next(token); L4917: yield* this.end(forceDoc, endOffset); L4918: } L4919: *next(token) { L4920: if (node_process.env.LOG_STREAM) L4921: console.dir(token, { depth: null }); ... L7789: } L7790: if (process.platform === "win32") { L7791: const osRelease = os.release().split(".");
High
Sandbox Evasion Gated Capability

Source gates dangerous network, credential, or execution behavior behind CI, host, platform, time, or geo fingerprint checks.

dist/host-control/main.jsView on unpkg · L2457
2457Cross-file remote execution chain: dist/host-control/main.js spawns dist/agent-scheduler/index.js; helper contains network access plus dynamic code execution. L2457: if (typeof node_buffer.Buffer === "function") { L2458: return node_buffer.Buffer.from(src, "base64"); L2459: } else if (typeof atob === "function") { ... L4916: yield* this.next(token); L4917: yield* this.end(forceDoc, endOffset); L4918: } L4919: *next(token) { L4920: if (node_process.env.LOG_STREAM) L4921: console.dir(token, { depth: null }); ... L7789: } L7790: if (process.platform === "win32") { L7791: const osRelease = os.release().split(".");
High
Cross File Remote Execution Context

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

dist/host-control/main.jsView on unpkg · L2457
telegram-plugin/dist/server.jsView file
12703sourceCode = this.opts.code.process(sourceCode, sch); L12704: const makeValidate = new Function(`${names_1.default.self}`, `${names_1.default.scope}`, sourceCode); L12705: const validate = makeValidate(this, this.scope.get());
Low
Eval

Package source references a known benign dynamic code generation pattern.

telegram-plugin/dist/server.jsView on unpkg · L12703
telegram-plugin/start.jsView file
25const target = existsSync(distPath) ? distPath : sourcePath; L26: await import(target);
Medium
Dynamic Require

Package source references dynamic require/import behavior.

telegram-plugin/start.jsView on unpkg · L25
telegram-plugin/shared/bot-runtime.tsView file
175contains invisible/control Unicode U+200B (zero width space) const safe = text.replace(/```/g, '`<U+200B>``')
Critical
Trojan Source Unicode

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

telegram-plugin/shared/bot-runtime.tsView on unpkg · L175
8* - `createRobustApiCall` — thin re-export of createRetryApiCall pre-wired L9: * with stderr logging (mirrors how gateway.ts constructs `robustApiCall`). L10: * - `makeSwitchroomExec` / `makeSwitchroomExecCombined` — factory fns for ... L26: import { run, type RunnerHandle } from '@grammyjs/runner' L27: import { execFileSync, spawnSync } from 'child_process' L28: import { createHash } from 'crypto' ... L116: const res = await prev(method, payload, signal) L117: process.stderr.write( L118: `tg-post method=${method} chat=${chat} thread=${thread} parse_mode=${parseMode} bytes=${bytes} hash=${hash} status=ok err=- code=- desc=-${tagSuffix}\n`, ... L203: export function makeSwitchroomExec(cfg: CliConfig = {}) { L204: const cli = cfg.cliPath ?? process.env.SWITCHROOM_CLI_PATH ?? 'switchroom' L205: const config = cfg.configPath ?? process.env.SWITCHROOM_CONFIG
Low
Weak Crypto

Package source references weak cryptographic algorithms.

telegram-plugin/shared/bot-runtime.tsView on unpkg · L8
dist/cli/switchroom.jsView file
context = nction renderProfileClaudeTemplate(profileName, profilesRoot = PROFILES_ROOT) {\n const profileDir = resolve4(profilesRoot, profileName);\n const hbsPath = join4(profileDir, "CLAUDE.md.hbs");\n const outPath = join4(profileDir, "CLAUDE.md");\n if (!existsSync6(hbsPath)) {\n return { wrote: false, path: outPath };\n }\n const source = readFileSync6(hbsPath, "utf-8");\n const template = import_handlebars.default.compile(source, { noEscape: true });\n const rendered = template({ profile: profileName });\n try {\n writeFileSync(outPath, rendered, "utf-8");\n return { wrote: true, path: outPath };\n } catch (err) {\n const code = err.code;\n if (code === "EACCES" || code === "EROFS" || code === "EPERM") {\n console.warn(`Note: profile CLAUDE.md at ${outPath} is not writable (${code}); ` + `skipping bookkeeping render. Agent scaffolds re-render the .hbs ` + `into their own dir, so this is non-fatal.`);\n return { wrote: false, path: outPath };\n }\n throw err;\n }\n}\nvar import_handlebars, PROFILES_ROOT, SHARE
Critical
Encrypted Payload Temp Execution

Source decrypts an embedded payload, writes it to disk, and executes it through a child process.

dist/cli/switchroom.jsView on unpkg
path = dist/cli/switchroom.js kind = oversized_source_file sizeBytes = 3511380 magicHex = [redacted]
High
Oversized Source File

Package contains source files above the static scanner size ceiling.

dist/cli/switchroom.jsView on unpkg
path = dist/cli/switchroom.js kind = oversized_cli_entrypoint sizeBytes = 3511380 magicHex = [redacted]
Medium
Oversized Cli Entrypoint

Package contains an oversized executable-looking CLI entrypoint.

dist/cli/switchroom.jsView on unpkg
bin/turn-pacing-hook.shView file
path = bin/turn-pacing-hook.sh kind = build_helper sizeBytes = 3963 magicHex = [redacted]
Medium
Ships Build Helper

Package ships non-JavaScript build or shell helper files.

bin/turn-pacing-hook.shView on unpkg
vendor/hindsight-memory/tests/conftest.pyView file
path = vendor/hindsight-memory/tests/conftest.py kind = payload_in_excluded_dir sizeBytes = 2548 magicHex = [redacted]
High
Payload In Excluded Dir

Package hides binary, compressed, or executable-looking payloads in test/fixture/hidden paths.

vendor/hindsight-memory/tests/conftest.pyView on unpkg
telegram-plugin/tests/secret-detect.test.tsView file
198patternName = private_key_rsa severity = critical line = 198 matchedText = const pe...----
Critical
Secret Pattern

RSA private key in telegram-plugin/tests/secret-detect.test.ts

telegram-plugin/tests/secret-detect.test.tsView on unpkg · L198

Findings

3 Critical6 High6 Medium8 Low
CriticalEncrypted Payload Temp Executiondist/cli/switchroom.js
CriticalTrojan Source Unicodetelegram-plugin/shared/bot-runtime.ts
CriticalSecret Patterntelegram-plugin/tests/secret-detect.test.ts
HighChild Processdist/host-control/main.js
HighShelldist/host-control/main.js
HighSandbox Evasion Gated Capabilitydist/host-control/main.js
HighCross File Remote Execution Contextdist/host-control/main.js
HighPayload In Excluded Dirvendor/hindsight-memory/tests/conftest.py
HighOversized Source Filedist/cli/switchroom.js
MediumDynamic Requiretelegram-plugin/start.js
MediumNetwork
MediumEnvironment Vars
MediumShips Build Helperbin/turn-pacing-hook.sh
MediumOversized Cli Entrypointdist/cli/switchroom.js
MediumStructural Risk Force Deep Review
LowNon Install Lifecycle Scripts
LowScripts Present
LowEvaltelegram-plugin/dist/server.js
LowWeak Cryptotelegram-plugin/shared/bot-runtime.ts
LowFilesystem
LowHigh Entropy Strings
LowTelemetry
LowUrl Strings