registry  /  @lmctl-ai/lmctl  /  0.1.44

@lmctl-ai/lmctl@0.1.44

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 established by source inspection. Risky primitives are explicit CLI features for an AI-agent control plane and diagnostics, not install-time or hidden behavior.

Static reason
One or more suspicious static signals were detected.
Trigger
User runs lmctl commands such as workflow run, terminal, diagnose, device, or team seed.
Impact
No unconsented credential theft, persistence, destructive install behavior, or hidden exfiltration identified.
Mechanism
User-invoked orchestration, local DB/workspace management, provider CLI spawning, and optional configured network clients.
Rationale
The static signals are real but align with the advertised lmctl CLI: workflow orchestration, diagnostics, provider session handling, and optional mailbox/network integrations. With no lifecycle hooks, hidden install/import execution, credential exfiltration path, or unconsented AI-agent control mutation, this should not be blocked.
Evidence
package.jsonbin/lmctldist/cli/index.jsREADME.mdworkflows/qa-suite.compound.jsonworkflows/pr-fix.compound.json

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 contains user-invoked child_process spawn/spawnSync for provider CLIs, tar/stat/du/uname/which/aws/git-like workflows.
  • dist/cli/index.js can fetch HTTPS workflow JSON and run loaded workflows after --yes or prompt.
  • dist/cli/index.js has diagnostic bundle creation and device mailbox/S3/Cognito support.
Evidence against
  • package.json has no lifecycle scripts; bin/lmctl only imports dist/cli/index.js and calls runCli.
  • Network use is package-aligned: update check, remote workflow loading, configured mailbox/API clients, and docs/install URLs.
  • Remote workflow URLs are restricted to https and refused on redirects; remote run path includes a trust prompt unless --yes/--no-prompt.
  • Diagnostics redact token/secret/key/password-like values by default; upload modes are stubbed or user-configured.
  • No import-time execution beyond exports/CLI guard; main behavior is activated by explicit lmctl commands.
  • No prompt/reviewer manipulation or unconsented AI-agent control-surface mutation found in package files.
Behavioral surface
Source
ChildProcessEnvironmentVarsFilesystemNetworkShell
Supply chain
HighEntropyStringsUrlStrings
Manifest
NoLicense
scanned 1 file(s), 771 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=>An(e)).join(` L5: `)}function Cf(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=Rn(f.join(`
High
Child Process

Package source references child process execution.

dist/cli/index.jsView on unpkg · L4
4`).map(e=>An(e)).join(` L5: `)}function Cf(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=Rn(f.join(` ... L16: `)}catch{}}function yk(){if(!Xs){let e=wk().slice(0,13).replace("T","-");Xs=Gs(za(),`debug-${e}.log`)}pk(hk(Xs),{recursive:!0})}function Vs(...t){vt({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 LT=Object.defineProperty;var b=(t,e)=>()=>(t&&(e=t(t=0)),e);var ce=(t,e)=>{for(var r in e)LT(t,r,{get:e[r],enumerable:!0})};import{existsSync as Dr,readdirSync as CT,readFileSy... L2: `)}function Xa(){return Tt(mr(),WT)}function Af(){return Tt(mr(),BT)}function HT(){try{return Dr(Xa())}catch{return!1}}function Rf(t=process.stderr){HT()&&t.write(`note: legacy ~/.... L3: `)}var PT,xf,FT,UT,$f,WT,BT,hr,Ve=b(()=>{"use strict";PT=".lmctl",xf="state.db",FT="workspaces",UT="active-workspace",$f="default",WT="profiles",BT="active-profile";hr={default:$f}... L4: `).map(e=>An(e)).join(` L5: `)}function Cf(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=Rn(f.join(` ... L16: `)}catch{}}function yk(){if(!Xs){let e=wk().slice(0,13).replace("T","-");Xs=Gs(za(),`debug-${e}.log`)}pk(hk(Xs),{recursive:!0})}function Vs(...t){vt({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 LT=Object.defineProperty;var b=(t,e)=>()=>(t&&(e=t(t=0)),e);var ce=(t,e)=>{for(var r in e)LT(t,r,{get:e[r],enumerable:!0})};import{existsSync as Dr,readdirSync as CT,readFileSy... L2: `)}function Xa(){return Tt(mr(),WT)}function Af(){return Tt(mr(),BT)}function HT(){try{return Dr(Xa())}catch{return!1}}function Rf(t=process.stderr){HT()&&t.write(`note: legacy ~/.... ... L4: `).map(e=>An(e)).join(` L5: `)}function Cf(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=Rn(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:Rn(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 yk(){if(!Xs){let e=wk().slice(0,13).replace("T","-");Xs=Gs(za(),`debug-${e}.log`)}pk(hk(Xs),{recursive:!0})}function Vs(...t){vt({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