Inside the Harness: Turn-Scoped Permissions Are Becoming an Agent-Runtime Primitive
OpenAI Codex now treats permissions as something bound to a single agent turn, not a machine or a user. What turn-scoped permissions are, the threat model they answer, how runtimes implement them, and why the snapshot semantics matter more than the settings UI.
On this page
- What happened
- What "turn-scoped" actually means
- The threat model it answers
- How the implementation actually hangs together
- What to do now
- FAQ
- What are turn-scoped permissions?
- How is this different from just running the agent as a restricted OS user?
- Can a prompt injection change Codex's permissions?
- Are permission profiles stable enough to build on?
- The bottom line
- Sources
There's an issue in the OpenAI Codex repository, filed in mid-July, that tells you more about where agent runtimes are heading than most launch posts do. The reporter noticed that if you change Codex's permission mode while a turn is running, the running turn ignores you. It keeps the permissions it started with, and your new setting only applies to the next turn. Raise access mid-turn and the agent stays blocked. Lower it mid-turn and, worse, the UI says restricted while the agent keeps its original powers for minutes more.
That behaviour is not a bug in the obvious sense. It's the visible edge of a design decision that is quietly becoming standard across agent runtimes: permissions are scoped to the turn, snapshotted when the turn starts, and treated as a property of that unit of work rather than of the user, the machine or the session. This piece is about what that primitive is, the threat model it answers, and how Codex, the reference implementation right now, actually wires it.
Key Takeaways - Turn-scoped permissions means the runtime snapshots an approval policy, sandbox policy and permission profile when a turn begins, and every tool call in that turn executes against the snapshot. - The threat model is not a malicious user. It's a capable agent following hostile instructions (prompt injection) or drifting off-task, running with your credentials on your machine. - Codex implements the boundary as three independent dials: approval policy (does it ask), sandbox mode (what can commands touch), and permission profiles (fine-grained filesystem and network rules), enforced by the OS, not the model. - Enforcement lives below the model: Seatbelt on macOS, bubblewrap plus seccomp on Linux, a dedicated sandbox on Windows. Where a policy can't be enforced, Codex refuses to run the command. - The unresolved frontier is mid-turn mutation: today the snapshot is immutable for the life of the turn, which is safe and occasionally maddening.
What happened
Through late July and early August, the Codex permission surface thickened from a pair of coarse settings into something closer to a policy engine, and the docs caught up with it. The older model was two dials in config.toml: sandbox_mode (read-only, workspace-write, danger-full-access) and approval_policy (untrusted, on-request, never). The newer model adds permission profiles, currently beta: named, composable policies that combine filesystem rules (read, write, deny per path, with deny winning) and network rules (domain allowlists enforced through a local proxy). Three built-ins ship with the runtime: :read-only, :workspace and :danger-full-access, and you extend them rather than starting from scratch.
Alongside the config surface, the interaction model got more turn-native. /permissions switches modes inside a running session. A granular approval policy lets you keep some prompt categories interactive (sandbox escalations, MCP elicitations) while auto-rejecting others, including a distinct request_permissions category, which is the agent itself asking for more access mid-task. And approvals can be routed to an automatic reviewer agent that screens requests for exfiltration, credential probing and destructive actions before a human ever sees them, per OpenAI's approvals and security documentation.
None of this is a single announcement. It's a runtime growing a permission layer the way operating systems grew user accounts: reluctantly, and in response to contact with reality.
OpenAI Codex has evolved from two coarse settings (sandbox mode, approval policy) into named permission profiles combining per-path filesystem rules and proxied network domain rules, with mid-session switching, granular approval categories and an optional auto-reviewing agent, per the official permissions and approvals documentation.
What "turn-scoped" actually means
The cleanest definition I've got: the set of things the agent may do is bound to the lifetime of a single turn, captured when the turn starts, and in principle releasable when it ends. Not bound to the user (who might step away for an hour while the agent works), not to the machine (which hosts many turns of wildly different risk), not even to the session (which might review code in the morning and install dependencies after lunch).
The Codex issue that opened this piece is the proof that the snapshot is real. The running turn "retains a permission or sandbox snapshot created when the turn starts", as the reporter put it, and the fix they propose is machinery to propagate a new approval policy, sandbox policy and permission profile into the active turn, or failing that, an internal pause-and-resume so the turn restarts under fresh permissions without the user re-prompting. Read the acceptance criteria and they're a spec for turn-scoped permissions as a first-class runtime concept: reducing permissions mid-turn must block new violating operations, raising them must unblock the agent, and resumed, delegated and compacted turns must preserve the updated context.
Why snapshot at all? Because the alternative is worse. If permissions are mutable global state, then anything that can influence that state, including content the agent reads, has a lever on what the agent may do next. An immutable-per-turn snapshot means the permission decision is made once, by a human or a policy, at a moment of clear intent, and the agent cannot talk its way past it mid-flight. The turn becomes the smallest unit of trust, which matches how agent work actually decomposes: "review this diff" and "push to main" should never share a permission context, even when they share a session.
Codex binds permissions to a turn-start snapshot: a July 2026 issue documents that changing access modes mid-turn does not affect the running turn, and proposes propagating updated approval policy, sandbox policy and permission profiles into the active turn, with resumed and delegated turns preserving the new context.
The threat model it answers
Worth being precise here, because "agent security" covers a lot of vague worry. The threat model behind turn-scoped permissions has three named actors, and none of them is a hacker in a hoodie.
Prompt injection is the headline threat. The agent reads untrusted content all day: repositories, web pages, issue tickets, tool output. Any of it can carry instructions aimed at the agent. OpenAI's own docs are blunt about the consequences: the default web search mode is cached rather than live specifically to reduce injection exposure, and the guidance warns that enabling network access lets an injected agent fetch and follow untrusted instructions. A turn-scoped, network-off-by-default sandbox caps what a successful injection can reach in that turn.
Drift and over-reach is the quiet one. A capable agent doing legitimate work will still wander: install something, fetch a dependency, "helpfully" clean up a directory. The sandbox answers this without needing the agent to be malicious, which is why the boundary is enforced by the OS (Seatbelt on macOS, bubblewrap plus seccomp on Linux, a native sandbox on Windows) and not by the model's good judgement. Where the platform can't enforce a requested policy, Codex refuses to run the command rather than running it unsandboxed. Fail closed, not fail hopeful.
Credential exposure is the multiplier. The docs' devcontainer guidance spells it out: run Codex with full access inside a container and a malicious project can exfiltrate anything in the container, including Codex credentials. That's why the newer primitives are so specific about secrets: "**/*.env" = "deny" globs that carve credential files out of writable workspaces, .git, .codex and .agents protected as read-only inside writable roots, and a network proxy that blocks local and private destinations by default as a DNS-rebinding defence. This is the same shape as the broader architecture question in agentic AI architecture: the model proposes, the harness disposes, and the harness should hold the secrets.
Codex's documented threat model centres on prompt injection (network off by default, cached web search to reduce exposure to hostile live content), agent drift (OS-enforced sandboxes that refuse commands they cannot enforce), and credential exposure (deny globs for.envfiles, read-only.gitand.codexpaths, local-network blocking), per OpenAI's security documentation.
How the implementation actually hangs together
Three implementation details are worth stealing for your own runtime thinking.
Deny beats write beats read, at equal specificity. Permission profiles let you grant broad access first and carve out exceptions: workspace writable, **/*.env denied, .devcontainer read-only. More specific paths override broader ones, and a denied subpath stays denied inside a writable parent. You can even reopen a narrow subtree inside a broad deny (~/Documents denied, ~/Documents/codex writable). This is the right precedence model because it makes least-privilege additive to write instead of subtractive from memory.
Network access and network filtering are separate switches. network.enabled = true lets commands reach the network; features.network_proxy = true is what actually enforces your domain rules through a local proxy. One without the other gives you unrestricted outbound access with a false sense of governance. Domain rules are allowlist-first, deny wins, and localhost and friends are blocked unless you allow them explicitly, because a sandboxed agent with access to your local daemons is not meaningfully sandboxed.
The old and new systems do not compose. Profiles and the legacy sandbox_mode settings are mutually exclusive; if any loaded config sets sandbox_mode, profiles are ignored. Enterprise admins can force the new model with a managed allowed_permission_profiles allowlist, which also denies omitted built-ins. If you take one operational lesson from the whole design, it's this: two permission systems that "both apply" is how you end up thinking you've denied something you haven't. Pick one, verify it with /permissions and /status, then expand.
For teams running agents beyond the CLI, the pattern generalises. Snapshot a permission context per task, hold credentials in the tool-execution layer rather than the model's context, enforce below the model, and expire everything at task end. Whether you get that from a vendor runtime or your own harness is the build versus buy question, and if you're running it yourself, the self-hosted agent trade-offs apply with knobs on.
Codex permission profiles use deny-over-write-over-read precedence with specificity overrides, separate network enablement from proxied domain enforcement, and refuse to compose with legacy sandbox settings to avoid ambiguity; admins can mandate profiles via managed allowlists, per the permissions documentation.
What to do now
Today: run
/permissionsand/statusin your next Codex session and look at what's actually in effect, not what you think is in effect. If any config layer still setssandbox_mode, you've silently opted out of permission profiles. Decide which system you're on.This week: write one custom profile that extends
:workspace, denies**/*.env, and allows only the API domains you actually call, withnetwork_proxyon. Test it withcodex debug(the sandbox command) before trusting it. If you review third-party code, pin those projects to a:read-only-derived profile in their project config.This month: if you're building an agent runtime or wrapping one, adopt the turn as your permission unit: snapshot at turn start, expire at turn end, hold secrets outside the model's context, and make your enforcement fail closed. Then write down your answer to the open question Codex itself hasn't finished answering: what should happen when permissions change mid-turn? "Nothing until the next turn" is safe, but your users will expect the UI to mean what it says.
FAQ
What are turn-scoped permissions?
A permission model where the runtime captures an approval policy, sandbox boundary and filesystem/network rules when an agent turn begins, and applies that snapshot to every tool call in the turn. Permissions are a property of the unit of work, not of the user, machine or session. In principle they're released when the turn ends, so elevated access never persists by default.
How is this different from just running the agent as a restricted OS user?
OS users are machine-scoped and static: every task the agent runs inherits the same blanket. Turn scoping lets "review this repo" run read-only while "install dependencies and test" runs with workspace writes and a domain allowlist, within the same session, without changing accounts. It also gives you a natural place to expire access, which OS users don't.
Can a prompt injection change Codex's permissions?
Not within a turn, by design: the running turn executes against the snapshot taken at turn start, and mid-turn changes to settings don't propagate to it (the behaviour documented in issue #32612). The residual risks are the next turn, and any surface the profile already allows, which is why network access defaults off and sensitive paths are denied or read-only.
Are permission profiles stable enough to build on?
They're explicitly beta and don't compose with the older sandbox_mode settings, so treat them as the direction of travel rather than a finished API. The older modes are the stable baseline today. For a team rollout, pick one model per client version, verify behaviour with /status, and expect profile fields to keep moving for a while.
The bottom line
Agent permissions are growing up the way Unix permissions did: from "root or nothing" towards fine-grained, least-privilege, auditable boundaries, except the unit isn't a process or a user, it's a turn. Codex is the clearest implementation to study right now, and its roughest edge, the immutable mid-turn snapshot, is also its most instructive: even the reference runtime is still negotiating how dynamic a permission can be before it stops meaning anything. If you build or operate agents, learn the shape of this primitive now. Every serious runtime will have one within a year, and the ones that get the snapshot semantics wrong will learn it in public.
If you're designing the permission layer for your own agents and want a second pair of eyes, that's work I do with client teams. Get in touch.
Sources
OpenAI Developers, "Codex permissions": https://developers.openai.com/codex/permissions (retrieved 2026-08-29)
OpenAI Developers, "Agent approvals and security": https://developers.openai.com/codex/agent-approvals-security (retrieved 2026-08-29)
GitHub, openai/codex issue #32612, "Apply access-control changes to the currently running turn": https://github.com/openai/codex/issues/32612 (filed 2026-07-12, retrieved 2026-08-29)
GitHub, openai/codex issue #23626, "Codex CLI /permissions omits Read-only in WSL2 but shows it in Windows PowerShell": https://github.com/openai/codex/issues/23626 (filed 2026-05-20, retrieved 2026-08-29)
OpenAI Codex repository: https://github.com/openai/codex (retrieved 2026-08-29)
Keep reading
Agent Field Notes
Get the next issue.
Agent harnesses, runtimes, security and governance, explained for the people who have to operate them.
Facing a decision like this?
We run architecture reviews, governance assessments and version-pinned framework evaluations for teams making consequential agent decisions.