Skip to content

Codex exact tool allowlist: expose native enforcement before accepting launches #623

Open

Description

@lukemaj

What: Native-boundary investigation found that Codex 0.162.1 cannot expose its existing exact-tool policy to Chromeria's app-server adapter.
Why: The policy is an internal Rust startup value, absent from the public protocol/config, and shell disabling still permits native file writes.
So what: Codex needs to expose that existing policy through app-server before the minimal Chromeria mapping can make Sol work; retain the current guard and unchanged allowlists.

Outcome

Enable Codex as a working option for t3_thread_launch with tools.allow, preserving exact restrictions and unrestricted defaults. This supports restricted Drafters in Chromeria's current Objective. Consumer task: lukemaj/italian-wedding#131. Prior contract and implementation: #552 and #559.

Acceptance criteria

  • Listed native/MCP tools work and every unlisted tool, including shell and files, is unavailable at the native boundary.
  • The identical allowlist applies across subsequent turns, resume, and restart; omitted tools retains current unrestricted behavior.
  • Keep existing fail-closed rejection unless enforcement is proven. No prompt-only policy or silent fallback.
  • If Codex cannot expose exact enforcement, record installed CLI version, help, config, generated protocol, source, and synthetic native-boundary evidence, then identify the smallest enforceable option.

Non-goals

Browser subscriptions, generic orchestration redesign, new harnesses, changed allowlists, real venue calls or sends, production state, credential/session changes, version bumps, merge, install or restart.

Blockers

Native prerequisite: expose existing ToolPolicy.allowed_tools to external app-server thread start/resume, with exact execution coverage and durable reapplication. The installed CLI is codex-cli 0.162.1; Chromeria alone cannot populate Rust extension data through its current protocol. Source, CLI, config and synthetic execution evidence. Independent T3 source challenge completed and confirmed the gap, including incomplete hook coverage; no implementation PR or live installation candidate exists.

Required proof

Focused adapter/policy tests if changed, synthetic native-boundary proof, and one isolated live test-thread proof only if no real venue or private state can be reached. Any implementation PR needs independent exact-head T3 review and fork-check before push. No repository-wide checks.

Upstream discovery

On 2026-10-26, searched pingdotgg/t3code open PRs and Issues for codex tool allowlist, open PRs for enabled_tools and tool restrictions; no matching implementation found. tool restrictions returned unrelated PRs #22442, #22808, #21158. Inspected current upstream main 1316d48b0c68151afd8b47eb0c11a114cf0b4daa using git grep for enabled_tools|tool allowlist|allowedtools|toolpolicy in Codex adapter/driver/app-server package, without a match. #552 deliberately left unsupported harnesses rejected; it proves Claude native enforcement, not Codex.

Elon record

Requirements and who asked: Lukasz's implementation brief for italian-wedding#131 requires Sol remain possible while live venues stay Claude; exact listed tools, unchanged defaults, durable restrictions, and native proof are mandatory.
Deleted: Removing the guard, weakening or changing allowlists, instruction-only restrictions, a new orchestration system, browser-subscription scope, installation, and version changes.
Bottleneck: Whether the installed Codex app-server exposes its internal native exact-tool policy through a supported external interface.
Checked myself: Read Chromeria instructions/direction and #552 in full; inspected the existing policy and Codex start/resume mapping; ran CLI help/version and experimental protocol generation; inspected OpenAI's tagged rust-v0.162.1 source at 092d3acd6bec3e3a14bdc7e7a2810ab628ab759d and official app-server/config docs.

Ownership

Exclusive branch fix/codex-exact-tool-allowlist, worktree /home/luke/.t3/worktrees/chromeria/fix-codex-exact-tools, base/head 4943d14ba305c0471df3ceca50a883c32ea98170. The canonical checkout remains read-only and its user-owned scripts/__pycache__/ is untouched. This agent owns the investigation and any in-scope implementation.

Activity

  1. lukemaj commented on Oct 26, 2026

    @lukemaj
    ContributorAuthor

    What: Installed Codex 0.162.1 cannot currently receive its existing internal exact-tool policy through the public app-server interface used by Chromeria.
    Why: The actual native ceiling is Rust ToolPolicy in thread startup extension data; the external protocol/config never populates it, and disabling shell does not disable file writes.
    So what: Keep Chromeria's fail-closed guard and unchanged allowlists; the smallest prerequisite is exposing that existing Codex policy through app-server start/resume before mapping it in Chromeria.

    Decisive source evidence

    Installed codex --version: codex-cli 0.162.1. Official release tag rust-v0.162.1, commit 092d3acd6bec3e3a14bdc7e7a2810ab628ab759d, inspected in /tmp/chromeria-codex-exact-source-01621.

    • Existing native ToolPolicy: exact namespace/name allowlist, captured at startup, must be supplied again at resume. This is a usable internal enforcement primitive, not a public app-server input.
    • App-server thread/start: creates ExtensionDataInit, inserts selected capability roots, and passes it to StartThreadOptions; does not insert ToolPolicy.
    • Session policy capture: reads ToolPolicy from extension data or defaults to ordinary unrestricted tool selection (special internal Guardian reviewer behavior is not an external arbitrary allowlist).
    • ToolsToml supports web search, request-user-input and update-plan controls, not a general native tool allowlist.
    • Native built-ins: apply_patch registration depends on available environment/model capability, not features.shell_tool; resource, clock, generated Code Mode and other tools have separate selection rules.
    • Existing internal boundary tests demonstrate both advertising and execution control when Rust callers provide ToolPolicy. Those tests are evidence of the correct owner, not proof of an external interface.

    CLI, protocol, docs, environment checks

    • Read codex --help, codex app-server --help and generator help. CLI has feature/config overrides and sandbox/approval controls, with no native exact allowlist option.
    • Ran codex app-server generate-ts --experimental --out /tmp/chromeria-codex-exact-protocol-01621; inspected complete v2/ThreadStartParams.ts, ThreadResumeParams.ts, TurnStartParams.ts, ToolsV2.ts, and config definitions. Start/resume have arbitrary config and additive dynamic tools, but no tool ceiling or extension-data policy field. Turn parameters have no exact tool list. Public ToolsV2 exposes web search only.
    • Read official app-server docs, configuration reference and bundled codex-rs/app-server/README.md. MCP enabled_tools filters MCP server tools only; dynamic tools add tools rather than replace the native registry. Sandbox and approvals are not exact tool selection.
    • Searched source for CODEX_.*(TOOL|POLICY|CONFIG) and environment-based tool policy entry points across core/app-server/config. Environment overrides concern user/managed config location, not a serialized native ToolPolicy. No supported external environment allowlist interface found.
    • Isolated strict-config attempts confirmed unsupported keys rather than silently accepting invented controls:
    codex app-server --strict-config -c 'tools.allowed_tools=[]'
    Error: unknown configuration field `tools.allowed_tools` in -c/--config override
    
    codex app-server --strict-config -c 'tool_policy.allowed_tools=[]'
    Error: unknown configuration field `tool_policy` in -c/--config override
    

    Both exited 1; each used an isolated CODEX_HOME, sanitized environment and stdin /dev/null. These are negative probes, not proposed configuration.

    Executed synthetic native-boundary proof

    Command: node /tmp/chromeria-codex-native-boundary.mjs.

    Final probe uses installed real app-server, an ephemeral native thread, isolated CODEX_HOME, blank /tmp workspace, sanitized child environment, gpt-6.1-sol model identity and a local loopback mock Responses endpoint requiring no authentication. No real inference, external MCP, real venue state, sends, copied user config, credential/session changes, live Chromeria server or ~/.t3 writes. Earlier iterations only exercised synthetic patch output and refined evidence collection; final probe also verifies disabled shell.

    Real known config controls: features.shell_tool=false, features.view_image=false, features.code_mode=false, tools.update_plan.enabled=false, tools.experimental_request_user_input.enabled=false, web search disabled. Native full-access/default behavior matches the allowlist contract's required runtime mode. A local synthetic response directly attempts shell and patch calls; no prompt obedience is involved.

    Final run evidence: /tmp/chromeria-623-native-JQRQ4e/evidence.json; native thread 01a17795-84f5-7d92-b259-62d95a251285; two local model HTTP requests; completed turn; exit 0.

    exec_command output: unsupported call: exec_command
    shell-marker.txt: absent
    apply_patch output: Success. Updated the following files: A synthetic-marker.txt
    synthetic-marker.txt: native apply_patch remains executable
    

    This proves that documented shell disabling does not impose the required native file/tool ceiling. It does not prove every imaginable configuration impossible, MCP allowlist usability, real Sol inference, or restart persistence. The source/protocol/config evidence establishes the missing policy input. The full local request contains harness instructions, so only this sanitized outcome is published.

    Smallest enforceable path and limits

    The requested outcome is Sol executing exactly the caller's existing list. Expose the already-existing native ToolPolicy.allowed_tools as an app-server startup/resume input in Codex, preserving omission as unrestricted and explicit empty as no tools; then map Chromeria's stored ThreadTools at its existing Codex adapter boundary. That native prerequisite is outside this repository's implementation scope and installed binary. It must be proven at dispatch, including Code Mode, hosted/native/MCP tools and resume/restart, before Chromeria's guard can accept Codex.

    Claude's existing exact enforcement remains usable for live venues. This is not a substitute for the required Sol option; Sol remains blocked by the native interface. A prompt restriction, shell-only disable, sandbox, additive dynamic tools or removing the guard would not meet the accepted requirement.

    Delivery state

    No tracked changes, commit, push, PR, version bump, merge, install, restart, live venue call or real-inference live proof. Worktree fix-codex-exact-tools remains clean at base/head 4943d14ba305c0471df3ceca50a883c32ea98170; canonical checkout and user untracked scripts are untouched. No repo-wide checks were run, and no fork-check was needed because nothing was pushed. A read-only independent native-interface challenger has been delegated through T3; its verdict will follow here. No code review readiness or approval is claimed.

  2. lukemaj commented on Oct 26, 2026

    @lukemaj
    ContributorAuthor

    What: Independent T3 challenge confirmed the installed Codex native-interface blocker.
    Why: The exact native policy is not exposed through app-server, and tool hooks do not provide a complete enforcement boundary.
    So what: Keep #623 open for the native prerequisite; no Chromeria implementation candidate, PR readiness, installation, or Sol live-proof success is claimed.

    Reviewer: GPT-6.1-Sol through Codex, selected by Prism; independent read-only challenger, not the author. Reviewed unchanged Chromeria base/head 4943d14ba305c0471df3ceca50a883c32ea98170, installed Codex 0.162.1, generated experimental protocol and tagged Codex source 092d3acd6bec3e3a14bdc7e7a2810ab628ab759d. Delegation key: chromeria-623-native-interface-challenger-r1; completed with no pending child runs. This is an independent investigation verdict, not exact-head approval of an implementation.

    Reviewer verdict, unchanged:

    Confirmed the native-interface gap in Codex 0.162.1: CLI help, config, generated protocol and tagged source expose no supported external exact-tool ceiling; ToolPolicy.allowed_tools exists internally but lacks app-server start/resume wiring.

    Hooks cannot substitute: some executors bypass them, and hook errors can continue execution, consistent with the official coverage limits.

    The inspected synthetic evidence proves disabled exec_command was rejected while forced native apply_patch created the marker, but establishes neither live Sol/MCP usability nor restart persistence; retain the guard and unchanged allowlists until that existing native policy is exposed, with no implementation approval implied.

    Parent acceptance: checked the referenced native registry, Code Mode wait hook opt-out, hook runtime and official hook coverage/error documentation directly. The conclusion survives the challenge. Latest worktree status remains clean at 4943d14ba305c0471df3ceca50a883c32ea98170; no tracked changes, commit, push, PR, version bump, real venue access, live installation or restart. Retain the task worktree and source/probe evidence for #623 continuation; upstream native API work needs scope/authority from the parent before any live effects.

  3. lukemaj commented on Oct 26, 2026

    @lukemaj
    ContributorAuthor

    Recheck 2026-10-26 20:45 Warsaw: installed codex-cli 0.162.1; latest stable 0.164.0 (npm, 2026-10-23), pre-release 0.165.0-alpha.1. Release notes for rust-v0.163.0 and rust-v0.164.0 contain no change exposing an exact tool allowlist / ToolPolicy.allowed_tools to app-server thread start/resume (only MCP tool-list, dynamic tool and permission-preset changes). openai/codex PR/issue search for 'allowed_tools' and 'app-server tool allowlist' found nothing relevant. Blocker unchanged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions