registry  /  wyrm-mcp  /  7.4.0

wyrm-mcp@7.4.0

Local-first persistent memory for AI agents over MCP. Ground truths, negative learning (recorded failures block repeats), decision causality, hybrid recall, live memory streams, run-attributed fleet memory — a structured SQLite memory on your machine, no

AI Security Review

scanned 3h ago · by lpm-firewall-ai

LPM treats this as warn-only first-party agent extension lifecycle risk. Lifecycle behavior is non-clean because install scripts write first-party Wyrm state under ~/.wyrm and may patch node-gyp build metadata on Termux. The broader AI-agent control surface writes exist, but are behind explicit Wyrm setup/CLI commands rather than npm install.

Static reason
One or more suspicious static signals were detected.; previous stored version diff introduced dangerous source
Trigger
npm install runs lifecycle scripts; user-invoked wyrm-setup/wyrm commands configure AI clients
Impact
Warn-level lifecycle and agent-extension risk without confirmed malicious delivery
Mechanism
first-party agent extension setup and guarded AI-client autoconfiguration
Policy narrative
On install, the package runs preinstall/postinstall. Postinstall registers bundled package skills into Wyrm-owned ~/.wyrm metadata; preinstall opportunistically patches node-gyp common.gypi for Termux compatibility. Separate setup commands can register Wyrm MCP entries and Claude hooks/statusline, but those are explicit CLI flows, not unconsented lifecycle mutation.
Rationale
Source inspection confirms real lifecycle writes and agent-extension capabilities, but the dangerous foreign AI-control-surface mutations are not install-triggered and appear package-aligned/user-invoked. This fits warn-level agent extension lifecycle risk rather than malicious publish blocking.
Evidence
package.jsonscripts/preinstall.cjsscripts/postinstall.cjsdist/autoconfig.jsdist/setup.jsdist/wyrm-cli.jsdist/handlers/companion.jsdist/cloud/client.jsdist/auto-capture.js~/.wyrm/bundled-skills.json~/.wyrm/.first-install-shown~/.cache/node-gyp/<node>/include/node/common.gypi~/.electron-gyp/<node>/common.gypi/usr/include/node/common.gypi/usr/lib/node_modules/node-gyp/include/node/common.gypi~/.claude/settings.json~/.claude/hooks/wyrm-session-capture.mjs~/.claude/hooks/wyrm-session-rehydrate.mjs~/.claude/hooks/wyrm-session-prune.mjs~/.claude/hooks/wyrm-tool-call-trace.mjs
Network endpoints2
wyrm.ghosts.lklocalhost:11434

Decision evidence

public snapshot
AI called this Suspicious at 86.0% confidence as Dangerous Capability with medium false-positive risk.
Evidence for warning
  • package.json defines preinstall and postinstall lifecycle scripts.
  • scripts/postinstall.cjs creates ~/.wyrm and writes bundled-skills.json plus .first-install-shown during install.
  • scripts/preinstall.cjs can patch node-gyp common.gypi on Android/Termux hosts.
  • dist/autoconfig.js can write MCP configs and Claude hooks/statusline, including ~/.claude/settings.json, but via wyrm-setup/wyrm CLI.
  • dist/handlers/companion.js contains confirmed self-update path running npm install -g wyrm-mcp@latest only after confirm:true.
Evidence against
  • No install-time writes to Claude/Cursor/Codex foreign AI control surfaces were found.
  • Postinstall writes only Wyrm's own ~/.wyrm namespace and displays setup instructions.
  • AI client config and Claude hook mutations are user-invoked through setup/CLI commands.
  • Cloud/network code is package-aligned to Wyrm sync/backup endpoints and local Ollama.
  • No credential harvesting, hidden exfiltration, destructive logic, or remote code execution was confirmed.
Behavioral surface
Source
ChildProcessCryptoDynamicRequireEnvironmentVarsFilesystemNativeBindingsNetworkShell
Supply chain
HighEntropyStringsUrlStrings
Manifest
NoLicense
scanned 161 file(s), 2.01 MB of source, external domains: 127.0.0.1, account.ghosts.lk, api.openai.com, fonts.googleapis.com, fonts.gstatic.com, ghosts.lk, github.com, registry.npmjs.org, www.cloudflarestatus.com, wyrm.ghosts.lk

Source & flagged code

10 flagged · loading source
package.jsonView file
scripts.postinstall = node scripts/postinstall.cjs
High
Install Time Lifecycle Scripts

Package defines install-time lifecycle scripts.

package.jsonView on unpkg
scripts.preinstall = node scripts/preinstall.cjs
Medium
Ambiguous Install Lifecycle Script

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

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

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

package.jsonView on unpkg
dist/database.jsView file
18import { join, basename, resolve, normalize } from 'path'; L19: import { spawnSync } from 'child_process'; L20: import { getResilienceManager } from './resilience.js';
High
Child Process

Package source references child process execution.

dist/database.jsView on unpkg · L18
dist/autoconfig.jsView file
669* containing a command substitution would EXECUTE on every tool call (crucible L670: * HIGH 2026-07-03). cmd.exe (Windows) does not honor single quotes, so there L671: * we wrap in double quotes and escape embedded double-quotes.
High
Shell

Package source references shell execution.

dist/autoconfig.jsView on unpkg · L669
dist/wyrm-cli.jsView file
matchType = previous_version_dangerous_delta matchedPackage = wyrm-mcp@7.3.3 matchedIdentity = npm:d3lybS1tY3A:7.3.3 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.

dist/wyrm-cli.jsView on unpkg
1622} L1623: console.log(c.dim('\n Running: npm install -g wyrm-mcp@latest\n')); L1624: const r = spawnSync('npm', ['install', '-g', 'wyrm-mcp@latest'], { stdio: 'inherit', shell: false }); L1625: if (r.status === 0)
High
Runtime Package Install

Package source invokes a package manager install command at runtime.

dist/wyrm-cli.jsView on unpkg · L1622
581{ L582: const bridge = await import('./reverse-bridge.js'); L583: const preBrief = buildRenderPlan(deps, project, stamp);
Medium
Dynamic Require

Package source references dynamic require/import behavior.

dist/wyrm-cli.jsView on unpkg · L581
dist/harvest.jsView file
18*/ L19: import { execFileSync } from 'child_process'; L20: import { readFileSync, existsSync } from 'fs'; ... L103: const out = []; L104: // ── package.json → stack fact ── L105: const pkgPath = join(projectPath, 'package.json'); ... L107: try { L108: const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')); L109: const deps = Object.keys({ ...pkg.dependencies, ...pkg.devDependencies }).slice(0, 16);
Low
Weak Crypto

Package source references weak cryptographic algorithms.

dist/harvest.jsView on unpkg · L18
dist/wyrm-ui.jsView file
18*/ L19: import { spawn } from 'child_process'; L20: const PORT = parseInt(process.env.WYRM_HTTP_PORT ?? '3333', 10) || 3333; L21: const HOST = '127.0.0.1'; L22: const URL_BASE = `http://${HOST}:${PORT}`; L23: async function isHttpUp() {
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/wyrm-ui.jsView on unpkg · L18

Findings

1 Critical5 High6 Medium7 Low
CriticalPrevious Version Dangerous Deltadist/wyrm-cli.js
HighInstall Time Lifecycle Scriptspackage.json
HighChild Processdist/database.js
HighShelldist/autoconfig.js
HighSame File Env Network Executiondist/wyrm-ui.js
HighRuntime Package Installdist/wyrm-cli.js
MediumAmbiguous Install Lifecycle Scriptpackage.json
MediumAmbiguous Install Lifecycle Scriptpackage.json
MediumDynamic Requiredist/wyrm-cli.js
MediumNetwork
MediumEnvironment Vars
MediumStructural Risk Force Deep Review
LowNon Install Lifecycle Scripts
LowScripts Present
LowWeak Cryptodist/harvest.js
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings
LowNo License