拓冰建站拓冰建站
首页 / 资讯中心 / 正文

opencodex 独立 Images 代理修复实录:Codex image_gen 404 根因、7 项安全阻断项闭环与审计门禁

【免费下载链接】opencodexUniversal provider proxy for OpenAI Codex Claude Code — use any LLM (Claude, Gemini, Grok, DeepSeek, Ollama…) with Codex CLI, App, SDK, and Claude Code项目地址https://gitcode.com/gh_mirrors/ope/opencodex点击查看免费下载本篇文章基于 opencodex 仓库devlog/_fin/260710_codex_image_proxy/目录下的一套完整设计评审记录核心围绕审计合成文档003_audit_synthesis.md展开它记录了 Codex 独立图片生成工具image_gen.imagegen在 opencodex 代理下命中404 Unknown endpoint的根因定位、第一轮独立审计提出的 7 个实现阻断项、逐项修复方案以及经过两轮复核最终放行GO的完整门禁闭环。读完本文你将掌握为什么 Codex 会发出第二次 Images API 请求、opencodex 如何在/v1/images/generations与/v1/images/edits上安全地中继付费图片请求、有界流式收集器与单次上游尝试等关键不变量如何落地以及一套先 RED 测试、再评审门禁、后实现验证的可复用工程方法论。背景与根因Codex 独立 image_gen 为什么会命中 404触发与基线复现触发路径非常具体Codex 的image_gen.imagegen工具调用通过 opencodex 代理发出POST /v1/images/generations随即收到POST http://127.0.0.1:10100/v1/images/generations HTTP 404 {error:{message:Unknown endpoint: POST /v1/images/generations,type:not_found,code:not_found}}基线事实记录于 000_plan.md代理源码此前只为/v1/responses和/v1/responses/compact提供处理逻辑其余所有/v1/*路径统一落入 JSON 404 守卫历史行号src/server/index.ts:292-350当前路由表构建于 src/server/index/serve-options.ts。既有回归测试甚至明确把/v1/images/generations列为必须返回 404 的路径历史tests/server-auth.test.ts:1020-1035。也就是说这是源码有意 404而非运行时代理版本陈旧。审计排除了仅需更新运行版本的假设详见下文 H1。七步因果链001_contract_research.md 给出了经过源码求证codex-rs 仓库的完整因果链Codex 不暴露 Responses 托管版image_generation工具而是声明本地命名空间函数image_gen.imagegen在模型调用它之后Codex 内部发起第二次 Images API 请求codex-rs/ext/image-generation/src/tool.rs:110-129。生成与编辑的分发逻辑位于同一文件tool.rs:132-164无引用图片 → 生成请求默认gpt-image-2、background:auto、quality:auto、size:auto带引用图片 → 编辑请求JSON 体携带images[].image_url。客户端以相对路径发出images/generations或images/editscodex-rs/codex-api/src/endpoint/images.rs:33-70。相对路径拼接到当前 provider base 之后codex-rs/codex-api/src/provider.rs:52-85。Codex 期望返回ImagesResponse其data[]条目必须包含必填的b64_jsoncodex-rs/codex-api/src/images.rs:55-70。opencodex 通过 Design B 注入openai_base_url http://host:port/v1及等价 provider 表当前实现见 src/codex/inject.ts。于是相对调用变成/v1/images/generations或/v1/images/edits——而代理在通用守卫之前不存在这两条路由最终产生观察到的 404。竞争假设的裁定设计文档用可证伪条件逐一排除了其他解释H1 — 运行中的守护进程只是旧版本若成立仓库 HEAD 应已包含 Images handler。但仓库 v2.7.4 仍无 handler且既有测试有意期待该路径 404故驳回。H2 — Codex 期望托管 Responsesimage_generation工具若成立Codex Responses 测试应通告托管工具而非本地命名空间。但responses_lite_uses_standalone_web_search_and_image_generation、non_lite_uses_standalone_image_generation_by_default断言了本地命名空间且无托管工具codex-rs/core/tests/suite/responses_lite.rs:204-245,382-418故驳回。H3 — 缺少独立 Images 路由是根因ImagesClient只追加images/generations或images/edits而代理两者均未匹配并发出 404假设成立。ima2-gen 对照不能简单翻译成托管工具流程ima2-gen是刻意不同的图片路径它向/v1/responses发送托管{type:image_generation}工具并强制该工具从 Responses SSE/JSON 中解析image_generation_call.result其直接/v1/images/generations路由属于另一条 provider 管线而非 GPT OAuth。因此 opencodex不能把 Codex 独立调用翻译成 ima2-gen 的托管工具工作流——Codex 自己拥有本地工具调用期望的是普通 Images 响应{created, data:[{b64_json}]}。修复边界目标、非目标与验收标准000_plan.md 将本次修复归类为 C4新数据面 API 契约 OAuth 凭据转发并明确目标让 Codex 独立图片生成与编辑调用以与无代理时相同的已认证上游契约穿越 opencodex。非目标不修改codex-rs、不修改ima2-gen、不用 Responses 托管image_generation工具替换独立工具、不为非 OpenAI provider 增加图片生成、不重新设计账户路由、不发布或发布包。12 条验收标准全部继承逐条可验证POST /v1/images/generations到达forward-provider-base/images/generations保留入站 JSON 载荷返回含data[].b64_json原样的ImagesResponse。POST /v1/images/edits到达forward-provider-base/images/editsCodex JSONimages[].image_url体原样保留兼容调用方若提供 multipart内容类型不被改写。两条路由在产生上游工作前先执行既有 drain、本地数据面 API 鉴权、origin 门禁。线程亲和池凭据替换入站主账户凭据与/v1/responses完全一致授权与账户 ID 永不写入日志或返回。Provider 选择确定且凭据安全仅启用openai-responsesforward按defaultProvider、openai、chatgpt、稳定配置序API-key 与 OAuth provider 永不入选。仅既有转发头白名单 请求content-type Codex providerversion头穿越边界provider 静态头先应用、运行时凭据后应用运行时鉴权胜出所有非 identity 请求content-encoding在产生上游工作前返回 415。流式收集器在保留每个 chunk 前先计数缓冲不超过既有 256 MiB 数据面上限数字声明长度仅是早期拒绝优化畸形/缺失声明由实际流决定超限返回 413 且零上游尝试。每个付费 Images POST 恰好一次上游尝试包括连接重置失败客户端在响应头之前取消 → 中止上游响应头之后取消 → 取消中继的上游响应体。池账户 429/5xx/连接失败更新既有上游健康状态主账户请求永不改变池健康。上游状态、响应体、安全头被中继陈旧的压缩/分帧与 cookie 由既有清洗器剥离。/v1/alpha/search、/v1/memories/trace_summarize及其他未知/v1/*路径仍返回 JSON 404。codex-rs、ima2-gen、web-search、vision、Responses 变换、provider 目录均无任何源码或行为改动。验证命令来自计划文档bun test tests/images-proxy.test.ts bun test tests/server-auth.test.ts tests/codex-auth-context.test.ts tests/upstream-retry.test.ts tests/passthrough-headers.test.ts bun run typecheck bun run privacy:scan bun test ./tests/ git diff --check威胁模型资产、入口与信任边界002_threat_model.md 把两条路由置于完整威胁模型之下资产ChatGPT bearer token 与ChatGPT-Account-ID线程到账户的亲和性与池账户健康状态用户提示词与参考图片字节/数据 URL生成图片字节受信 provider base URL 与静态头。入口与信任边界本地客户端请求 →非回环绑定时由OPENCODEX_API_AUTH_TOKEN/配置 key 与 origin 策略保护的数据面边界 → 选择受信 forward provider 与线程亲和凭据 → 有界不透明请求体与白名单头跨越到 ChatGPT 后端 → 清洗后的上游响应返回调用方。关键假设provider 配置是受信本地状态请求数据不得选择任意上游主机当前 Codex 扩展使用 ChatGPT/OpenAI 认证图片载荷可能合法很大既有 256 MiB 数据面上限是可接受的 OOM 天花板提示词/图片为敏感内容不得写入请求日志或错误文本。其风险控制矩阵节选核心项是后续 7 个阻断项的雏形风险控制验证无本地代理鉴权的远程使用处理前调用requireApiAuth(..., data-plane)非回环路由测试token/账户错配解析 Codex auth context池凭据覆盖入站值集成测试断言替换发生且响应无 tokenSSRF上游主机仅来自受信 forward provider 配置测试断言调用方 body/路径无法改上游主机内存耗尽数字content-length仅为早期提示流式读、保留前逐 chunk 计数超 256 MiB 取消并返回 413声明超限与逐 chunk 溢出测试均证明零上游调用压缩体放大/不透明解码歧义所有非 identity 请求content-encoding在读/转发前返回 415gzip/br/未知编码零上游调用重复付费工作恰好一次 fetch无来源证明幂等契约时不用 reset 重试reset 形态失败断言一次上游尝试 安全 502取消后上游工作泄漏fetch 前链接req.signal响应头后用relayWithAbort头前/头后两个取消测试错误掩盖中继上游状态/体仅本地连接失败映射安全 502聚焦 4xx/5xx 集成用例上游 cookie/会话泄漏既有响应清洗器丢弃set-cookie*响应头断言错误 provider/凭据类别确定性选择器只接受启用openai-responsesforwardkey/OAuth 排除禁用、key、多 provider 优先级、无合格项用例跨账户健康污染仅对选中池上下文调用健康记录器主账户失败仅观察池 429/5xx/连接更新健康主账户不更新第一轮独立审计GO-WITH-FIXES 与 7 个实现阻断项003_audit_synthesis.md 记录了第一轮独立计划审计审计方认同根因与路由形态但指出 7 个实现阻断blocking遗漏且全部被采纳。这是整篇合成文档的灵魂——审计结论从方案对推进到实现必须满足的 7 个不变量#阻断项采纳后的契约1路由门禁是注释而非具体代码drain 返回 503 Retry-After随后数据面 API 鉴权再运行 origin 策略每次拒绝都必须证明零上游调用2存在 reset 重试移除。Images POST 可能产生付费非幂等工作被检的 Codex 契约无幂等键reset 形态失败必须恰好一次尝试3使用Request.arrayBuffer() 读后检查替换为流式有界收集器保留每个 chunk之前计数content-length仅作早期提示4对非 identitycontent-encoding无策略一律 415代理不猜测不透明载荷字节是压缩还是未压缩5Provider 选择不确定选择确定且限定于启用openai-responsesforward条目合格defaultProvider、openai、chatgpt、稳定配置序key/OAuth 条目永不接收 ChatGPT 账户凭据6取消与健康契约未分离响应头前链接 abort响应头后中继取消池结果更新健康主账户结果不更新7激活覆盖不足必须覆盖真实 chunked 溢出、畸形长度、编码策略、全部 provider 分支、不可用 auth 上下文、reset/无重试、两个取消阶段、健康隔离、零上游断言阻断项 1把门禁顺序从注释变成具体实现审计要求三类拒绝路径都必须是真实执行的代码而非注释承诺drainisDraining()→ 数据面 API 鉴权 → origin 策略。且每一类拒绝都必须在集成测试中证明上游调用计数为零——防止先打付费 API 再拒绝的隐性浪费。最终路由形态如下当前实现位于 src/server/index/serve-options.tsif (req.method POST (url.pathname /v1/images/generations || url.pathname /v1/images/edits)) { disableResponsesRequestTimeout(req, requestServer); if (isDraining()) { return drainingResponse(req, policy); // 503 Retry-After } const admission resolveApiAuth(req, policy); if (!admission) return withCors(formatErrorResponse(401, authentication_error, opencodex API key required), req, policy); if (!isAllowedRequestOrigin(req, policy)) { return withCors(formatErrorResponse(403, origin_rejected, cross-origin>new Response(Service shutting down, { status: 503, headers: { ...corsHeaders(req, config), Retry-After: 5 }, });激活测试随即要求该精确的头部/CORS 行为。值得注意的工程细节门禁关闭期间没有写任何产品代码——评审循环与实现严格隔离。最终复核GO最终复核对照src/server/index.ts验证了修正后的 drain 构造确认此前的每个阻断项仍保持关闭且未发现新的实现阻断问题给出GO。B 阶段实现得以开始。这套GO-WITH-FIXES7 blockers→ 补充修正 → NO-GO新编译期问题→ 修正 → GO的迭代本身就是审计方法论的核心产出每个评审结论都绑定可验证证据任何阻挡性问题都会让门禁保持关闭。实现落地与门禁证据RED → GREEN实现采用严格的 RED/GREEN写产品代码之前先加入生成路由回归测试并运行——它如预期失败bun test tests/images-proxy.test.ts Expected: 200 Received: 404 0 pass, 1 fail该失败精确复现了原始通用守卫错误而非 mock-only 的单测条件。构建期被激活测试揪出的时序缺陷真实 chunk 溢出测试首先暴露了一个实现顺序缺陷收集器在异步取消传播稳定之前就释放了 reader 锁。修复方案是把锁释放调度到 cancel resolve/reject 之后同时不等待即返回 413一个在溢出 chunk 后仍保持打开的流证明了其底层 cancel 钩子确实触发。这印证了阻断项 7激活覆盖的价值——不真实的测试路径发现不了这类竞态。自动化门禁数据聚焦受影响套件与全仓库门禁011_implementation_and_verification.mdbun test tests/images-proxy.test.ts tests/images-proxy-safety.test.ts \ tests/server-auth.test.ts tests/codex-auth-context.test.ts \ tests/upstream-retry.test.ts tests/passthrough-headers.test.ts 80 pass, 0 fail, 289 expect() calls bun test ./tests/ 1942 pass, 0 fail, 8285 expect() calls across 194 files bun run privacy:scan → passed bun run typecheck → exit 0 git diff --check → exit 0此外一次独立的gpt-5.6-sol中型实现评审返回PASSblocking_issues: none覆盖凭据类别、body 边界、头选择、单次尝试行为、取消/生命周期、健康隔离、文档与测试。手工 HTTP QA对打补丁的 opencodex 服务器与 mock forward provider 用curl -i驱动的真实 HTTP 验证证据根目录.codeclaw/evidence/.../qa/http-images/确认generation 返回 200证明/backend-api/codex/images/generations、auth、account、version全部正确edit 返回 200证明/backend-api/codex/images/edits匿名/错误 key → 401恶意 origin → 403合法 preflight → 204GET/未知子路径 → JSON 404空/畸形 body 中继上游 400 信封错误内容类型中继 415非 identity 编码本地 415真实 chunked 268,435,457 字节请求在 268,435,456 字节256 MiB天花板处返回可解析的 413两个显式相同 POST 产生上游调用号 4 和 5——证实每次调用独立、无隐藏自动重试。部署注意codex-rs与ima2-gen无文件改动未发布任何包任务期间未替换已在 10100 端口提供服务的安装代理中断活跃代理可能切断当前 Codex 会话。补丁源码行为已在真实 HTTP 表面验证激活已安装的旧守护进程是独立的重启/更新操作。当前源码形态审计契约的演进与扩展对照审计时锁定的最小修复当前仓库源码已在此基础上扩展以下均为可从源码确认的事实路径见各文件路由与门禁两条精确 POST 路由注册在 src/server/index/serve-options.ts顺序依然是 drain → 数据面鉴权 → origin 策略 →handleImagessrc/server/index.ts 的回环白名单同样只放行这两个精确路径的 POST。核心中继不变量src/server/images.ts恰好一次上游 fetchredirect: manual防止携带 Codex 凭据的跨源 3xx 把chatgpt-account-id、session_id、x-codex-turn-metadata等非标准头泄漏到重定向目标请求体经readJsonRequestBody 入站上限解析上游响应体经readImageResponseBytes以IMAGES_RESPONSE_MAX_BYTES 100 MiB为界流式读取响应为含 base64 图片的 JSON 文档通常仅数 MB上游超时IMAGES_UPSTREAM_TIMEOUT_MS 300_000图片生成耗时可达数十秒只绑定悬挂的上游而非正常调用客户端取消优先映射 499client_closed_request超时映射 504连接失败映射 502错误文本经sanitizeUpstreamErrorText脱敏且剥离 URL池上下文经recordOutcome更新健康主上下文隔离。配置面OcxImagesConfigsrc/types/config.ts在审计之后引入了可选自定义 API-key provider 与桥接开关{ images: { provider: my-keyed-openai-responses, // 可选显式选择 API-key 自定义 provider timeoutMs: 300000, // 单次图片生成/编辑调用上游超时默认 60000 桥接/300000 中继 bridgeEnabled: false, // xAI Grok Imagine 付费生成总开关默认关闭 bridgeModel: grok-imagine-image-quality, maxRounds: 3, // 图片生成循环上限钳制在 [0, 10] artifactsKeepCount: 200 // artifacts/ 下保留文件上限 } }显式images.provider失败即关闭provider 缺失/禁用/注册表管理/不兼容/无可用 key 均报错永不落到另一条付费上游未显式配置时保留内置 OpenAI 回退ChatGPT forward 或api.openai.comkey 路径见 src/providers/openai-sidecar.ts。从源码结构看后续还叠加了 xAI Imagine 桥bridgeEnabled与 Google AntigravityCCA生成回退以及基于 admission 的 key scope 门禁structure/data-planes/images.md 与tests/server/api-key-scope-images.test.ts——这些是审计闭环放行之后的功能扩展审计锁定的安全不变量单次尝试、有界收集、凭据类别隔离、取消传播、健康隔离、未知子路径 404在扩展路径中均被保留。总结评审驱动的可靠性经验回顾这套修复最有价值的不只是两条路由补上了而是过程本身沉淀的可复用方法用可证伪假设做根因分析H1/H2/H3 每条都给出什么证据能推翻它最终锁定源码级因果链。先锁安全不变量再写实现7 个阻断项全部是可测试的契约而非风格建议且每条都绑定零上游调用这类可观测断言。评审与实现严格分阶段门禁关闭期间不写产品代码每次评审结论都记录证据。RED 测试驱动产品代码之前先让回归测试按真实失败路径红掉。真实激活测试补盲区chunked 溢出测试揪出的 reader 锁释放竞态是 mock-only 测试发现不了的问题。对任何运行 opencodex 代理、并把 Codex 图片生成指向该代理的团队本套文档000_plan.md → 001_contract_research.md → 002_threat_model.md → 003_audit_synthesis.md → 010_wp1_standalone_images_proxy.md → 011_implementation_and_verification.md提供了从根因到验证的完整复现路径当前实现则以 src/server/images.ts 为单一入口持续承载这些契约。赞分享【免费下载链接】opencodexUniversal provider proxy for OpenAI Codex Claude Code — use any LLM (Claude, Gemini, Grok, DeepSeek, Ollama…) with Codex CLI, App, SDK, and Claude Code项目地址https://gitcode.com/gh_mirrors/ope/opencodex点击查看免费下载相关推荐opencodex WebSocket 审计修复全解析15 项外部审计问题的甄别、补丁实现与验证闭环opencodex WebSocket 审计修复全解析15 项外部审计问题的甄别、补丁实现与验证闭环 导读 本文完整还原 opencodex 项目中一次围绕OpenCodex Grok Build 硬化审计实录xAI OAuth/缓存路径的五轮修复闭环OpenCodex Grok Build 硬化审计实录xAI OAuth/缓存路径的五轮修复闭环 导读 本文以 OpenCodex 仓库中 devlog/_fSlang 编译器架构文档的独立评审实录module-map.md 评审报告全景解读与修复闭环Slang 编译器架构文档的独立评审实录module map.md 评审报告全景解读与修复闭环 本文以 Slang 开源仓库中 architecture/mo编译器图形学编程语言创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门