registry  /  caveat-cli  /  0.16.3

caveat-cli@0.16.3

Long-term memory CLI for Claude Code and Codex (markdown + SQLite FTS5 + MCP + hooks)

AI Security Review

scanned 3h ago · by lpm-firewall-ai

LPM treats this as warn-only first-party agent extension lifecycle risk. No install-time attack surface was found. Explicit CLI setup can register Caveat-owned Claude/Codex hooks and local MCP integration, with backups and uninstall support. No confirmed exfiltration or remote code-loading chain was found.

Static reason
One or more suspicious static signals were detected.; previous stored version diff introduced dangerous source
Trigger
User runs `caveat init` or `caveat codex-hook install`.
Impact
Hooks run Caveat commands during configured Claude/Codex events; setup mutates the user's agent configuration only after user invocation.
Mechanism
Explicit first-party AI-agent hook and MCP configuration.
Rationale
Static scanner signals are explained by bundled schema tooling and explicit CLI-controlled hook/sidecar features. The package should be warned for its intentional first-party agent integration risk, not blocked as malicious.
Evidence
package.jsondist/caveat.jsdist/index.jsdist/server-ZMIRSFMH.jsREADME.md~/.claude/settings.json~/.codex/hooks.json~/.codex/config.toml~/.caveat/

Decision evidence

public snapshot
AI called this Suspicious at 90.0% confidence as Dangerous Capability with low false-positive risk.
Evidence for warning
  • `dist/index.js` explicitly installs Claude and Codex hooks that execute the Caveat CLI.
  • `dist/index.js` writes `~/.claude/settings.json`, `~/.codex/hooks.json`, and may enable Codex hooks in `~/.codex/config.toml`.
Evidence against
  • `package.json` has no preinstall, install, postinstall, or other lifecycle hook.
  • `dist/caveat.js` only imports the CLI entry after the user runs `caveat`.
  • Hook registration is behind explicit `caveat init` or `caveat codex-hook install` commands and supports `--dry-run`.
  • Installers preserve backups and remove only Caveat-owned hook commands on uninstall.
  • No credential harvesting, outbound HTTP client call, remote payload fetch, or eval-based execution was confirmed in the inspected CLI code.
  • `dist/server-ZMIRSFMH.js` serves a local portal on `127.0.0.1`, not a remote listener.
Behavioral surface
Source
ChildProcessCryptoDynamicRequireEnvironmentVarsEvalFilesystemNetworkShell
Supply chain
HighEntropyStringsUrlStrings
ManifestNo manifest risk signals triggered.
scanned 4 file(s), 2.16 MB of source, external domains: developer.mozilla.org, developers.cloudflare.com, gist.github.com, github.com, hono.dev, json-schema.org, mathiasbynens.be, raw.githubusercontent.com, spec.openapis.org, stackoverflow.com, tools.ietf.org, www.w3.org

Source & flagged code

6 flagged · loading source
dist/index.jsView file
matchType = previous_version_dangerous_delta matchedPackage = caveat-cli@0.16.1 matchedIdentity = npm:Y2F2ZWF0LWNsaQ:0.16.1 similarity = 0.750 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.

dist/index.jsView on unpkg
6884// src/commands/init.ts L6885: import { spawnSync as spawnSync4 } from "node:child_process"; L6886: import { existsSync as existsSync5, mkdirSync as mkdirSync3, readdirSync, renameSync, rmdirSync, writeFileSync as writeFileSync4 } from "node:fs";
High
Child Process

Package source references child process execution.

dist/index.jsView on unpkg · L6884
7002const line = [CLAUDE_BIN, ...args].map(shellQuote).join(" "); L7003: return spawnSync(line, { shell: true, encoding: "utf-8" }); L7004: }
High
Shell

Package source references shell execution.

dist/index.jsView on unpkg · L7002
63Cross-file remote execution chain: dist/index.js spawns dist/server-ZMIRSFMH.js; helper contains network access plus dynamic code execution. L63: setRuntimeErrorStatus, L64: stderrLogger, L65: stopReminderText, ... L1268: // validation function arguments L1269: data: new codegen_1.Name("data"), L1270: // data passed to validation function ... L2295: id = normalizeId(id); L2296: return resolver.resolve(baseId, id); L2297: } ... L3155: for (i = 0; i < input.length; i++) { L3156: code = input[i].charCodeAt(0); L3157: if (code === 48) {
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/index.jsView on unpkg · L63
dist/chunk-PD5E6TFL.jsView file
2import { createRequire as __caveat_createRequire } from 'node:module'; L3: const require = __caveat_createRequire(import.meta.url); L4: var __create = Object.create;
Medium
Dynamic Require

Package source references dynamic require/import behavior.

dist/chunk-PD5E6TFL.jsView on unpkg · L2
1383if (ast.body[0].expression.body.type === "BlockStatement") { L1384: return new Function(params, source.slice(body[0] + 1, body[1] - 1)); L1385: }
Low
Eval

Package source references a known benign dynamic code generation pattern.

dist/chunk-PD5E6TFL.jsView on unpkg · L1383

Findings

1 Critical3 High3 Medium5 Low
CriticalPrevious Version Dangerous Deltadist/index.js
HighChild Processdist/index.js
HighShelldist/index.js
HighCross File Remote Execution Contextdist/index.js
MediumDynamic Requiredist/chunk-PD5E6TFL.js
MediumNetwork
MediumEnvironment Vars
LowScripts Present
LowEvaldist/chunk-PD5E6TFL.js
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings