App Server schema/runtime reject documented restricted read access on turn/start

Open 💬 0 comments Opened Aug 15, 2026 by alphapinggabriel

What issue are you seeing?

The current Codex App Server documentation says that sandboxPolicy supports explicit restricted read access:

{
  "type": "readOnly",
  "access": {
    "type": "restricted",
    "includePlatformDefaults": true,
    "readableRoots": ["/canonical/review/root"]
  }
}

The same page documents sandboxPolicy as a per-turn override on turn/start, and says command/exec accepts the same shape.

However, generated production schemas from the current official npm distributions do not expose that stable binding:

  • @openai/codex@0.147.0 (latest)
  • @openai/codex@0.148.0-alpha.19 (alpha)

In the generated production types, the readOnly sandbox variant does not expose the documented restricted access object on the stable per-turn surface. The alpha runtime also rejects the documented shape with:

Invalid request: readOnly.access is no longer supported; use permissionProfile for restricted reads

But the generated bindings do not expose a stable permissionProfile equivalent on production TurnStartParams. The available permission-profile surfaces are beta/experimental and therefore cannot replace a documented stable per-turn security boundary.

This creates a three-way contradiction between the documentation, generated production schemas, and runtime validation behavior.

Official documentation: https://learn.chatgpt.com/docs/app-server

What steps can reproduce the bug?

  1. Install an exact official runtime:

``sh
npm install @openai/codex@0.147.0
``

  1. Generate the App Server TypeScript and JSON schemas with that exact runtime.
  2. Inspect the generated SandboxPolicy and TurnStartParams.
  3. Compare them with the documented readOnly.access.type = "restricted" / readableRoots shape.
  4. Initialize App Server without experimental API capability.
  5. Start a thread.
  6. Attempt a turn/start or sandboxed command/exec using the documented restricted-root shape.
  7. Observe that the generated stable contract cannot express it; the alpha candidate additionally rejects readOnly.access and points to a permission-profile mechanism not exposed as a stable per-turn binding.

The current registry tags at the time of this report are:

latest = 0.147.0
alpha  = 0.148.0-alpha.19

What is the expected behavior?

One stable contract should exist across documentation, generated schemas, and runtime behavior.

Either:

  1. the documented restricted readOnly.access shape is accepted and generated for stable turn/start; or
  2. a supported equivalent is documented and generated on the stable per-turn API, with exact restricted readable roots and no broader-access fallback.

If permissionProfile is the replacement, custom App Server clients need a documented, generated, stable way to bind the selected restricted profile to every turn/start.

Additional information

This matters for security-critical custom App Server clients that must make a source worktree readable but not writable while restricting reads to explicitly authorized canonical roots. Without a stable per-turn binding, a client must either fail closed or weaken its security model.

A detached review/start call also does not document an exact restricted-root sandbox parameter, so it cannot safely substitute for an explicit policy-bound turn/start.

No private credentials, account identifiers, thread IDs, or local repository contents are included in this report.

View original on GitHub ↗