registry  /  @lmctl-ai/lmctl  /  0.1.78

@lmctl-ai/lmctl@0.1.78

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

AI Security Review

scanned 7d ago · by lpm-firewall-ai

Review flagged AI-agent configuration or capability changes. This remains warn-only unless evidence shows foreign-agent hijack through preinstall/install/postinstall, hidden persistence, exfiltration, remote code execution, or other concrete malicious behavior.

Static reason
One or more suspicious static signals were detected.
Trigger
Explicit user invocation of lmctl commands such as workflow run, clone, plan, seed/refresh, diagnose, or provider resume actions.
Impact
Could execute powerful agent workflows in the user's project if the user loads untrusted workflows or invokes bypass-mode agent operations; no install-time or hidden persistence behavior found.
Mechanism
User-invoked AI-agent orchestration with remote workflow loading and approval-bypass provider flags.
Policy narrative
The package is a CLI control plane for AI coding agents. Its risky behavior is explicit and package-aligned: it can fetch remote workflow/skill definitions, spawn provider CLIs, and use provider flags that bypass approvals for resumed sessions. I found no npm lifecycle hook, hidden import-time payload, credential exfiltration, or unconsented mutation of foreign agent control surfaces.
Rationale
Static inspection supports a warning for dangerous agent-facing capability, not a publish block: the risky primitives are user-invoked and aligned with the package purpose. No concrete malicious delivery path, install-time execution, exfiltration, persistence, or foreign AI-agent control hijack was found.
Evidence
package.jsonbin/lmctldist/cli/index.jsdist/cli/schema.sqlREADME.mdworkflows/qa-suite.compound.jsonworkflows/pr-fix.compound.jsondist/config/durable_memory_templates/*.templatedist/config/ai_test_templates/*.templateworkflows/*.compound.json~/.lmctl/state.db~/.lmctl/.update-check.json~/.lmctl/recent-intents.logdurable-memory/skills/*.md
Network endpoints4
registry.npmjs.org/@lmctl-ai/lmctl/latestlmctl.comlmctl.anthropic.comuser-supplied https workflow/skill URLs

Decision evidence

public snapshot
AI called this Suspicious at 84.0% confidence as Dangerous Capability with medium false-positive risk.
Evidence for warning
  • dist/cli/index.js defines provider resume/start commands with approval-bypass flags for codex, claude, gemini, copilot, qwen, and agy.
  • dist/cli/index.js supports user-supplied https workflow and skill loading, with --yes/--no-prompt bypass for remote workflow trust prompt.
  • dist/cli/index.js can spawn agent/provider CLIs and shell-like commands as part of lmctl workflows.
  • dist/cli/index.js diagnose can collect local status/env/log metadata, though secrets are redacted by default.
Evidence against
  • package.json has no npm lifecycle scripts, so no install-time execution was found.
  • bin/lmctl only imports dist/cli/index.js and calls runCli on explicit CLI invocation.
  • No evidence of credential exfiltration; diagnostic upload modes are stubbed or local, and --no-sanitize is rejected with upload modes.
  • No unconsented writes to foreign AI-agent config surfaces such as .mcp.json, CLAUDE.md, or .claude commands were found.
  • Network access is package-aligned or user-supplied: update check, remote workflows/skills, and documented lmctl URLs.
Behavioral surface
Source
ChildProcessEnvironmentVarsFilesystemNetworkShell
Supply chain
HighEntropyStringsUrlStrings
Manifest
NoLicense
scanned 1 file(s), 807 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=>Dn(e)).join(` L5: `)}function zf(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=Pn(f.join(`
High
Child Process

Package source references child process execution.

dist/cli/index.jsView on unpkg · L4
4`).map(e=>Dn(e)).join(` L5: `)}function zf(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=Pn(f.join(` ... L16: `)}catch{}}function ov(){if(!eo){let e=sv().slice(0,13).replace("T","-");eo=to(cl(),`debug-${e}.log`)}ev(tv(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 Ek=Object.defineProperty;var b=(t,e)=>()=>(t&&(e=t(t=0)),e);var le=(t,e)=>{for(var r in e)Ek(t,r,{get:e[r],enumerable:!0})};import{existsSync as qr,readdirSync as bk,readFileSy... L2: `)}function ol(){return xt(wr(),Nk)}function Gf(){return xt(wr(),$k)}function jk(){try{return qr(ol())}catch{return!1}}function Kf(t=process.stderr){jk()&&t.write(`note: legacy ~/.... L3: `)}var kk,Hf,vk,Ik,Jf,Nk,$k,Er,Ye=b(()=>{"use strict";kk=".lmctl",Hf="state.db",vk="workspaces",Ik="active-workspace",Jf="default",Nk="profiles",$k="active-profile";Er={default:Jf}... L4: `).map(e=>Dn(e)).join(` L5: `)}function zf(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=Pn(f.join(` ... L16: `)}catch{}}function ov(){if(!eo){let e=sv().slice(0,13).replace("T","-");eo=to(cl(),`debug-${e}.log`)}ev(tv(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 Ek=Object.defineProperty;var b=(t,e)=>()=>(t&&(e=t(t=0)),e);var le=(t,e)=>{for(var r in e)Ek(t,r,{get:e[r],enumerable:!0})};import{existsSync as qr,readdirSync as bk,readFileSy... L2: `)}function ol(){return xt(wr(),Nk)}function Gf(){return xt(wr(),$k)}function jk(){try{return qr(ol())}catch{return!1}}function Kf(t=process.stderr){jk()&&t.write(`note: legacy ~/.... ... L4: `).map(e=>Dn(e)).join(` L5: `)}function zf(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=Pn(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:Pn(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 ov(){if(!eo){let e=sv().slice(0,13).replace("T","-");eo=to(cl(),`debug-${e}.log`)}ev(tv(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