registry  /  claude-codex-wechat  /  0.1.18

claude-codex-wechat@0.1.18

`claude-codex-wechat` 是一个本地 bridge daemon。它把:

AI Security Review

scanned 3d ago · by lpm-firewall-ai

User-invoked start creates a persistent local bridge daemon and default relay tunnel. The relay server can forward HTTP requests into the local admin/API surface, which can drive Claude Code or Codex sessions.

Static reason
High-risk behavior combination matched malicious policy.
Trigger
Running `claude-codex-wechat start` or default CLI start
Impact
Remote relay/authorized WeChat control can steer local Claude/Codex agents and access bridge APIs; risk depends on relay/auth trust and intended deployment.
Mechanism
persistent relay-backed local AI-agent bridge
Attack narrative
On user start, the package installs/starts a background daemon, listens broadly, generates relay credentials, and connects to a default WebSocket relay. Relay messages are translated into local HTTP requests against the bridge API, whose documented purpose is to let WeChat users drive local Claude Code/Codex sessions. This is not install-time malware, but it is a real remote agent-control surface with persistence.
Rationale
Source inspection does not support a malicious install-time payload or hidden decode-execute behavior, but the package exposes a persistent relay-controlled AI-agent bridge by default after user start. That dangerous capability is documented and package-aligned, so warn rather than block.
Evidence
package.jsonREADME.mdconfig.example.jsondist/server/cli.js~/.claude-codex-wechat/config.json~/Library/LaunchAgents/com.claude-codex-wechat.plist~/.config/systemd/user/claude-codex-wechat.service~/.claude-codex-wechat/service.pid~/.claude-codex-wechat/logs/service.stdout.log~/.claude-codex-wechat/logs/service.stderr.log
Network endpoints5
ilinkai.weixin.qq.comnovac2c.cdn.weixin.qq.com/c2cwss://wechat.style520.com/agent127.0.0.1:87870.0.0.0:8787

Decision evidence

public snapshot
AI called this Suspicious at 78.0% confidence as Dangerous Capability with medium false-positive risk.
Evidence for block
  • dist/server/cli.js starts a Fastify daemon on host 0.0.0.0 port 8787 by default.
  • dist/server/cli.js auto-generates relay credentials and connects to wss://wechat.style520.com/agent when daemon starts.
  • Relay handler proxies relay-supplied HTTP requests to http://127.0.0.1:<port><path>.
  • Local/admin APIs can attach/start Claude Code or Codex sessions and spawn codex/claude app-server/CLI processes.
  • start command installs persistent launchd/systemd-user service or detached Windows process.
Evidence against
  • No npm install/postinstall/preinstall lifecycle execution; prepublishOnly only builds before publishing.
  • Scanner remote decode/execute hint is noisy: mediaDownloader fetches WeChat media, AES-decrypts it, and writes bytes; no execution found.
  • No eval, Function, vm, dynamic import, curl/wget, or shell payload pattern found.
  • Network endpoints are package-aligned with documented WeChat/relay bridge behavior.
  • README discloses local daemon, WeChat control plane, Codex/Claude bridge, and service commands.
Behavioral surface
Source
ChildProcessCryptoEnvironmentVarsFilesystemNetworkShellWebSocket
Supply chain
HighEntropyStringsMinifiedUrlStrings
Manifest
NoLicenseWildcardDependency
scanned 2 file(s), 424 KB of source, external domains: 127.0.0.1, ilinkai.weixin.qq.com, novac2c.cdn.weixin.qq.com, react.dev, www.apple.com, www.w3.org

Source & flagged code

6 flagged · loading source
dist/server/cli.jsView file
21// src/channels/weixin-direct/loginClient.ts L22: var DEFAULT_BASE_URL = "https://ilinkai.weixin.qq.com"; L23: var WeixinDirectLoginClient = class { ... L60: if (!response.ok) throw new Error(`weixin_login_request_failed:${response.status}`); L61: const payload = await response.json(); L62: return payload.data ?? payload; ... L70: function defaultConfigPath() { L71: return join(homedir(), ".claude-codex-wechat", "config.json"); L72: } L73: function loadBridgeConfig(path = process.env.BRIDGE_CONFIG ?? defaultConfigPath()) { L74: if (!existsSync(path)) return normalizeBridgeConfig({}, process.env, path); ... L1077: }));
Critical
Remote Asset Decode Execute

Source fetches a remote non-code asset, decodes its contents, and dynamically executes the decoded payload.

dist/server/cli.jsView on unpkg · L21
Trigger-reachable chain: manifest.bin -> dist/server/cli.js Reachable file contains a blocking source-risk pattern.
Critical
Trigger Reachable Dangerous Capability

A package entrypoint or install-time lifecycle script reaches a source file with blocking dangerous behavior.

dist/server/cli.jsView on unpkg
2321// src/providers/claude-code/claudeStreamingRunner.ts L2322: import { spawn as spawn2 } from "node:child_process"; L2323: import { randomUUID as randomUUID2 } from "node:crypto";
High
Child Process

Package source references child process execution.

dist/server/cli.jsView on unpkg · L2321
21Detached bundled service listener: dist/server/cli.js launches a Node helper and exposes a broad-bound HTTP listener. L21: // src/channels/weixin-direct/loginClient.ts L22: var DEFAULT_BASE_URL = "https://ilinkai.weixin.qq.com"; L23: var WeixinDirectLoginClient = class { ... L60: if (!response.ok) throw new Error(`weixin_login_request_failed:${response.status}`); L61: const payload = await response.json(); L62: return payload.data ?? payload; ... L70: function defaultConfigPath() { L71: return join(homedir(), ".claude-codex-wechat", "config.json"); L72: } L73: function loadBridgeConfig(path = process.env.BRIDGE_CONFIG ?? defaultConfigPath()) { L74: if (!existsSync(path)) return normalizeBridgeConfig({}, process.env, path); ... L1077: }));
High
Spawned Bundled Service Listener

Source launches a detached bundled service that exposes a broad-bound HTTP listener.

dist/server/cli.jsView on unpkg · L21
21// src/channels/weixin-direct/loginClient.ts L22: var DEFAULT_BASE_URL = "https://ilinkai.weixin.qq.com"; L23: var WeixinDirectLoginClient = class { ... L60: if (!response.ok) throw new Error(`weixin_login_request_failed:${response.status}`); L61: const payload = await response.json(); L62: return payload.data ?? payload; ... L70: function defaultConfigPath() { L71: return join(homedir(), ".claude-codex-wechat", "config.json"); L72: } L73: function loadBridgeConfig(path = process.env.BRIDGE_CONFIG ?? defaultConfigPath()) { L74: if (!existsSync(path)) return normalizeBridgeConfig({}, process.env, path); ... L1077: }));
Medium
Install Persistence

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

dist/server/cli.jsView on unpkg · L21
dist/web/assets/bootstrap-icons-mSm7cUeB.woff2View file
path = dist/web/assets/bootstrap-icons-mSm7cUeB.woff2 kind = high_entropy_blob sizeBytes = 134044 magicHex = [redacted]
High
Ships High Entropy Blob

Package ships high-entropy non-source blobs.

dist/web/assets/bootstrap-icons-mSm7cUeB.woff2View on unpkg

Findings

2 Critical4 High5 Medium6 Low
CriticalRemote Asset Decode Executedist/server/cli.js
CriticalTrigger Reachable Dangerous Capabilitydist/server/cli.js
HighChild Processdist/server/cli.js
HighShell
HighSpawned Bundled Service Listenerdist/server/cli.js
HighShips High Entropy Blobdist/web/assets/bootstrap-icons-mSm7cUeB.woff2
MediumNetwork
MediumEnvironment Vars
MediumInstall Persistencedist/server/cli.js
MediumStructural Risk Force Deep Review
MediumWildcard Dependency
LowNon Install Lifecycle Scripts
LowScripts Present
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings
LowNo License