BigPizzaV3/CodexPlusPlus · error · Error

收到未加密数据包

Error message

收到未加密数据包

What it means

Raised in mobile_relay_page when a WebSocket packet arrives without the expected AES-GCM encrypted envelope: plaintext or malformed data was received, typically from a key/protocol mismatch between browser and relay or a non-relay client sending frames.

Source

Thrown at apps/codex-plus-mobile-relay/src/main.rs:810

  if (!crypto?.subtle) throw new Error("当前页面不是安全上下文,WebCrypto 不可用");
  const raw = new TextEncoder().encode($("key").value);
  const digest = await crypto.subtle.digest("SHA-256", raw);
  return crypto.subtle.importKey("raw", digest, "AES-GCM", false, ["encrypt", "decrypt"]);
}
async function encrypt(payload) {
  if (!crypto?.subtle) {
    setStatus("当前浏览器禁用 WebCrypto,已使用兼容模式", true);
    return { type: "plaintext", payload };
  }
  const key = await cryptoKey();
  const nonce = crypto.getRandomValues(new Uint8Array(12));
  const plain = new TextEncoder().encode(JSON.stringify(payload));
  const encrypted = await crypto.subtle.encrypt({ name: "AES-GCM", iv: nonce }, key, plain);
  return { type: "encrypted", nonce: b64url(nonce), payload: b64url(encrypted) };
}
async function decrypt(envelope) {
  if (envelope?.type === "plaintext") return envelope.payload;
  if (!envelope || envelope.type !== "encrypted") throw new Error("收到未加密数据包");
  const key = await cryptoKey();
  const nonce = b64urlDecode(envelope.nonce);
  const data = b64urlDecode(envelope.payload);
  const plain = await crypto.subtle.decrypt({ name: "AES-GCM", iv: nonce }, key, data);
  return JSON.parse(new TextDecoder().decode(plain));
}
async function connect() {
  const room = encodeURIComponent($("room").value.trim());
  if (!room || !$("key").value) { setStatus("需要房间 ID 和 Key", true); return; }
  const scheme = location.protocol === "https:" ? "wss" : "ws";
  if (socket) try { socket.close(); } catch {}
  socket = new WebSocket(`${scheme}://${location.host}/client?room=${room}&token=${room}`);
  socket.onopen = async () => { setStatus("已连接 relay,正在读取会话..."); try { await loadSessions(); } catch (e) { setStatus(e.message, true); } };
  socket.onclose = () => { appServerConnected = false; setStatus("已断开"); };
  socket.onerror = () => setStatus("连接错误", true);
  socket.onmessage = async (event) => {
    try {
      const message = JSON.parse(event.data);

View on GitHub (pinned to f2074595a2)

Solutions

  1. Confirm both ends use the same access key so encryption modes match
  2. Reload the page to renegotiate with the current relay protocol
  3. Check no proxy is rewriting WebSocket frames
Defensive patterns

Strategy: try-catch

When it happens

Trigger: Thrown at apps/codex-plus-mobile-relay/src/main.rs:810 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of BigPizzaV3/CodexPlusPlus@f2074595a2 (2026-08-23). Data as JSON: /api/errors/506544f3ccea42d6. Report an issue: GitHub.