registry  /  @goplausible/ac2-plugin-codex  /  0.1.2

@goplausible/ac2-plugin-codex@0.1.2

AC2 plugin for Codex — connects Codex to AC2 wallet peers over Liquid Auth (FIDO2) + WebRTC DataChannels.

AI Security Review

scanned 4h ago · by lpm-firewall-ai

LPM treats this as warn-only first-party agent extension lifecycle risk. This is a Codex agent extension that can bridge Codex to a wallet over Liquid Auth/WebRTC, relay hooks, request signatures, and make x402 paid HTTP calls. Risk is agent-extension capability exposure, not confirmed malware or unconsented install-time hijack.

Static reason
High-risk behavior combination matched malicious policy.
Trigger
User installs/enables the Codex plugin or runs the MCP server/bin.
Impact
A paired wallet user and enabled plugin can influence agent interactions and approve signatures/payments; no automatic credential theft or install-time foreign control-surface write was found.
Mechanism
Codex MCP wallet bridge with hooks, remote chat, signing, and x402 payment tools
Policy narrative
When explicitly enabled as a Codex plugin, the package starts an MCP server that pairs with an AC2 wallet, opens a local hook listener, relays Codex hook events/status to the wallet channel, and exposes tools for signing and x402 payments. The dangerous functions are aligned with the plugin's stated purpose and appear user/pairing mediated rather than install-time hijacking.
Rationale
Static inspection found a high-risk agent/wallet extension surface, but no npm install-time execution, credential harvesting, private-key exfiltration, broad foreign agent config mutation, or automatic fund transfer. Warn is appropriate for guarded Codex extension lifecycle and payment/signing capability risk.
Evidence
package.jsondist/server.js.mcp.json.codex-plugin/plugin.jsonhooks/hooks.jsonREADME.mdskills/ac2/SKILL.mdcommands/setup.md~/.codex/ac2/hook.port~/.codex/ac2/attachments/*
Network endpoints9
liquidauth.goplausible.xyzfacilitator.goplausible.xyzac2.io/v1127.0.0.1mainnet-api.4160.nodely.devtestnet-api.4160.nodely.devapi.mainnet-beta.solana.com/api.testnet.solana.comapi.devnet.solana.com

Decision evidence

public snapshot
AI called this Suspicious at 84.0% confidence as Dangerous Capability with medium false-positive risk.
Evidence for warning
  • .codex-plugin/plugin.json registers Codex skills and .mcp.json as a platform extension.
  • .mcp.json launches a stdio MCP server via npx @goplausible/ac2-plugin-codex@0.1.2.
  • hooks/hooks.json defines Codex hooks that POST prompt/tool/stop events to a local AC2 listener.
  • dist/server.js exposes wallet signing, x402 paid HTTP, remote approval relay, and WebRTC chat tooling.
  • dist/server.js writes runtime state such as ~/.codex/ac2/hook.port and attachment files.
Evidence against
  • package.json has no install/postinstall/prepare lifecycle; only prepublishOnly build tasks.
  • commands/setup.md says not to edit Claude settings files; no lifecycle mutation of foreign agent config found.
  • README.md and skills/ac2/SKILL.md describe user wallet approval and no private-key custody.
  • dist/server.js includes prompt-injection warning for inbound wallet messages and requires explicit pairing/signing tools.
  • Scanner wallet-drain hint maps to user-approved transaction signing/payment functionality, not local private-key theft.
Behavioral surface
Source
ChildProcessCryptoEnvironmentVarsEvalFilesystemNativeBindingsNetwork
Supply chain
HighEntropyStringsMinifiedObfuscatedProtestwareTelemetryUrlStrings
ManifestNo manifest risk signals triggered.
scanned 1 file(s), 1.92 MB of source, external domains: 127.0.0.1, api.devnet.solana.com, api.mainnet-beta.solana.com, api.testnet.solana.com, developer.mozilla.org, example.x402.goplausible.xyz, facilitator.goplausible.xyz, github.com, json-schema.org, mainnet-api.4160.nodely.dev, raw.githubusercontent.com, sola.na, testnet-api.4160.nodely.dev, viem.sh, www.w3.org

Source & flagged code

4 flagged · loading source
dist/server.jsView file
6const __filename = __ac2FileURLToPath(import.meta.url); L7: const __dirname = __ac2Dirname(__filename); L8: var j1e=Object.create;var _3=Object.defineProperty;var q1e=Object.getOwnPropertyDescriptor;var H1e=Object.getOwnPropertyNames;var Z1e=Object.getPrototypeOf,K1e=Object.prototype.has... L9: `:""},this._extScope=e,this._scope=new Ec.Scope({parent:e}),this._nodes=[new wR]}toString(){return this._root.render(this.opts)}name(e){return this._scope.name(e)}scopeName(e){retu... L10: || (${a} == "string" && ${i} && ${i} == +${i})`).assign(s,(0,$r._)`+${i}`);return;case"integer":n.elseIf((0,$r._)`${a} === "boolean" || ${i} === null L11: || (${a} === "string" && ${i} && ${i} == +${i} && !(${i} % 1))`).assign(s,(0,$r._)`+${i}`);return;case"boolean":n.elseIf((0,$r._)`${i} === "false" || ${i} === 0 || ${i} === null`).... L12: || ${a} === "boolean" || ${i} === null`).assign(s,(0,$r._)`[${i}]`)}}}function $4e({gen:t,parentData:e,parentDataProperty:r},n){t.if((0,$r._)`${e} !== undefined`,()=>t.assign((0,$r... L13: missingProperty: ${n}, ... L18: ${new this._window.XMLSerializer().serializeToString(h)}`;return typeof Blob>"u"||this._options.jsdom?Buffer.from(b):new Blob([b],{type:w})}return
Critical
Wallet Drain

Source uses private key material to transfer cryptocurrency funds.

dist/server.jsView on unpkg · L6
6Trigger-reachable chain: manifest.bin -> dist/server.js L6: const __filename = __ac2FileURLToPath(import.meta.url); L7: const __dirname = __ac2Dirname(__filename); L8: var j1e=Object.create;var _3=Object.defineProperty;var q1e=Object.getOwnPropertyDescriptor;var H1e=Object.getOwnPropertyNames;var Z1e=Object.getPrototypeOf,K1e=Object.prototype.has... L9: `:""},this._extScope=e,this._scope=new Ec.Scope({parent:e}),this._nodes=[new wR]}toString(){return this._root.render(this.opts)}name(e){return this._scope.name(e)}scopeName(e){retu... L10: || (${a} == "string" && ${i} && ${i} == +${i})`).assign(s,(0,$r._)`+${i}`);return;case"integer":n.elseIf((0,$r._)`${a} === "boolean" || ${i} === null L11: || (${a} === "string" && ${i} && ${i} == +${i} && !(${i} % 1))`).assign(s,(0,$r._)`+${i}`);return;case"boolean":n.elseIf((0,$r._)`${i} === "false" || ${i} === 0 || ${i} === null`).... L12: || ${a} === "boolean" || ${i} === null`).assign(s,(0,$r._)`[${i}]`)}}}function $4e({gen:t,parentData:e,parentDataProperty:r},n){t.if((0,$r._)`${e} !== undefined`,()=>t.assign((0,$r... L13: missingProperty: ${n}, ... L18: ${new this._window.XMLSerializer().serializeToString(h)}`;return typeof Blob>"u"||this._o…
Critical
Trigger Reachable Dangerous Capability

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

dist/server.jsView on unpkg · L6
11|| (${a} === "string" && ${i} && ${i} == +${i} && !(${i} % 1))`).assign(s,(0,$r._)`+${i}`);return;case"boolean":n.elseIf((0,$r._)`${i} === "false" || ${i} === 0 || ${i} === null`).... L12: || ${a} === "boolean" || ${i} === null`).assign(s,(0,$r._)`[${i}]`)}}}function $4e({gen:t,parentData:e,parentDataProperty:r},n){t.if((0,$r._)`${e} !== undefined`,()=>t.assign((0,$r... L13: missingProperty: ${n},
Low
Eval

Package source references a known benign dynamic code generation pattern.

dist/server.jsView on unpkg · L11
6const __filename = __ac2FileURLToPath(import.meta.url); L7: const __dirname = __ac2Dirname(__filename); L8: var j1e=Object.create;var _3=Object.defineProperty;var q1e=Object.getOwnPropertyDescriptor;var H1e=Object.getOwnPropertyNames;var Z1e=Object.getPrototypeOf,K1e=Object.prototype.has... L9: `:""},this._extScope=e,this._scope=new Ec.Scope({parent:e}),this._nodes=[new wR]}toString(){return this._root.render(this.opts)}name(e){return this._scope.name(e)}scopeName(e){retu... L10: || (${a} == "string" && ${i} && ${i} == +${i})`).assign(s,(0,$r._)`+${i}`);return;case"integer":n.elseIf((0,$r._)`${a} === "boolean" || ${i} === null L11: || (${a} === "string" && ${i} && ${i} == +${i} && !(${i} % 1))`).assign(s,(0,$r._)`+${i}`);return;case"boolean":n.elseIf((0,$r._)`${i} === "false" || ${i} === 0 || ${i} === null`).... L12: || ${a} === "boolean" || ${i} === null`).assign(s,(0,$r._)`[${i}]`)}}}function $4e({gen:t,parentData:e,parentDataProperty:r},n){t.if((0,$r._)`${e} !== undefined`,()=>t.assign((0,$r... L13: missingProperty: ${n}, ... L18: ${new this._window.XMLSerializer().serializeToString(h)}`;return typeof Blob>"u"||this._options.jsdom?Buffer.from(b):new Blob([b],{type:w})}return
Low
Weak Crypto

Package source references weak cryptographic algorithms.

dist/server.jsView on unpkg · L6

Findings

2 Critical1 High4 Medium8 Low
CriticalWallet Draindist/server.js
CriticalTrigger Reachable Dangerous Capabilitydist/server.js
HighObfuscated
MediumNetwork
MediumEnvironment Vars
MediumProtestware
MediumStructural Risk Force Deep Review
LowNon Install Lifecycle Scripts
LowScripts Present
LowEvaldist/server.js
LowWeak Cryptodist/server.js
LowFilesystem
LowHigh Entropy Strings
LowTelemetry
LowUrl Strings