registry  /  @lmctl-ai/lmctl  /  0.1.43

@lmctl-ai/lmctl@0.1.43

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 user-invoked CLI features for workflows, diagnostics, provider checks, update notification, and local configuration.

Static reason
One or more suspicious static signals were detected.
Trigger
User runs lmctl commands such as workflow/run/diagnose/serve/workspace/hire.
Impact
No evidence of install-time execution, credential harvesting, persistence, or unconsented exfiltration.
Mechanism
User-directed AI workflow orchestration, local state management, and provider CLI integration.
Rationale
Static inspection shows suspicious primitives, but they are tied to explicit CLI functionality for managing AI-agent workflows and local diagnostics, with no lifecycle hook or import-time payload. The scanner signals appear explainable by the package's declared purpose rather than concrete malicious behavior.
Evidence
package.jsonbin/lmctldist/cli/index.jsREADME.mdworkflows/qa-suite.compound.jsonworkflows/pr-fix.compound.json
Network endpoints4
registry.npmjs.org/@lmctl-ai/lmctl/latestlmctl.com/templates/lmctl.anthropic.comcognito-idp.${region}.amazonaws.com/

Decision evidence

public snapshot
AI called this Clean at 86.0% confidence as Benign with medium false-positive risk.
Evidence for block
  • dist/cli/index.js contains child_process spawnSync and writes local config/diagnostic files during explicit CLI commands.
  • dist/cli/index.js can fetch https workflow/skill/MCP sources and cache them under lmctl paths.
  • dist/cli/index.js update notifier contacts https://registry.npmjs.org/@lmctl-ai/lmctl/latest on interactive CLI use.
Evidence against
  • package.json has no lifecycle scripts; only bin lmctl -> bin/lmctl.
  • bin/lmctl only imports runCli and calls it with user CLI args.
  • dist/cli/index.js gates main CLI execution on direct entrypoint comparison; import exposes runCli.
  • Diagnostics redact token/secret/key/password values and upload modes are stubbed, not actual exfiltration.
  • Remote workflow run requires https and has a trust prompt unless --yes/--no-prompt is user supplied.
  • Network endpoints and provider process execution match the advertised AI-agent control-plane CLI purpose.
Behavioral surface
Source
ChildProcessEnvironmentVarsFilesystemNetworkShell
Supply chain
HighEntropyStringsUrlStrings
Manifest
NoLicense
scanned 1 file(s), 767 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 Mf(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 Mf(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 Ga(){return Tt(mr(),WT)}function Rf(){return Tt(mr(),BT)}function HT(){try{return Dr(Ga())}catch{return!1}}function Of(t=process.stderr){HT()&&t.write(`note: legacy ~/.... L3: `)}var PT,jf,FT,UT,Nf,WT,BT,hr,Ve=b(()=>{"use strict";PT=".lmctl",jf="state.db",FT="workspaces",UT="active-workspace",Nf="default",WT="profiles",BT="active-profile";hr={default:Nf}... L4: `).map(e=>An(e)).join(` L5: `)}function Mf(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 Ga(){return Tt(mr(),WT)}function Rf(){return Tt(mr(),BT)}function HT(){try{return Dr(Ga())}catch{return!1}}function Of(t=process.stderr){HT()&&t.write(`note: legacy ~/.... ... L4: `).map(e=>An(e)).join(` L5: `)}function Mf(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