fix(tools): stop registering image_gen.imagegen (reserved provider name)#389
Open
andrei-hasna wants to merge 1 commit into
Open
fix(tools): stop registering image_gen.imagegen (reserved provider name)#389andrei-hasna wants to merge 1 commit into
andrei-hasna wants to merge 1 commit into
Conversation
…namespace The standalone image tool once shipped under the Responses-API-reserved `image_gen` namespace (wire name `image_gen.imagegen`), which the model rejects with a 400 that fails the whole turn. Commit 5cc22bc renamed the tool to the non-reserved `images` namespace, but left the invariant unguarded: nothing prevents a first-party / extension / code-mode tool from regressing back under `image_gen` (or another reserved built-in namespace), and the only protection was a single unit-test assertion on that one tool. Add a durable, centralized guard: - codex-tools: new `reserved_namespaces` module — single source of truth for `RESERVED_RESPONSES_NAMESPACES`, plus `is_reserved_responses_namespace` and `is_forbidden_first_party_namespace`. `web` is allowlisted via `FIRST_PARTY_ALLOWED_RESERVED_NAMESPACES` (standalone web search advertises the built-in `web.run` schema on purpose). - Dedupe the two existing copies of the reserved list (app-server `validate_dynamic_tools`, core `validate_multi_agent_v2_tool_namespace`) onto the shared constant so they can't drift. - core spec_plan: `namespace_spec_is_safe_for_wire` runs on the assembled model-visible tool list. A first-party namespace tool under a reserved, non-allowlisted namespace fails loudly (debug_assert) in debug/CI and is dropped with a warning in release, so a mis-namespaced tool degrades gracefully instead of the API rejecting the entire turn. Tests: assembled Responses-wire turn exposes images.imagegen and never image_gen.imagegen; guard allows images/web and fails loud on image_gen; reserved_namespaces unit tests.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a durable, centralized guard so no first-party / extension / code-mode
tool can ever be assembled under the Responses-API-reserved
image_gennamespace (wire name
image_gen.imagegen), which the model rejects with a 400that fails the entire turn:
Investigation — what
git show 5cc22bc71did, and whereimage_gen.imagegenstill comes from5cc22bc71 fix(image-gen): move standalone imagegen off reserved image_gen namespacerenamed the standalone image tool's namespace from the reserved
image_gentothe non-reserved
imagesin two producer sites:codex-rs/ext/image-generation/src/lib.rs—IMAGE_GEN_NAMESPACE: "image_gen" -> "images"codex-rs/core/src/tools/spec_plan.rs—IMAGE_GEN_NAMESPACE: "image_gen" -> "images"On current
main(0.1.77) this is NOT reverted and there is NO secondproducer path. Verified:
"images"onorigin/main."image_gen"string literals incodex-rsare the twoRESERVED-name allowlists (
app-server .../thread_processor.rs,core/src/config/mod.rs) plus the ext regression-test assertion — none areproducers. The code-mode nested name is derived from the same
IMAGE_GEN_NAMESPACEconstant, so it isimages__imagegen, notimage_gen__imagegen.~/.codewith/sessions/**contains a tool specnamed
image_gen; theimage_gen.imagegenstrings there are agent notes.The live 400 is an old-binary deployment gap, not a
mainregression. Theaffected iapp-factory session runs codewith 0.1.67, the release immediately
before the fix.
git show rust-v0.1.67:.../ext/image-generation/src/lib.rsand
.../spec_plan.rsboth still haveIMAGE_GEN_NAMESPACE = "image_gen";rust-v0.1.68+ have"images". So the immediate operational fix is to roll0.1.68+ (ride 0.1.78) onto that box.
Why this PR anyway (the missing guard)
5cc22bc71fixed the value but left the invariant unguarded: nothingstructurally prevents a first-party / extension / code-mode / MCP tool from
regressing back under a reserved namespace, and the only protection was a
single unit-test assertion on that one tool. The dynamic-tool validator
(
validate_dynamic_tools) only covers user-supplied tools, so thefirst-party assembly path — the exact path that produced the original
image_gen.imagegen— was never guarded.Fix
codex-tools: newreserved_namespacesmodule — single source of truthfor
RESERVED_RESPONSES_NAMESPACES, plusis_reserved_responses_namespaceand
is_forbidden_first_party_namespace.webis allowlisted viaFIRST_PARTY_ALLOWED_RESERVED_NAMESPACESbecause standalone web search(
web.run) deliberately advertises the built-in schema; every other reservednamespace (notably
image_gen) is forbidden for first-party tools.validate_dynamic_tools, corevalidate_multi_agent_v2_tool_namespace) ontothe shared constant so they can't drift.
core/src/tools/spec_plan.rs:namespace_spec_is_safe_for_wireruns onthe assembled model-visible tool list in
build_model_visible_specs_and_registry— the single chokepoint wherefirst-party, extension, code-mode, and MCP namespace tools converge. A tool
under a reserved, non-allowlisted namespace fails loudly (
debug_assert)in debug/CI and is dropped with a warning in release, so a mis-namespaced
tool degrades gracefully (one tool missing) instead of the API rejecting the
whole turn.
Tests (added)
standalone_imagegen_never_uses_reserved_image_gen_namespace_on_responses_wire— assembled Responses-wire turn exposes
images.imagegenand neverimage_gen.imagegen, and no assembled namespace tool carries a forbiddenreserved name.
namespace_guard_fails_loud_on_reserved_image_gen_namespace(#[should_panic])and
namespace_guard_allows_non_reserved_and_allowlisted_namespaces.reserved_namespacesunit tests (image_gen reserved+forbidden; webreserved+allowed; list sorted/unique; allowlist ⊆ reserved).
Blacksmith gate (16 vCPU warm box)
just test/nextestcodex-core(+codex-tools): my 3 new tests pass.75 failures are pre-existing sandbox/MCP/approval/shell-snapshot
environment tests — an
origin/mainbaseline on the same box produced anidentical 75-failure set (0 regressions, 0 fixed).
cargo fmt --all -- --config imports_granularity=Item --check: clean.cargo clippy --tests --all-targets -p codex-tools -p codex-core -p codex-app-server:7 warnings, all in pre-existing files (
cli/Cargo.toml,code-mode/src/runtime/mod.rs,core/src/unified_exec/process_manager_tests.rs,proc-macro-error2dep) — none in changed files.*.mdchanged → prettier N/A.Regression context: #5cc22bc71. Do not merge/tag — rides 0.1.78.