registry  /  @lmctl-ai/lmctl  /  0.1.50

@lmctl-ai/lmctl@0.1.50

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 found. Risky primitives are exposed as user-invoked CLI features for an AI-agent control plane, with no install-time execution or hidden exfiltration path identified.

Static reason
One or more suspicious static signals were detected.
Trigger
User runs lmctl commands such as workflow run, seed, chat, serve, api, diagnose, or device.
Impact
Can execute configured provider/workflow commands under user direction; no evidence of unauthorized persistence, credential harvesting, or covert exfiltration.
Mechanism
User-invoked provider orchestration, workflow fetching, local DB/config writes, diagnostics, and API/device mailbox access.
Rationale
The suspicious scanner signals are explained by the package's stated purpose as a local-first AI-agent workflow CLI: it spawns provider CLIs, fetches explicit HTTPS workflows, reads configuration/env, and stores local state. There are no lifecycle hooks, import-time behavior, covert endpoints, credential exfiltration flow, or unconsented AI-agent control-surface mutation found by source inspection.
Evidence
package.jsonbin/lmctldist/cli/index.jsREADME.mdexamples/opencode.jsonworkflows/qa-suite.compound.jsonworkflows/pr-fix.compound.json~/.lmctl/state.db~/.lmctl/.update-check.json~/.lmctl/recent-intents.log~/.lmctl/cli-tokens.json~/.lmctl/device-auth.json.mcp.json~/.copilot/mcp-config.json
Network endpoints7
lmctl.comregistry.npmjs.org/@lmctl-ai/lmctl/latest127.0.0.1:8787api.githubcopilot.comapi.deepseek.com/v1openrouter.ai/api/v1cognito-idp.<region>.amazonaws.com/

Decision evidence

public snapshot
AI called this Clean at 83.0% confidence as Benign with medium false-positive risk.
Evidence for block
  • dist/cli/index.js can spawn provider CLIs with permissive/yolo flags during user-invoked agent workflows.
  • dist/cli/index.js fetches https remote workflows and can run them after trust prompt or --yes.
  • dist/cli/index.js reads env/config tokens for its local API/device mailbox features.
Evidence against
  • package.json has no lifecycle scripts; bin/lmctl only imports runCli.
  • Network endpoints are package-aligned: lmctl.com docs/workflows, npm registry update check, local API, AWS Cognito/S3 device mailbox.
  • Diagnostic bundle code redacts token/secret/key/password patterns and upload modes are stubbed or explicit.
  • Remote workflow loader records source_uri/source_sha256 and rejects non-https redirects.
  • Shell/child_process usage is CLI workflow/provider orchestration, not install/import-time execution.
Behavioral surface
Source
ChildProcessEnvironmentVarsFilesystemNetworkShell
Supply chain
HighEntropyStringsUrlStrings
Manifest
NoLicense
scanned 1 file(s), 773 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