@minhspark/codex-mcp-bridge 1.11.2 → 1.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,10 +2,22 @@
2
2
 
3
3
  Follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and [SemVer](https://semver.org/).
4
4
 
5
- ## [Unreleased]
5
+ ## [1.11.3] - 2026-09-03
6
6
 
7
7
  ### Fixed
8
8
 
9
+ - **The peer endpoint never started on Windows, so the bridge was one-way there.** `/tmp/cc-socks` has no
10
+ Windows equivalent, and `path.join` rewrote it to `\tmp\cc-socks` on the system drive, where `listen()`
11
+ fails with `EACCES`. Codex could push a message into a live Claude session, but Claude had no address to
12
+ answer on - and the only sign was one line on stderr saying replies could not be received, which nothing
13
+ surfaces once the server is running under an MCP client. The peer now listens on a named pipe on Windows,
14
+ the same transport Claude Code itself advertises in `~/.claude/sessions/<pid>.json`, and skips the
15
+ directory, mode and unlink steps that a pipe does not have.
16
+
17
+ - `fast-uri` is bumped to 3.1.7 and `qs` to 6.16.0. `fast-uri` 3.0.0-3.1.5 is vulnerable to host confusion
18
+ and server-side request forgery through repeated hostname percent-decoding (CVE-2026-75899, high); it
19
+ reaches the tree transitively through `@modelcontextprotocol/sdk` -> `ajv`.
20
+
9
21
  - **A tag is not a release, and nothing was creating the release.** Pushing `v1.10.1`, `v1.11.0` and
10
22
  `v1.11.1` published all three to npm, while the Releases page still showed `v1.10.0` as *Latest* -
11
23
  the one release that had been created by hand. Anyone reading the repository saw a project that had
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minhspark/codex-mcp-bridge",
3
- "version": "1.11.2",
3
+ "version": "1.11.3",
4
4
  "description": "Two-way MCP bridge between Claude and Codex: prompts into a live Codex thread, messages into a running Claude Code session.",
5
5
  "keywords": [
6
6
  "mcp",
@@ -8,7 +8,7 @@ import { PLATFORM_LABEL } from "./platform.mjs";
8
8
  import { PeerEndpoint, findClaudeSession, listClaudeSessions, readTranscript } from "./peer-protocol.mjs";
9
9
  import { runTurn } from "./turn.mjs";
10
10
 
11
- const VERSION = "1.11.2";
11
+ const VERSION = "1.11.3";
12
12
  const FORWARD_MIN_INTERVAL_MS = 5000;
13
13
  const FORWARD_MAX_PER_SESSION = 50;
14
14
 
package/src/index.mjs CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  import { runTurn } from "./turn.mjs";
22
22
  import { BridgeSecurityPolicy } from "./security-policy.mjs";
23
23
 
24
- const VERSION = "1.11.2";
24
+ const VERSION = "1.11.3";
25
25
  const log = (msg) => process.stderr.write(`[codex-mcp-bridge] ${msg}\n`);
26
26
 
27
27
  /**
@@ -5,9 +5,24 @@ import net from "node:net";
5
5
  import os from "node:os";
6
6
  import path from "node:path";
7
7
 
8
- import { homeDir } from "./platform.mjs";
8
+ import { homeDir, IS_WINDOWS } from "./platform.mjs";
9
9
 
10
10
  const SOCKET_DIR = "/tmp/cc-socks";
11
+
12
+ /**
13
+ * Windows has no /tmp, and path.join rewrites the unix default to "\tmp\cc-socks"
14
+ * on the system drive, where listen() fails with EACCES. The endpoint then never
15
+ * comes up, so Claude has no address to answer on and the bridge is silently
16
+ * one-way: messages reach Claude, replies never come back.
17
+ *
18
+ * Claude Code advertises a named pipe on Windows for exactly this reason, so the
19
+ * peer uses the same transport there. net.connect({ path }) and server.listen()
20
+ * accept a pipe name unchanged, so only creation differs - a pipe has no
21
+ * directory to create, no mode to chmod and no file to unlink beforehand.
22
+ */
23
+ function peerSocketPath(pid) {
24
+ return IS_WINDOWS ? `\\\\.\\pipe\\LOCAL\\cc-peer-${pid}` : path.join(SOCKET_DIR, `${pid}.sock`);
25
+ }
11
26
  const PEER_PROTOCOL_VERSION = 1;
12
27
  const CLAUDE_VERSION_HINT = "2.1.229";
13
28
  const PS_BIN = "/bin/ps";
@@ -171,7 +186,7 @@ export class PeerEndpoint {
171
186
  this.cwd = cwd;
172
187
  this.log = log;
173
188
  this.pid = process.pid;
174
- this.socketPath = path.join(SOCKET_DIR, `${this.pid}.sock`);
189
+ this.socketPath = peerSocketPath(this.pid);
175
190
  this.registryPath = path.join(sessionsDir(), `${this.pid}.json`);
176
191
  this.keyPath = null;
177
192
  this.server = null;
@@ -219,16 +234,16 @@ export class PeerEndpoint {
219
234
  const keyHash = crypto.createHash("sha256").update(`${peerToken}${procStart}`).digest("hex");
220
235
  this.keyPath = path.join(sessionsDir(), `${this.pid}.${keyHash}.key`);
221
236
 
222
- fs.mkdirSync(SOCKET_DIR, { recursive: true });
237
+ if (!IS_WINDOWS) fs.mkdirSync(SOCKET_DIR, { recursive: true });
223
238
  fs.mkdirSync(sessionsDir(), { recursive: true });
224
- if (fs.existsSync(this.socketPath)) fs.rmSync(this.socketPath, { force: true });
239
+ if (!IS_WINDOWS && fs.existsSync(this.socketPath)) fs.rmSync(this.socketPath, { force: true });
225
240
 
226
241
  await new Promise((resolve, reject) => {
227
242
  this.server = net.createServer((socket) => this.#handleConnection(socket));
228
243
  this.server.on("error", reject);
229
244
  this.server.listen(this.socketPath, resolve);
230
245
  });
231
- fs.chmodSync(this.socketPath, 0o600);
246
+ if (!IS_WINDOWS) fs.chmodSync(this.socketPath, 0o600);
232
247
 
233
248
  this.registry = {
234
249
  pid: this.pid,