registry  /  @yancyyu/agentcli  /  1.9.14

@yancyyu/agentcli@1.9.14

AgentCli: AI 工程协作平台,本地优先的用量采集与团队协作工具。

AI Security Review

scanned 2h ago · by lpm-firewall-ai

When the telemetry worker runs with configuration and an auth token, the package reads local AI-session messages and uploads their content to a hard-coded HTTP endpoint. Installation also writes package-owned workflow files beneath `~/.hermit`.

Static reason
High-risk behavior combination matched malicious policy.; previous stored version diff introduced dangerous source
Trigger
Running the CLI/server telemetry worker after installation; upload is default-on unless configuration opts out.
Impact
Private Claude Code/Codex conversation text, project metadata, and usage data can leave the machine over plaintext HTTP.
Mechanism
default-on collection and remote upload of AI conversation content
Attack narrative
The package's periodic telemetry path treats conversation upload as enabled by default. Once a usable local Bearer token exists, it collects Claude Code and Codex JSONL-derived message records, including message text and project/conversation metadata, then posts batches to a hard-coded IP address over HTTP. The install hook separately seeds marked workflows only inside the package's `~/.hermit` home, so that lifecycle write is not the blocking behavior.
Rationale
Concrete default-on remote transmission of local AI conversation content to a hard-coded plaintext endpoint is data exfiltration behavior. The install hook is package-scoped, but it does not mitigate the telemetry upload risk.
Evidence
bin/postinstall.mjssrc/main/services/session-intelligence/UsageTelemetryService.tssrc/main/services/session-intelligence/ConversationMessageUploadService.tssrc/main/telemetry/worker.tssrc/main/services/auth/OpenHermitAuthClient.ts~/.hermit/.claude/workflow/*~/.hermit/config.json~/.hermit/telemetry/conversation-message-upload.lock~/.hermit/telemetry/conversation-upload.log
Network endpoints2
159.75.231.98:8088/api/v1/report/messages159.75.231.98:8088/api/v1/auth/me

Decision evidence

public snapshot
AI called this Malicious at 94.0% confidence as Malware with low false-positive risk.
Evidence for block
  • `src/main/services/session-intelligence/UsageTelemetryService.ts` enables conversation upload by default unless explicitly disabled.
  • `ConversationMessageUploadService.ts` scans and uploads full Claude Code/Codex message content, not only token totals.
  • Uploads default to `http://159.75.231.98:8088/api/v1/report/messages` using a Bearer token.
  • `src/main/telemetry/worker.ts` runs periodic telemetry scans that invoke the upload path.
  • `bin/postinstall.mjs` seeds and refreshes package workflows under `~/.hermit/.claude/workflow` during install.
Evidence against
  • Upload waits for a locally stored valid Bearer token; no upload is sent when absent.
  • `bin/postinstall.mjs` has no network calls and confines its writes to `~/.hermit`.
  • Workflow seeding preserves files without the package marker instead of overwriting them.
Behavioral surface
Source
ChildProcessCryptoDynamicRequireEnvironmentVarsFilesystemNetworkShellWebSocket
Supply chain
HighEntropyStringsMinifiedUrlStrings
Manifest
CopyleftLicense
scanned 1,123 file(s), 10.3 MB of source, external domains: 0.0.0.0, 127.0.0.1, api.anthropic.com, api.dicebear.com, api.example.com, api.github.com, cdn.jsdelivr.net, chevrotain.io, en.wikipedia.org, github.com, jquery.org, langium.org, monitor.test, raw.githubusercontent.com, react.dev, redis.example.com, redis.lazymind.vip, registry.npmjs.org, tldrlegal.com, voicetext.site, www.w3.org, yancyuu.github.io, yancyyu.github.io
Oversized source lightweight scan
dist-renderer/assets/index-C1mZc0uS.js6.24 MB file, sampled 256 KB
NetworkChildProcessHighEntropyStringsMinifiedUrlStringsreact.dev

Source & flagged code

15 flagged · loading source
package.jsonView file
scripts.postinstall = node ./bin/postinstall.mjs
High
Install Time Lifecycle Scripts

Package defines install-time lifecycle scripts.

package.jsonView on unpkg
scripts.postinstall = node ./bin/postinstall.mjs
Medium
Ambiguous Install Lifecycle Script

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

package.jsonView on unpkg
bin/kill-dev.jsView file
1#!/usr/bin/env node L2: import { spawnSync } from 'child_process'; L3:
High
Child Process

Package source references child process execution.

bin/kill-dev.jsView on unpkg · L1
8stdio: 'inherit', L9: shell: true, L10: });
High
Shell

Package source references shell execution.

bin/kill-dev.jsView on unpkg · L8
bin/lib/navigationCommand.mjsView file
133L134: const require = createRequire(import.meta.url); L135:
Medium
Dynamic Require

Package source references dynamic require/import behavior.

bin/lib/navigationCommand.mjsView on unpkg · L133
bin/lib/teams.mjsView file
70if (!raw) return ''; L71: if (raw === '~') return os.homedir(); L72: if (raw.startsWith('~/')) return path.join(os.homedir(), raw.slice(2));
Low
Weak Crypto

Package source references weak cryptographic algorithms.

bin/lib/teams.mjsView on unpkg · L70
bin/lib/usageCommand.mjsView file
65import { existsSync, mkdirSync, writeFileSync, readFileSync, unlinkSync, openSync, closeSync, statSync } from 'node:fs'; L66: import { spawn, execSync } from 'node:child_process'; L67: import os from 'node:os'; ... L73: function fitProgressLine(text) { L74: const columns = Math.max(40, Number(process.stdout.columns || 80)); L75: const maxWidth = Math.max(20, columns - 2); ... L112: running: Boolean(server?.running), L113: url: server?.url || `http://127.0.0.1:${port}`, L114: version: server?.version || '', ... L263: return lines.flatMap((line) => { L264: try { return [JSON.parse(line)]; } catch { return []; } L265: });
Medium
Install Persistence

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

bin/lib/usageCommand.mjsView on unpkg · L65
bin/lib/auth.mjsView file
367async function openExternalUrl(url) { L368: const mode = process.env.OPENHERMIT_AUTH_OPEN_BROWSER || process.env.OPENHERMIT_OAUTH_OPEN_BROWSER; L369: if (mode === '0') return { opened: false, skipped: true }; L370: if (mode === 'fetch') { L371: await fetch(url, { redirect: 'follow', signal: AbortSignal.timeout(30_000) }); L372: return { opened: true, mode: 'fetch' }; ... L377: // as a single argument, so query characters (& ? =) need no shell quoting. L378: // The previous powershell `Start-Process -FilePath $args[0]` form exited L379: // non-zero and the browser silently never opened on Windows.
High
Same File Env Network Execution

A single source file combines environment access, network access, and code or shell execution; review context before blocking.

bin/lib/auth.mjsView on unpkg · L367
bin/postinstall.mjsView file
1Install-time AI-agent control hijack evidence: L3: import { L4: copyFileSync, L5: cpSync, L6: existsSync, L7: mkdirSync, L8: readFileSync, ... L11: rmSync, L12: writeFileSync, L13: } from 'node:fs'; ... L46: const bundledWorkflowsDir = path.join(packageRoot, 'src/main/services/system-manager/builtin-workflows'); L47: const hermitWorkflowDir = path.join(hermitHome, '.claude', 'workflow'); L48: const builtinWorkflowMarker = '<!-- hermit-builtin-workflow:v2-loop -->'; Payload evidence from src/renderer/features/CLAUDE.md: L1: # Renderer Features - Legacy Note L2:
Critical
Ai Agent Control Hijack

Install-time source drops package-supplied AI-agent/MCP control files or instructions.

bin/postinstall.mjsView on unpkg · L1
bin/lib/update.mjsView file
88try { L89: exec(`npm install -g ${BRAND.npmPackage}@latest --registry=https://registry.npmjs.org/`, { L90: stdio: 'inherit',
High
Runtime Package Install

Package source invokes a package manager install command at runtime.

bin/lib/update.mjsView on unpkg · L88
dist-renderer/icon.rarView file
path = dist-renderer/icon.rar kind = high_entropy_blob sizeBytes = 85506 magicHex = [redacted]
High
Ships High Entropy Blob

Package ships high-entropy non-source blobs.

dist-renderer/icon.rarView on unpkg
path = dist-renderer/icon.rar kind = compressed_blob sizeBytes = 85506 magicHex = [redacted]
Medium
Ships Compressed Blob

Package ships compressed or archive-like blobs.

dist-renderer/icon.rarView on unpkg
path = dist-renderer/icon.rar kind = nested_archive_needs_inspection sizeBytes = 85506 magicHex = [redacted]
Low
Nested Archive Needs Inspection

Package ships a nested archive or MCP bundle that was inventoried but not recursively analyzed.

dist-renderer/icon.rarView on unpkg
dist-renderer/assets/index-C1mZc0uS.jsView file
path = dist-renderer/assets/index-C1mZc0uS.js kind = oversized_source_file sizeBytes = 6543246 magicHex = [redacted]
High
Oversized Source File

Package contains source files above the static scanner size ceiling.

dist-renderer/assets/index-C1mZc0uS.jsView on unpkg
bin/hermit.mjsView file
matchType = previous_version_dangerous_delta matchedPackage = @yancyyu/agentcli@1.9.12 matchedIdentity = npm:QHlhbmN5eXUvYWdlbnRjbGk:1.9.12 similarity = 0.925 summary = stored previous version shares package body but lacks this dangerous source file
Critical
Previous Version Dangerous Delta

This package version adds a dangerous source file absent from the previous stored version; route for source-aware review.

bin/hermit.mjsView on unpkg

Findings

2 Critical7 High7 Medium7 Low
CriticalAi Agent Control Hijackbin/postinstall.mjs
CriticalPrevious Version Dangerous Deltabin/hermit.mjs
HighInstall Time Lifecycle Scriptspackage.json
HighChild Processbin/kill-dev.js
HighShellbin/kill-dev.js
HighSame File Env Network Executionbin/lib/auth.mjs
HighRuntime Package Installbin/lib/update.mjs
HighShips High Entropy Blobdist-renderer/icon.rar
HighOversized Source Filedist-renderer/assets/index-C1mZc0uS.js
MediumAmbiguous Install Lifecycle Scriptpackage.json
MediumDynamic Requirebin/lib/navigationCommand.mjs
MediumNetwork
MediumEnvironment Vars
MediumInstall Persistencebin/lib/usageCommand.mjs
MediumShips Compressed Blobdist-renderer/icon.rar
MediumStructural Risk Force Deep Review
LowScripts Present
LowWeak Cryptobin/lib/teams.mjs
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings
LowNested Archive Needs Inspectiondist-renderer/icon.rar
LowCopyleft License