registry  /  claude-codex-wechat  /  0.1.30

claude-codex-wechat@0.1.30

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

AI Security Review

scanned 12h ago · by lpm-firewall-ai

The package is a user-invoked WeChat bridge for Claude/Codex with dangerous agent-facing capabilities. It can run Claude with permissions disabled, attach remote chat input to local agent sessions, and install a persistent background service when the CLI is started.

Static reason
High-risk behavior combination matched malicious policy.; previous stored version diff introduced dangerous source
Trigger
User runs claude-codex-wechat start or uses the bridge UI/API to connect WeChat and agent sessions
Impact
Remote WeChat messages can drive local Claude/Codex sessions with broad local agent privileges; service persistence keeps the bridge running after start.
Mechanism
remote chat bridge plus permission-bypassing agent launcher and session metadata mutation
Attack narrative
No npm install-time hijack was confirmed. The risk is that after a user starts the bridge, WeChat or relay-delivered messages can control local Claude/Codex sessions while the package launches Claude with --dangerously-skip-permissions, registers a media MCP config, mutates Claude/Codex session metadata, and can persist as a user service.
Rationale
Source inspection supports a real dangerous agent-control surface, but activation is user-invoked and package-aligned rather than an unconsented npm lifecycle mutation. Warn rather than block.
Evidence
package.jsondist/server/cli.jsdist/mcp/mediaServer.jsconfig.example.json~/.claude-codex-wechat/config.json~/.claude-codex-wechat/mcp-media.json~/.claude/projects/*/*.jsonl~/.claude/history.jsonl~/.codex/session_index.jsonl~/.codex/state_5.sqlite~/Library/LaunchAgents/com.claude-codex-wechat.plist~/.config/systemd/user/claude-codex-wechat.service
Network endpoints6
ilinkai.weixin.qq.comwss://wechat.style520.com/agentnovac2c.cdn.weixin.qq.com/c2cregistry.npmmirror.com/claude-codex-wechat/latest127.0.0.1:8787localhost:8787

Decision evidence

public snapshot
AI called this Suspicious at 88.0% confidence as Dangerous Capability with medium false-positive risk.
Evidence for block
  • dist/server/cli.js starts Claude with --dangerously-skip-permissions and optional --mcp-config for bridge media tools
  • dist/server/cli.js can modify ~/.claude project session JSONL/history and inserts permissionMode=bypassPermissions when normalizing sdk-cli sessions
  • dist/server/cli.js user-invoked start installs persistent launchd/systemd-user service or detached Windows daemon
  • dist/server/cli.js bridges WeChat/relay messages into Claude/Codex sessions and can steer active turns
  • dist/mcp/mediaServer.js exposes MCP tools that send arbitrary absolute file paths to the local bridge for WeChat media upload
Evidence against
  • package.json has no install/postinstall lifecycle hook; prepublishOnly is publish-time build only
  • Network endpoints are package-aligned WeChat, relay, media CDN, and update-check services
  • No confirmed eval/vm/Function remote code execution pattern found in inspected source
  • Persistence is activated by CLI start/restart commands, not npm installation
  • Config and generated MCP files are under ~/.claude-codex-wechat except explicit Claude/Codex session metadata updates
Behavioral surface
Source
ChildProcessCryptoEnvironmentVarsFilesystemNetworkShellWebSocket
Supply chain
HighEntropyStringsMinifiedUrlStrings
Manifest
NoLicenseWildcardDependency
scanned 3 file(s), 463 KB of source, external domains: 127.0.0.1, ilinkai.weixin.qq.com, novac2c.cdn.weixin.qq.com, react.dev, registry.npmmirror.com, www.apple.com, www.w3.org

Source & flagged code

8 flagged · loading source
dist/server/cli.jsView file
22// src/channels/weixin-direct/loginClient.ts L23: var DEFAULT_BASE_URL = "https://ilinkai.weixin.qq.com"; L24: var WeixinDirectLoginClient = class { ... L61: if (!response.ok) throw new Error(`weixin_login_request_failed:${response.status}`); L62: const payload = await response.json(); L63: return payload.data ?? payload; ... L71: function defaultConfigPath() { L72: return join(homedir(), ".claude-codex-wechat", "config.json"); L73: } L74: function loadBridgeConfig(path = process.env.BRIDGE_CONFIG ?? defaultConfigPath()) { L75: if (!existsSync(path)) return normalizeBridgeConfig({}, process.env, path); ... L170: function isRetriableRenameError(error) {
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 · L22
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
matchType = previous_version_dangerous_delta matchedPackage = claude-codex-wechat@0.1.27 matchedIdentity = npm:Y2xhdWRlLWNvZGV4LXdlY2hhdA:0.1.27 similarity = 0.500 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/server/cli.jsView on unpkg
2762// src/providers/claude-code/claudeStreamingRunner.ts L2763: import { spawn as spawn3 } from "node:child_process"; L2764: import { randomUUID as randomUUID2 } from "node:crypto";
High
Child Process

Package source references child process execution.

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

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

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

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

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

Package source references weak cryptographic algorithms.

dist/server/cli.jsView on unpkg · L22
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

3 Critical4 High5 Medium7 Low
CriticalRemote Asset Decode Executedist/server/cli.js
CriticalTrigger Reachable Dangerous Capabilitydist/server/cli.js
CriticalPrevious Version Dangerous Deltadist/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
LowWeak Cryptodist/server/cli.js
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings
LowNo License