registry  /  fleetlens  /  0.16.2

fleetlens@0.16.2

fleetlens — local-only dashboard and usage tracker for Claude Code sessions and agent fleets

AI Security Review

scanned 2h ago · by lpm-firewall-ai

A normal `fleetlens start` can check the npm registry and globally reinstall the package when a newer version exists. The package also reads local Claude credentials to retrieve usage data from provider APIs. No install-time execution or confirmed malicious exfiltration is present.

Static reason
One or more suspicious static signals were detected.; previous stored version diff introduced dangerous source
Trigger
User runs `fleetlens start`; autostart requires an explicit CLI action or interactive confirmation.
Impact
A trusted installed version can replace itself with a newer registry version; provider credentials are used for intended usage API calls.
Mechanism
Automatic npm self-update plus local credential-backed usage collection.
Rationale
The package is not concretely malicious, but its automatic runtime self-update executes npm installation of a remote latest version during a normal start command. That is a meaningful dangerous capability requiring a warning rather than a publish block.
Evidence
package.jsondist/index.jsdist/daemon-worker.jsapp/apps/web/lib/agent/run.tsapp/apps/web/app/api/team/autostart/route.ts~/.claude/.credentials.json~/.config/claude/credentials.json~/Library/LaunchAgents/com.fleetlens.autostart.plist
Network endpoints4
registry.npmjs.org/fleetlens/latestapi.anthropic.com/api/oauth/usageapi.z.ai/api/monitor/usage/quota/limitcli-chat-proxy.grok.com/v1/billing?format=credits

Decision evidence

public snapshot
AI called this Suspicious at 84.0% confidence as Dangerous Capability with low false-positive risk.
Evidence for warning
  • `dist/index.js` runs update checks during `fleetlens start`.
  • `dist/index.js` fetches the npm registry then executes global `npm install -g fleetlens@latest`.
  • `dist/daemon-worker.js` reads Claude OAuth credentials and sends usage requests to Anthropic.
  • `dist/index.js` can install a macOS LaunchAgent after CLI invocation or interactive prompt.
Evidence against
  • `package.json` has no preinstall/install/postinstall lifecycle hook.
  • CLI server is configured for `localhost`; no broad agent-control mutation was found.
  • Credential reads support documented local usage tracking and provider usage endpoints.
  • No hidden exfiltration endpoint, obfuscated payload, eval, or foreign AI-agent config write was found.
Behavioral surface
Source
ChildProcessCryptoEnvironmentVarsFilesystemNetworkShell
Supply chain
HighEntropyStringsMinifiedUrlStrings
ManifestNo manifest risk signals triggered.
scanned 211 file(s), 2.65 MB of source, external domains: api.anthropic.com, api.z.ai, auth.x.ai, cli-chat-proxy.grok.com, example.com, github.com, keepachangelog.com, registry.npmjs.org, team.example.com, www.apple.com, z.ai

Source & flagged code

8 flagged · loading source
app/apps/web/app/api/menubar/route.tsView file
1import { execFile } from "node:child_process"; L2: import { promisify } from "node:util";
High
Child Process

Package source references child process execution.

app/apps/web/app/api/menubar/route.tsView on unpkg · L1
app/apps/web/app/api/pdf/[key]/route.tsView file
83L84: function digestExists(match: RegExpExecArray): boolean { L85: const monday = match[2];
High
Shell

Package source references shell execution.

app/apps/web/app/api/pdf/[key]/route.tsView on unpkg · L83
dist/index.jsView file
5844const dataDir = join3(homedir2(), ".claude", "projects"); L5845: const child = spawn(process.execPath, [serverJs], { L5846: detached: true, ... L5848: env: { L5849: ...process.env, L5850: PORT: String(port), ... L5859: writePid(PID_FILE, pid, port, onDiskVersion()); L5860: await waitForHealth(`http://localhost:${port}`, 3e4); L5861: return { pid, port };
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/index.jsView on unpkg · L5844
13import { readFileSync, writeFileSync, mkdirSync, unlinkSync } from "node:fs"; L14: import { execFileSync } from "node:child_process"; L15: import { dirname } from "node:path"; ... L943: "<command-name>", L944: "<local-command-stdout>", L945: "<local-command-caveat>", ... L990: try { L991: const parsed = JSON.parse(body); L992: if (parsed.type === "idle_notification") ... L1512: function walkBoundary(start2) { L1513: const home = realpathOrSelf(homedir()); L1514: return start2 === home || start2.startsWith(`${home}/`) ? home : void 0;
High
Sandbox Evasion Gated Capability

Source gates dangerous network, credential, or execution behavior behind CI, host, platform, time, or geo fingerprint checks.

dist/index.jsView on unpkg · L13
6161try { L6162: execSync(`npm install -g ${PACKAGE_NAME}@latest --prefer-online`, { L6163: stdio: "pipe",
High
Runtime Package Install

Package source invokes a package manager install command at runtime.

dist/index.jsView on unpkg · L6161
13import { readFileSync, writeFileSync, mkdirSync, unlinkSync } from "node:fs"; L14: import { execFileSync } from "node:child_process"; L15: import { dirname } from "node:path"; ... L943: "<command-name>", L944: "<local-command-stdout>", L945: "<local-command-caveat>", ... L990: try { L991: const parsed = JSON.parse(body); L992: if (parsed.type === "idle_notification") ... L1512: function walkBoundary(start2) { L1513: const home = realpathOrSelf(homedir()); L1514: return start2 === home || start2.startsWith(`${home}/`) ? home : void 0;
Medium
Install Persistence

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

dist/index.jsView on unpkg · L13
dist/daemon-worker.jsView file
875Cross-file remote execution chain: dist/daemon-worker.js spawns dist/index.js; helper contains network access plus dynamic code execution. L875: "<command-name>", L876: "<local-command-stdout>", L877: "<local-command-caveat>", ... L922: try { L923: const parsed = JSON.parse(body); L924: if (parsed.type === "idle_notification") ... L1488: const owner = segs.slice(0, -1).join("/"); L1489: return { host, owner, name, url, webUrl: `https://${host}/${owner}/${name}` }; L1490: } ... L1654: toTeammateId, L1655: body: msg.body, L1656: kind: "message"
High
Cross File Remote Execution Context

Source spawns a local helper that also contains network and dynamic execution context; review data flow before blocking.

dist/daemon-worker.jsView on unpkg · L875
app/apps/web/lib/agent/run.tsView file
matchType = previous_version_dangerous_delta matchedPackage = fleetlens@0.16.1 matchedIdentity = npm:ZmxlZXRsZW5z:0.16.1 similarity = 0.983 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.

app/apps/web/lib/agent/run.tsView on unpkg

Findings

1 Critical6 High4 Medium4 Low
CriticalPrevious Version Dangerous Deltaapp/apps/web/lib/agent/run.ts
HighChild Processapp/apps/web/app/api/menubar/route.ts
HighShellapp/apps/web/app/api/pdf/[key]/route.ts
HighSame File Env Network Executiondist/index.js
HighSandbox Evasion Gated Capabilitydist/index.js
HighCross File Remote Execution Contextdist/daemon-worker.js
HighRuntime Package Installdist/index.js
MediumNetwork
MediumEnvironment Vars
MediumInstall Persistencedist/index.js
MediumStructural Risk Force Deep Review
LowScripts Present
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings