{"record":{"id":"65c8e18be8f0c9af","repo":"BigPizzaV3/CodexPlusPlus","slug":"app-65c8e1","errorCode":null,"errorMessage":"不支持此分享的数据格式。","messagePattern":"不支持此分享的数据格式。","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"services/share-site/app.js","lineNumber":186,"sourceCode":"}\n\nasync function encryptText(value) {\n  const key = await crypto.subtle.generateKey({ name: \"AES-GCM\", length: 256 }, true, [\"encrypt\"]);\n  const iv = crypto.getRandomValues(new Uint8Array(12));\n  const ciphertext = await crypto.subtle.encrypt({ name: \"AES-GCM\", iv }, key, encoder.encode(value));\n  const exportedKey = await crypto.subtle.exportKey(\"raw\", key);\n  return {\n    key: toBase64Url(new Uint8Array(exportedKey)),\n    payload: {\n      v: 1,\n      iv: toBase64Url(iv),\n      ciphertext: toBase64Url(new Uint8Array(ciphertext)),\n    },\n  };\n}\n\nasync function decryptText(payload, keyValue) {\n  if (payload?.v !== 1) throw new Error(\"不支持此分享的数据格式。\");\n  const key = await crypto.subtle.importKey(\n    \"raw\",\n    fromBase64Url(keyValue),\n    { name: \"AES-GCM\" },\n    false,\n    [\"decrypt\"],\n  );\n  const plaintext = await crypto.subtle.decrypt(\n    { name: \"AES-GCM\", iv: fromBase64Url(payload.iv) },\n    key,\n    fromBase64Url(payload.ciphertext),\n  );\n  return decoder.decode(plaintext);\n}\n\nfunction toBase64Url(bytes) {\n  let binary = \"\";\n  for (const byte of bytes) binary += String.fromCharCode(byte);","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6/services/share-site/app.js#L168-L204","documentation":"decryptText() rejects any encrypted payload whose envelope version field v is not exactly 1 before attempting AES-GCM decryption. This is a forward-compatibility guard: the share-site only knows how to decrypt the v=1 envelope {v:1, iv, ciphertext, ...}, and would otherwise produce corrupt or misleading decryption failures on newer formats.","triggerScenarios":"Calling decryptText with data.encrypted that is null/undefined, or an object produced by a newer writer using a different envelope version (v !== 1).","commonSituations":"Server stores shares written by a newer version of the encrypting app than the static share-site JS; the encrypted field was corrupted or replaced; the API returned an error object instead of the expected envelope.","solutions":["Upgrade the share-site (app.js / encryptText writer) so writer and reader agree on the same envelope version.","Log/inspect data.encrypted in the browser console to see the actual v value before assuming corruption.","Pin the encrypting app and share-site to compatible versions during rollout of a format change.","If v is genuinely newer, show a clear 'please update / unsupported share version' notice instead of a generic format error."],"exampleFix":"// before\nif (payload?.v !== 1) throw new Error(\"不支持此分享的数据格式。\");\n// after\nconst SUPPORTED_V = 1;\nif (payload?.v !== SUPPORTED_V) throw new Error(`不支持此分享的数据格式（版本 ${payload?.v ?? \"未知\"}，需要 v${SUPPORTED_V}）。`);","handlingStrategy":"type-guard","validationCode":"const payload = data.encrypted;\nif (!payload || payload.v !== 1 || !(payload.iv && payload.ciphertext)) {\n  viewNotice.textContent = \"此分享使用了不受支持的数据格式，请更新客户端。\";\n  return;\n}","typeGuard":"function isV1Envelope(p) {\n  return !!p && p.v === 1 && typeof p.iv === 'string' && typeof p.ciphertext === 'string';\n}","tryCatchPattern":"try {\n  const plaintext = await decryptText(data.encrypted, keyValue);\n} catch (e) {\n  if (e.message.includes(\"不支持此分享的数据格式\")) {\n    viewNotice.textContent = \"分享格式版本不受支持，请更新页面或联系分享者。\";\n  } else { throw e; }\n}","preventionTips":["Keep the encrypting client and the static share-site deployed in lockstep.","Version the envelope explicitly and negotiate versions in the UI before decrypting.","Log the observed v value server-side to detect version drift early.","Add a smoke test that round-trips encryptText -> decryptText on every release."],"tags":["encryption","schema-validation","versioning","webcrypto"],"backgroundTag":"schema-validation-failed","analyzedSha":"b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6","analyzedAt":"2026-09-19T23:35:21.129Z","contentChangedAt":"2026-09-19T23:35:21.129Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}