registry  /  switchboard-router  /  0.5.21

switchboard-router@0.5.21

Switchboard CLI — local AI routing gateway (install: npm i -g switchboard-router; run: switchboard)

AI Security Review

scanned 4d ago · by lpm-firewall-ai

LPM treats this as warn-only first-party agent extension lifecycle risk. The package has a guarded AI-tool routing/MITM capability and explicit setup flows that write AI CLI configuration. No confirmed malicious install-time hijack or exfiltration chain was found.

Static reason
One or more suspicious static signals were detected.
Trigger
npm install runs postinstall runtime setup; user runs switchboard and opts into CLI tool setup or MITM routing
Impact
Warn-worthy capability to redirect selected AI tool traffic through a local Switchboard gateway; no evidence of covert persistence or credential exfiltration.
Mechanism
runtime dependency install plus user-invoked local router/MITM and AI CLI config mutation
Rationale
Source inspection supports a warn verdict for a guarded AI-agent routing/MITM capability and explicit AI CLI config mutation, not a publish block. The suspicious primitives are aligned with the package purpose and are mostly user-invoked, while postinstall is limited to package-owned runtime dependency setup.
Evidence
package.jsonhooks/postinstall.jshooks/sqliteRuntime.jshooks/trayRuntime.jscli.jsapp/src/mitm/server.jssrc/cli/menus/cliTools.jsapp/.next-cli-build/server/app/api/cli-tools/codex-settings/route.js~/.switchboard/runtime/package.json~/.switchboard/runtime/node_modules~/.switchboard/auth/cli-secret~/.switchboard/mitm/rootCA.key~/.switchboard/mitm/rootCA.crt/etc/hosts~/.codex/config.toml~/.codex/auth.json
Network endpoints9
registry.npmjs.org/${updatePackage}/latestdaily-cloudcode-pa.googleapis.comcloudcode-pa.googleapis.comapi.individual.githubcopilot.comq.us-east-1.amazonaws.comcodewhisperer.us-east-1.amazonaws.comruntime.us-east-1.kiro.devapi2.cursor.shapi.anthropic.com/mcp-registry/v0/servers

Decision evidence

public snapshot
AI called this Suspicious at 84.0% confidence as Dangerous Capability with medium false-positive risk.
Evidence for warning
  • package.json runs postinstall node hooks/postinstall.js
  • hooks/sqliteRuntime.js installs sql.js and better-sqlite3 into ~/.switchboard/runtime via npm install
  • hooks/trayRuntime.js installs systray2 and removes legacy systray from runtime/package node_modules
  • app/src/mitm/server.js runs HTTPS MITM on port 443, generates CA certs, and edits /etc/hosts for AI tool hosts
  • app/.next-cli-build/server/app/api/cli-tools/codex-settings/route.js writes ~/.codex/config.toml and auth.json on API request
  • src/cli/menus/cliTools.js exposes Claude/Codex/Droid/OpenClaw quick setup actions that route tools to Switchboard
Evidence against
  • No install-time mutation of foreign AI agent configs found; agent config writes are behind explicit menu/API setup actions
  • Postinstall installs pinned runtime dependencies for package-owned ~/.switchboard runtime, not arbitrary remote code
  • cli.js binds to 127.0.0.1 by default and LAN exposure requires --host opt-in
  • Update check only queries npm registry for this package and update action prints npm install command rather than silently updating
  • The secret-like chunk is bundled JOSE/JWT implementation code, not a hardcoded credential
  • No credential harvesting or exfiltration endpoint outside package-aligned routing/update behavior found
Behavioral surface
Source
ChildProcessCryptoDynamicRequireEnvironmentVarsFilesystemNativeBindingsNetworkShell
Supply chain
HighEntropyStringsMinifiedObfuscatedUrlStrings
ManifestNo manifest risk signals triggered.
scanned 35 file(s), 543 KB of source, external domains: 127.0.0.1, api.example.com, registry.npmjs.org, www.apple.com

Source & flagged code

14 flagged · loading source
package.jsonView file
scripts.postinstall = node hooks/postinstall.js
High
Install Time Lifecycle Scripts

Package defines install-time lifecycle scripts.

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

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

package.jsonView on unpkg
app/.next-cli-build/server/chunks/9078.jsView file
1patternName = private_key_rsa severity = critical line = 1 matchedText = "use str...}}};
Critical
Critical Secret

Package contains a critical-looking secret pattern.

app/.next-cli-build/server/chunks/9078.jsView on unpkg · L1
1patternName = private_key_rsa severity = critical line = 1 matchedText = "use str...}}};
Critical
Secret Pattern

RSA private key in app/.next-cli-build/server/chunks/9078.js

app/.next-cli-build/server/chunks/9078.jsView on unpkg · L1
app/src/mitm/server.jsView file
32`)}catch{}}var od=(()=>{let e=new Uint32Array(256);for(let t=0;t<256;t++){let a=t;for(let r=0;r<8;r++)a=a&1?3988292384^a>>>1:a>>>1;e[t]=a}return e})();function Po(e){let t=42949672... L33: `);t.push({role:"tool",tool_call_id:n.toolUseId||"",content:s})}let r=(e.content||"").trim();return(r||a.length===0)&&t.push({role:"user",content:r}),t}function fd(e){let t=e.toolU... L34: $proc = Start-Process powershell -ArgumentList @(
High
Child Process

Package source references child process execution.

app/src/mitm/server.jsView on unpkg · L32
24Private-MAC: `+B.digest().toHex()+`\r L25: `,s};Ca.publicKeyToOpenSSH=function(e,t){var a="ssh-rsa";t=t||"";var r=Ce.util.createBuffer();return vr(r,a),Et(r,e.e),Et(r,e.n),a+" "+Ce.util.encode64(r.bytes())+" "+t};Ca.private... L26: `);u=c.pop()||"";for(let g of c){let v=g.trim();if(!v||!v.startsWith("data:"))continue;let y=v.slice(5).trim();if(y!=="[DONE]"){process.env.DEBUG_MITM&&Ea(`[SSE in] ${y.slice(0,200... ... L32: `)}catch{}}var od=(()=>{let e=new Uint32Array(256);for(let t=0;t<256;t++){let a=t;for(let r=0;r<8;r++)a=a&1?3988292384^a>>>1:a>>>1;e[t]=a}return e})();function Po(e){let t=42949672... L33: `);t.push({role:"tool",tool_call_id:n.toolUseId||"",content:s})}let r=(e.content||"").trim();return(r||a.length===0)&&t.push({role:"user",content:r}),t}function fd(e){let t=e.toolU... L34: $proc = Start-Process powershell -ArgumentList @(
High
Same File Env Network Execution

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

app/src/mitm/server.jsView on unpkg · L24
24Private-MAC: `+B.digest().toHex()+`\r L25: `,s};Ca.publicKeyToOpenSSH=function(e,t){var a="ssh-rsa";t=t||"";var r=Ce.util.createBuffer();return vr(r,a),Et(r,e.e),Et(r,e.n),a+" "+Ce.util.encode64(r.bytes())+" "+t};Ca.private... L26: `);u=c.pop()||"";for(let g of c){let v=g.trim();if(!v||!v.startsWith("data:"))continue;let y=v.slice(5).trim();if(y!=="[DONE]"){process.env.DEBUG_MITM&&Ea(`[SSE in] ${y.slice(0,200... ... L32: `)}catch{}}var od=(()=>{let e=new Uint32Array(256);for(let t=0;t<256;t++){let a=t;for(let r=0;r<8;r++)a=a&1?3988292384^a>>>1:a>>>1;e[t]=a}return e})();function Po(e){let t=42949672... L33: `);t.push({role:"tool",tool_call_id:n.toolUseId||"",content:s})}let r=(e.content||"").trim();return(r||a.length===0)&&t.push({role:"user",content:r}),t}function fd(e){let t=e.toolU... L34: $proc = Start-Process powershell -ArgumentList @( ... L37: ) -Verb RunAs -Wait -PassThru -WindowStyle Hidden; L38: if ($proc.ExitCode -ne 0) { throw "Elevated command exited with code $($proc.ExitCode)" } L39: `;return new Promise((r,n)=>{zo(`powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -Command ${$o(a)}`,{windowsHide:!0},(s,i,o)=>{if(s){let u=o||s.message;u.includes("ca..
High
Command Output Exfiltration

Source combines command execution, command-output handling, and outbound requests; review data flow before blocking.

app/src/mitm/server.jsView on unpkg · L24
cli.jsView file
194if (process.platform === "win32") { L195: const psCmd = `powershell -NonInteractive -WindowStyle Hidden -Command "Get-WmiObject Win32_Process -Filter 'Name=\\"cloudflared.exe\\"' | Select-Object ProcessId,CommandLine | Con... L196: const output = execSync(psCmd, { encoding: "utf8", windowsHide: true, timeout: 5000 });
High
Shell

Package source references shell execution.

cli.jsView on unpkg · L194
2Cross-file remote execution chain: cli.js spawns app/src/mitm/server.js; helper contains network access plus dynamic code execution. L2: L3: const { spawn, exec, execSync } = require("child_process"); L4: const path = require("path"); L5: const fs = require("fs"); L6: const https = require("https"); L7: const os = require("os"); ... L16: start() { L17: if (process.stdout.isTTY) { L18: process.stdout.write(`\r${frames[0]} ${currentText}`); L19: interval = setInterval(() => { ... L44: L45: const pkg = require("./package.json");
High
Cross File Remote Execution Context

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

cli.jsView on unpkg · L2
app/server.jsView file
1const path = require('path') L2:
Medium
Dynamic Require

Package source references dynamic require/import behavior.

app/server.jsView on unpkg · L1
src/cli/tray/autostart.jsView file
3const os = require("os"); L4: const { execSync } = require("child_process"); L5: ... L36: } L37: const computed = path.resolve(__dirname, "..", "..", "..", "cli.js"); L38: if (fs.existsSync(computed)) return computed; ... L47: function enableAutoStart(cliPath) { L48: const platform = process.platform; L49: L50: if (!["darwin", "win32", "linux"].includes(platform)) return false; L51: if (platform === "linux" && !process.env.DISPLAY) return false; L52:
Medium
Install Persistence

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

src/cli/tray/autostart.jsView on unpkg · L3
app/src/lib/updater/updater.jsView file
1// Standalone detached updater process. L2: // Spawns `npm i -g <pkg>@latest`, exposes progress via tiny HTTP server. L3: // Survives after parent Next server exits (detached + unref by spawner). L4: L5: const { spawn } = require("child_process"); L6: const http = require("http");
High
Runtime Package Install

Package source invokes a package manager install command at runtime.

app/src/lib/updater/updater.jsView on unpkg · L1
src/cli/tray/tray.ps1View file
path = src/cli/tray/tray.ps1 kind = build_helper sizeBytes = 4005 magicHex = [redacted]
Medium
Ships Build Helper

Package ships non-JavaScript build or shell helper files.

src/cli/tray/tray.ps1View on unpkg
app/.next-cli-build/static/media/73cb51aac9c97f90-s.woff2View file
path = app/.next-cli-[redacted]-s.woff2 kind = high_entropy_blob sizeBytes = 4320 magicHex = [redacted]
High
Ships High Entropy Blob

Package ships high-entropy non-source blobs.

app/.next-cli-build/static/media/73cb51aac9c97f90-s.woff2View on unpkg

Findings

2 Critical8 High7 Medium6 Low
CriticalCritical Secretapp/.next-cli-build/server/chunks/9078.js
CriticalSecret Patternapp/.next-cli-build/server/chunks/9078.js
HighInstall Time Lifecycle Scriptspackage.json
HighChild Processapp/src/mitm/server.js
HighShellcli.js
HighSame File Env Network Executionapp/src/mitm/server.js
HighCommand Output Exfiltrationapp/src/mitm/server.js
HighCross File Remote Execution Contextcli.js
HighRuntime Package Installapp/src/lib/updater/updater.js
HighShips High Entropy Blobapp/.next-cli-build/static/media/73cb51aac9c97f90-s.woff2
MediumAmbiguous Install Lifecycle Scriptpackage.json
MediumDynamic Requireapp/server.js
MediumNetwork
MediumEnvironment Vars
MediumInstall Persistencesrc/cli/tray/autostart.js
MediumShips Build Helpersrc/cli/tray/tray.ps1
MediumStructural Risk Force Deep Review
LowNon Install Lifecycle Scripts
LowScripts Present
LowFilesystem
LowObfuscated
LowHigh Entropy Strings
LowUrl Strings