registry  /  publishport-opencli  /  1.8.5-pp.14

publishport-opencli@1.8.5-pp.14

Make any website or Electron App your CLI. AI-powered.

AI Security Review

scanned 1d ago · by lpm-firewall-ai

No confirmed malicious attack surface was established. The risky primitives are lifecycle home-directory setup, local cleanup, browser automation, dynamic adapter loading, and user-invoked service API calls that align with an extensible browser CLI.

Static reason
One or more suspicious static signals were detected.
Trigger
global install, uninstall, or user running opencli commands
Impact
Creates OpenCLI config/completion files and may clear stale OpenCLI adapter overrides; no evidence of secret exfiltration, persistence, or destructive behavior outside OpenCLI-managed paths.
Mechanism
package-aligned CLI setup and runtime adapter execution
Rationale
Static inspection found suspicious primitives, but they are consistent with an extensible OpenCLI browser automation tool and are gated by install/global/user-invoked flows. I found no unconsented credential collection, outbound exfiltration, malware persistence, dependency confusion, or AI-agent control-surface mutation.
Evidence
package.jsonscripts/postinstall.jsscripts/fetch-adapters.jsdist/src/main.jsdist/src/discovery.jsdist/src/external.jsdist/src/update-check.jsclis/flomo/memos.js~/.zsh/completions/_opencli~/.bash_completion.d/opencli~/.config/fish/completions/opencli.fish~/.opencli/spotify.env~/.opencli/adapter-manifest.json~/.opencli/clis/~/.opencli/node_modules/@jackwener/opencli
Network endpoints4
127.0.0.1:19825/shutdownregistry.npmjs.org/@jackwener/opencli/latestapi.github.com/repos/jackwener/OpenCLI/releases?per_page=20flomoapp.com/api/v1/memo/updated/

Decision evidence

public snapshot
AI called this Clean at 86.0% confidence as Benign with medium false-positive risk.
Evidence for block
  • package.json has postinstall and preuninstall lifecycle scripts.
  • scripts/postinstall.js writes completion files and ~/.opencli/spotify.env on global install.
  • scripts/fetch-adapters.js can remove stale ~/.opencli/clis overrides and legacy shim files on global/explicit install.
Evidence against
  • No install-time credential harvesting or outbound exfiltration found in scripts/postinstall.js or scripts/fetch-adapters.js.
  • preuninstall only POSTs to http://127.0.0.1:19825/shutdown with a local OpenCLI header.
  • dist/src/external.js executes user/configured external CLIs after parsing install commands to reject shell operators.
  • dist/src/discovery.js dynamically imports adapter/plugin JS from package and ~/.opencli as the product extension mechanism.
  • dist/src/update-check.js only fetches npm/GitHub update metadata and caches it under ~/.opencli.
  • clis/flomo/memos.js sends a browser-session token only to Flomo API for a user-invoked Flomo command.
Behavioral surface
Source
ChildProcessCryptoDynamicRequireEnvironmentVarsEvalFilesystemNetwork
Supply chain
HighEntropyStringsMinifiedObfuscatedTelemetryUrlStrings
Manifest
NoLicense
scanned 1,551 file(s), 4.75 MB of source, external domains: 127.0.0.1, 36kr.com, a.example, account.dianping.com, accounts.douban.com, accounts.google.com, accounts.pixiv.net, accounts.spotify.com, admin.xiaoe-tech.com, api.bilibili.com, api.chess.com, api.coingecko.com, api.dictionaryapi.dev, api.fda.gov, api.github.com, api.juejin.cn, api.llama.fi, api.m.jd.com, api.manus.im, api.npmjs.org, api.nuget.org, api.openalex.org, api.osv.dev, api.ruguoapp.com, api.semanticscholar.org, api.slock.ai, api.spotify.com, api.stackexchange.com, api.tvmaze.com, api.xiaoyuzhoufm.com, api.zhihu.com, api.zsxq.com, api2.mubu.com, api2.openreview.net, apiv1.oschina.net, app.cj.sina.com.cn, app.slock.ai, appxxxx.h5.xet.citv.cn, archive.org, arxiv.org, assets.grok.com, auth.1point3acres.com, auth.band.us, auth.openai.com, azuresearch-usnc.nuget.org, baijiahao.baidu.com, bbs.hupu.com, bid.powerchina.cn, bizapi.csdn.net, blog.51cto.com

Source & flagged code

10 flagged · loading source
package.jsonView file
scripts.postinstall = node scripts/postinstall.js || true; node scripts/fetch-adapters.js || true
High
Install Time Lifecycle Scripts

Package defines install-time lifecycle scripts.

package.jsonView on unpkg
scripts.postinstall = node scripts/postinstall.js || true; node scripts/fetch-adapters.js || true
Medium
Ambiguous Install Lifecycle Script

Install-time lifecycle script is not statically allowlisted and needs review.

package.jsonView on unpkg
dist/src/external.jsView file
1import*as Q from"node:fs";import*as Y from"node:path";import*as V from"node:os";import{fileURLToPath as M}from"node:url";import{spawnSync as U,execFileSync as L}from"node:child_pro...
High
Child Process

Package source references child process execution.

dist/src/external.jsView on unpkg · L1
dist/src/browser/article-extract.jsView file
1import*as j from"node:fs";import{createRequire as O}from"node:module";const v=O(import.meta.url);let Y=null;function U(){if(Y)return Y;const Q=v.resolve("@mozilla/readability/Reada... L2: `)}export async function extractArticle(Q,V={}){const Z=buildExtractArticleJs(V),W=await Q.evaluate(Z);if(W==null||typeof W!=="object")return null;const z=W;if(typeof z.html!=="str...
Low
Eval

Package source references a known benign dynamic code generation pattern.

dist/src/browser/article-extract.jsView on unpkg · L1
dist/src/discovery.jsView file
1import*as H from"node:fs";import*as G from"node:os";import*as Y from"node:path";import{fileURLToPath as F,pathToFileURL as v}from"node:url";import{Strategy as A,registerCommand as ... L2: `;try{if(await H.promises.readFile(x,"utf-8")!==B)await H.promises.writeFile(x,B,"utf-8")}catch{await H.promises.writeFile(x,B,"utf-8")}const V=L,q=Y.join(z,"node_modules","@jackwe...
Medium
Dynamic Require

Package source references dynamic require/import behavior.

dist/src/discovery.jsView on unpkg · L1
clis/flomo/memos.jsView file
1import{cli as y,Strategy as A}from"@jackwener/opencli/registry";import{ArgumentError as m,AuthRequiredError as l,CommandExecutionError as s,EmptyResultError as b}from"@jackwener/op... L2: (() => { ... L5: if (!raw) return null; L6: const me = JSON.parse(raw); L7: const token = me?.access_token || me?.data?.access_token || ''; ... L12: })() L13: `}function P(t){return/auth|unauth|login|token|permission|forbidden|unauthorized|登录|登陆|鉴权|权限/i.test(String(t||""))}function $(t){if(!Array.isArray(t))return"";return t.map((e)=>{if...
Low
Weak Crypto

Package source references weak cryptographic algorithms.

clis/flomo/memos.jsView on unpkg · L1
scripts/postinstall.jsView file
7* standard completion directory. For zsh and bash, the script prints manual L8: * instructions instead of modifying rc files (~/.zshrc, ~/.bashrc) — this L9: * avoids breaking multi-line shell commands and other fragile rc structures. ... L60: function detectShell() { L61: const shell = process.env.SHELL || ''; L62: if (shell.includes('zsh')) return 'zsh'; ... L77: // Skip in CI environments L78: if (process.env.CI || process.env.CONTINUOUS_INTEGRATION) { L79: return; ... L93: L94: const home = homedir(); L95:
Medium
Install Persistence

Source writes installer persistence such as shell profile or service configuration.

scripts/postinstall.jsView on unpkg · L7
dist/src/browser/managed-chrome.jsView file
1import{execFileSync as O}from"node:child_process";import*as I from"node:fs";import*as W from"node:path";import{request as C}from"node:http";import{WebSocket as N}from"ws";import{pr...
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/src/browser/managed-chrome.jsView on unpkg · L1
dist/src/launcher.jsView file
1import{execFileSync as B,spawn as w}from"node:child_process";import{request as D}from"node:http";import*as K from"node:path";import{getElectronApp as U}from"./electron-apps.js";imp... L2: ${j(W,J)} L3: `+` • Set OPENCLI_CDP_ENDPOINT=http://127.0.0.1:${J} L4: `+` • Or just re-run the command once ${W} is listening on port ${J}.`);if(detectProcess(X)){G.debug(`[launcher] ${W} is running but CDP not available`);if(!await q(`${W} is runni... L5: `);await killProcess(X)}const H=discoverAppPath(W);if(!H)throw new $(`Could not find ${W} on this machine.`,`Install ${W} or register a custom path in ~/.opencli/apps.yaml`);const ...
High
Command Output Exfiltration

Source combines command execution, command-output handling, and outbound requests; review data flow before blocking.

dist/src/launcher.jsView on unpkg · L1
scripts/check-doc-coverage.shView file
path = scripts/check-doc-coverage.sh kind = build_helper sizeBytes = 2256 magicHex = [redacted]
Medium
Ships Build Helper

Package ships non-JavaScript build or shell helper files.

scripts/check-doc-coverage.shView on unpkg

Findings

4 High7 Medium10 Low
HighInstall Time Lifecycle Scriptspackage.json
HighChild Processdist/src/external.js
HighSame File Env Network Executiondist/src/browser/managed-chrome.js
HighCommand Output Exfiltrationdist/src/launcher.js
MediumAmbiguous Install Lifecycle Scriptpackage.json
MediumDynamic Requiredist/src/discovery.js
MediumNetwork
MediumEnvironment Vars
MediumInstall Persistencescripts/postinstall.js
MediumShips Build Helperscripts/check-doc-coverage.sh
MediumStructural Risk Force Deep Review
LowNon Install Lifecycle Scripts
LowScripts Present
LowEvaldist/src/browser/article-extract.js
LowWeak Cryptoclis/flomo/memos.js
LowFilesystem
LowObfuscated
LowHigh Entropy Strings
LowTelemetry
LowUrl Strings
LowNo License