registry  /  @lmctl-ai/lmctl  /  0.1.47

@lmctl-ai/lmctl@0.1.47

A provider-agnostic control plane for teams of AI coding agents — across providers, with independent review and durable memory.

AI Security Review

scanned 10d ago · by lpm-firewall-ai

No confirmed malicious attack surface was found. Risky primitives are part of a user-invoked AI agent control-plane CLI and are gated by commands/configuration rather than install or import execution.

Static reason
One or more suspicious static signals were detected.
Trigger
Explicit user commands such as lmctl run, lmctl workflow run, lmctl serve, lmctl diagnose, or lmctl terminal.
Impact
Could run user-selected workflows or provider CLIs with local project access, but no unconsented malicious behavior is present in the inspected package.
Mechanism
User-invoked CLI orchestration, local database/state management, provider CLI spawning, and optional remote workflow loading.
Rationale
Static inspection shows a legitimate CLI for coordinating AI coding agents with expected child process, network, env, and local state primitives. There is no lifecycle execution or source-grounded evidence of credential harvesting, exfiltration, persistence, destructive action, or unconsented agent control mutation.
Evidence
package.jsonbin/lmctldist/cli/index.jsREADME.mdworkflows/qa-suite.compound.jsonworkflows/pr-fix.compound.json
Network endpoints10
registry.npmjs.org/@lmctl-ai/lmctl/latestlmctl.com127.0.0.1:8787docs.claude.comgithub.com/openai/codexgithub.com/google/generative-ai-cliopencode.aigithub.com/QwenLM/qwen-codedocs.github.com/copilot/cliantigravity.google

Decision evidence

public snapshot
AI called this Clean at 86.0% confidence as Benign with low false-positive risk.
Evidence for block
  • dist/cli/index.js includes user-invoked child_process spawning for provider CLIs and terminal resume.
  • dist/cli/index.js can fetch https workflow URLs and enqueue/run them after a trust check.
  • dist/cli/index.js has diagnostic bundle code reading selected env/status data, with optional --no-sanitize.
Evidence against
  • package.json has no install/preinstall/postinstall lifecycle scripts.
  • bin/lmctl only imports dist/cli/index.js and calls runCli on explicit CLI execution.
  • dist/cli/index.js redacts token/secret/password/key-like env values in diagnostics by default.
  • Remote workflow fetch is https-only and prints source/sha/workflow details before running.
  • Network endpoints are package-aligned: update check, docs/workflows, local API, AWS device/mailbox support.
  • No evidence of import-time exfiltration, persistence, destructive behavior, or AI-agent control-surface mutation.
Behavioral surface
Source
ChildProcessEnvironmentVarsFilesystemNetworkShell
Supply chain
HighEntropyStringsUrlStrings
Manifest
NoLicense
scanned 1 file(s), 772 KB of source, external domains: 127.0.0.1, antigravity.google, api.deepseek.com, api.github.com, api.githubcopilot.com, cli.github.com, docs.anthropic.com, docs.claude.com, docs.github.com, github.com, lmctl.ai, lmctl.anthropic.com, lmctl.com, mailbox.local, nodejs.org, opencode.ai, openrouter.ai, registry.npmjs.org, unpkg.com

Source & flagged code

4 flagged · loading source
dist/cli/index.jsView file
4`).map(e=>On(e)).join(` L5: `)}function Df(t,e){let r=t.toUpperCase();return r.includes("TOKEN")||r.includes("SECRET")||r.includes("KEY")||r.includes("PASSWORD")||r.includes("PASSWD")||r.includes("CREDENTIAL"... L6: `),f=d.slice(Math.max(0,d.length-n));c=f.length,a=Ln(f.join(`
High
Child Process

Package source references child process execution.

dist/cli/index.jsView on unpkg · L4
4`).map(e=>On(e)).join(` L5: `)}function Df(t,e){let r=t.toUpperCase();return r.includes("TOKEN")||r.includes("SECRET")||r.includes("KEY")||r.includes("PASSWORD")||r.includes("PASSWD")||r.includes("CREDENTIAL"... L6: `),f=d.slice(Math.max(0,d.length-n));c=f.length,a=Ln(f.join(` ... L16: `)}catch{}}function Tk(){if(!Vs){let e=Sk().slice(0,13).replace("T","-");Vs=Ks(Za(),`debug-${e}.log`)}wk(yk(Vs),{recursive:!0})}function ot(...t){It({event:"legacy",msg:t.join(" ")... L17: `)){let r=e.trim();if(!r||r.startsWith("#"))continue;if(r.startsWith("["))break;let n=/^debug\s*=\s*(.+)$/.exec(r);if(n){let s=n[1].trim().toLowerCase().replace(/^["']|["']$/g,"");... L18: CREATE TABLE IF NOT EXISTS session_size (
High
Same File Env Network Execution

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

dist/cli/index.jsView on unpkg · L4
1var PT=Object.defineProperty;var b=(t,e)=>()=>(t&&(e=t(t=0)),e);var ce=(t,e)=>{for(var r in e)PT(t,r,{get:e[r],enumerable:!0})};import{existsSync as Pr,readdirSync as FT,readFileSy... L2: `)}function Va(){return kt(pr(),JT)}function Of(){return kt(pr(),XT)}function VT(){try{return Pr(Va())}catch{return!1}}function Lf(t=process.stderr){VT()&&t.write(`note: legacy ~/.... L3: `)}var BT,jf,qT,HT,Af,JT,XT,_r,Ve=b(()=>{"use strict";BT=".lmctl",jf="state.db",qT="workspaces",HT="active-workspace",Af="default",JT="profiles",XT="active-profile";_r={default:Af}... L4: `).map(e=>On(e)).join(` L5: `)}function Df(t,e){let r=t.toUpperCase();return r.includes("TOKEN")||r.includes("SECRET")||r.includes("KEY")||r.includes("PASSWORD")||r.includes("PASSWD")||r.includes("CREDENTIAL"... L6: `),f=d.slice(Math.max(0,d.length-n));c=f.length,a=Ln(f.join(` ... L16: `)}catch{}}function Tk(){if(!Vs){let e=Sk().slice(0,13).replace("T","-");Vs=Ks(Za(),`debug-${e}.log`)}wk(yk(Vs),{recursive:!0})}function ot(...t){It({event:"legacy",msg:t.join(" ")... L17: `)){let r=e.trim();if(!r||r.startsWith("#"))continue;if(r.startsWith("["))break;let n=/^debug\s*=\s*(.+)$/.exec(r);if(n){let s=n[1].trim().toLowerCase().rep
High
Command Output Exfiltration

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

dist/cli/index.jsView on unpkg · L1
1var PT=Object.defineProperty;var b=(t,e)=>()=>(t&&(e=t(t=0)),e);var ce=(t,e)=>{for(var r in e)PT(t,r,{get:e[r],enumerable:!0})};import{existsSync as Pr,readdirSync as FT,readFileSy... L2: `)}function Va(){return kt(pr(),JT)}function Of(){return kt(pr(),XT)}function VT(){try{return Pr(Va())}catch{return!1}}function Lf(t=process.stderr){VT()&&t.write(`note: legacy ~/.... ... L4: `).map(e=>On(e)).join(` L5: `)}function Df(t,e){let r=t.toUpperCase();return r.includes("TOKEN")||r.includes("SECRET")||r.includes("KEY")||r.includes("PASSWORD")||r.includes("PASSWD")||r.includes("CREDENTIAL"... L6: `),f=d.slice(Math.max(0,d.length-n));c=f.length,a=Ln(f.join(` ... L14: `).filter(i=>i.length>0),o=s.slice(Math.max(0,s.length-r));return{source_path:e,tail_lines:o.length,tail:Ln(o.join(` L15: `)),note:null}}catch(n){return n.code==="ENOENT"?{source_path:e,tail_lines:0,tail:"",note:"no intent log present (status never run on this host)"}:{source_path:e,tail_lines:0,tail:... L16: `)}catch{}}function Tk(){if(!Vs){let e=Sk().slice(0,13).replace("T","-");Vs=Ks(Za(),`debug-${e}.log`)}wk(yk(Vs),{recursive:!0})}function ot(...t){It({event:"legacy",msg:t.join(" ")... L17: `)){let r=e.trim();if(!r||r.s
Low
Weak Crypto

Package source references weak cryptographic algorithms.

dist/cli/index.jsView on unpkg · L1

Findings

4 High2 Medium5 Low
HighChild Processdist/cli/index.js
HighShell
HighSame File Env Network Executiondist/cli/index.js
HighCommand Output Exfiltrationdist/cli/index.js
MediumNetwork
MediumEnvironment Vars
LowWeak Cryptodist/cli/index.js
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings
LowNo License