App Server schema/runtime reject documented restricted read access on turn/start
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.5k
- PR merge metrics
- PR metrics pending
Description
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?
-
Install an exact official runtime:
npm install @openai/codex@0.147.0 -
Generate the App Server TypeScript and JSON schemas with that exact runtime.
-
Inspect the generated
SandboxPolicyandTurnStartParams. -
Compare them with the documented
readOnly.access.type = "restricted"/readableRootsshape. -
Initialize App Server without experimental API capability.
-
Start a thread.
-
Attempt a
turn/startor sandboxedcommand/execusing the documented restricted-root shape. -
Observe that the generated stable contract cannot express it; the alpha candidate additionally rejects
readOnly.accessand 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:
- the documented restricted
readOnly.accessshape is accepted and generated for stableturn/start; or - 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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by inspecting the generated SandboxPolicy and TurnStartParams bindings for @openai/codex versions 0.147.0 and 0.148.0-alpha.19, then compare them with the documented turn/start and command/exec shapes. Reproduce the documented restricted read request and the alpha runtime rejection. Done means the documentation, generated stable contract, and runtime validation consistently support one secure per-turn policy.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust, typescript
- Domain
- api, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100