registry  /  @lmctl-ai/lmctl  /  0.1.79

@lmctl-ai/lmctl@0.1.79

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

AI Security Review

scanned 6d ago · by lpm-firewall-ai

No confirmed malicious attack surface was established. The risky primitives are explicit CLI features of an AI-agent control plane: running provider CLIs, loading workflows, MCP bridge setup, local DB/config writes, and project workflow actions.

Static reason
One or more suspicious static signals were detected.
Trigger
User runs lmctl subcommands such as seed, workflow run, diagnose, api, or packaged workflows.
Impact
Can modify configured project/workflow/session files when the user invokes those commands, but no install-time or hidden execution was found.
Mechanism
User-invoked AI workflow orchestration with local shell/provider execution
Rationale
Static inspection shows a legitimate user-invoked AI-agent orchestration CLI with dangerous capabilities, but no lifecycle hook, hidden startup path, exfiltration flow, or unconsented mutation of foreign agent surfaces. The scanner hits are explained by package-aligned CLI workflow, diagnostics, API, update-check, and provider-integration features.
Evidence
package.jsonbin/lmctldist/cli/index.jsREADME.mdworkflows/pr-fix.compound.jsonworkflows/triage-v2.compound.json~/.lmctl/state.db~/.lmctl/.update-check.json.mcp.json/tmp/lmctl-next-run-<run_id>-*.json{{project.local_path}}
Network endpoints5
registry.npmjs.org/@lmctl-ai/lmctl/latestlmctl.comlmctl.com/workflows/research.compound.jsonlmctl.anthropic.comLMCTL_API_URL

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 supports user-invoked shell/provider orchestration and workflow steps that can write project files.
  • dist/cli/index.js runSeed can install an lmctl MCP bridge .mcp.json for a Lead sessiondir during explicit lmctl seed.
  • dist/cli/index.js includes provider permission modes such as codex danger-full-access for code tasks.
  • workflows/*.compound.json contain user-invoked commands that run git/node/lmctl and write /tmp run artifacts.
Evidence against
  • package.json has no preinstall/install/postinstall lifecycle scripts; bin only exposes lmctl CLI.
  • Remote workflow execution in dist/cli/index.js is CLI-triggered and mentions a trust prompt, with --yes/--no-prompt explicit flags.
  • Network use is package-aligned: update check, docs/workflow URLs, local/configured API calls, and stub diagnostics upload.
  • diagnose path redacts secrets by default and rejects unsanitized upload; internal-s3/hq upload code is marked stub/no actual upload.
  • No evidence of import-time execution, credential harvesting, persistence, destructive install behavior, or unconsented broad agent control-surface mutation.
Behavioral surface
Source
ChildProcessEnvironmentVarsFilesystemNetworkShell
Supply chain
HighEntropyStringsUrlStrings
Manifest
NoLicense
scanned 1 file(s), 810 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=>Pn(e)).join(` L5: `)}function Qf(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=Fn(f.join(`
High
Child Process

Package source references child process execution.

dist/cli/index.jsView on unpkg · L4
4`).map(e=>Pn(e)).join(` L5: `)}function Qf(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=Fn(f.join(` ... L16: `)}catch{}}function dv(){if(!eo){let e=uv().slice(0,13).replace("T","-");eo=to(ul(),`debug-${e}.log`)}iv(av(eo),{recursive:!0})}function Je(...t){At({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 Ik=Object.defineProperty;var b=(t,e)=>()=>(t&&(e=t(t=0)),e);var ae=(t,e)=>{for(var r in e)Ik(t,r,{get:e[r],enumerable:!0})};import{existsSync as Hr,readdirSync as Nk,readFileSy... L2: `)}function il(){return xt(yr(),Ok)}function Vf(){return xt(yr(),Lk)}function Mk(){try{return Hr(il())}catch{return!1}}function Yf(t=process.stderr){Mk()&&t.write(`note: legacy ~/.... L3: `)}var jk,Xf,Ak,Rk,Gf,Ok,Lk,br,Ye=b(()=>{"use strict";jk=".lmctl",Xf="state.db",Ak="workspaces",Rk="active-workspace",Gf="default",Ok="profiles",Lk="active-profile";br={default:Gf}... L4: `).map(e=>Pn(e)).join(` L5: `)}function Qf(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=Fn(f.join(` ... L16: `)}catch{}}function dv(){if(!eo){let e=uv().slice(0,13).replace("T","-");eo=to(ul(),`debug-${e}.log`)}iv(av(eo),{recursive:!0})}function Je(...t){At({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 Ik=Object.defineProperty;var b=(t,e)=>()=>(t&&(e=t(t=0)),e);var ae=(t,e)=>{for(var r in e)Ik(t,r,{get:e[r],enumerable:!0})};import{existsSync as Hr,readdirSync as Nk,readFileSy... L2: `)}function il(){return xt(yr(),Ok)}function Vf(){return xt(yr(),Lk)}function Mk(){try{return Hr(il())}catch{return!1}}function Yf(t=process.stderr){Mk()&&t.write(`note: legacy ~/.... ... L4: `).map(e=>Pn(e)).join(` L5: `)}function Qf(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=Fn(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:Fn(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 dv(){if(!eo){let e=uv().slice(0,13).replace("T","-");eo=to(ul(),`debug-${e}.log`)}iv(av(eo),{recursive:!0})}function Je(...t){At({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