Codex security · Windows Windows
Safer Codex on Windows.
Limit what Codex can read, change, and send — then verify the setup and recover from mistakes.
Community project · Not affiliated with OpenAI
- workspace write
- minimal runtime reads
- explicit network policy
- credentials
- filesystem root
- unrestricted network
Approval is not a security boundary.
Faced with a destructive command, most people’s first instinct is: “I’ll write clear instructions and approve everything important myself.” But approval only protects you if you can actually read every command — and on Windows, with its quoting rules, encodings, registry entries, and endless parameters, that is far harder than it sounds.
Commands get longer, approvals repeat dozens of times a day, and sooner or later you skim, misread, or only see the first half. Reviewer agents misjudge too. When approval is the only line of defense, one wrong click hands over full authority.
Read the whole script once before looking at the answer below. There is no malicious line in sight — but it deletes a folder you never meant to touch.
Set-Location "C:\Users\you\projects\webapp"
$ErrorActionPreference = "SilentlyContinue"
if (-not (Test-Path "C:\Users\you\projects\webapp\node_modules")) {
npm ci --no-audit --no-fund --loglevel=error
}
$config = Get-Content "C:\Users\you\projects\webapp\tools\build-config.json" -Raw -ErrorAction SilentlyContinue | ConvertFrom-Json
$base = $config.outputDirectory
npm run build -- --outDir "$base" --minify
Copy-Item -Path "$base\*" -Destination "C:\Users\you\projects\webapp\release\latest" -Recurse -Force -Confirm:$false
Remove-Item -Path "$base\data" -Recurse -Force -Confirm:$false
git add -A; git commit -m "sync build output"; git push origin main A routine build-and-release script.
By the time you reach the final lines, line 7 looks completely innocent: $base takes its value from the config. But the config read failed quietly — $base is $null. Not one line in this script was written to cause the accident.
$config = Get-Content "C:\Users\you\projects\webapp\tools\build-config.json" -Raw -ErrorAction SilentlyContinue | ConvertFrom-Json$base = $config.outputDirectoryRemove-Item -Path "$base\data" -Recurse -Force -Confirm:$false PowerShell resolves paths starting with \ from the root of the current drive — here, C:. The config file is missing, so the read fails quietly and $base is $null: "$base\data" becomes \data, and "$base\*" becomes \*. Copy-Item first copies whatever it can read from C:\* into release\latest; Remove-Item targets C:\data. Whether the deletion actually lands depends on C:\data existing and on your permissions. Danger did not come from a dangerous line — two locally reasonable choices combined into a path you never meant.
Risk one · Agent accidents — no malice required
Completing the task correctly is not the same as completing it safely. Nothing in these commands is evil; the outcome is simply wrong.
git fetch origin main --quiet git reset --hard origin/main git clean -fdx -e ".env.local" -e "node_modules"
An ordinary request: bring the repo back to a clean state of remote main.
It never checks whether the working tree holds your only copy of anything. reset --hard discards tracked changes; clean -fdx wipes even ignored files. The task is correct — the completion is unsafe.
Risk two · More permission than the task needs
These are not reasoning accidents — they are what granted permissions allow: code you cannot audit, and one-time approvals that keep executing later.
powershell.exe -NoProfile -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -EncodedCommand JABFAHIAcgBvAHIAQQBjAHQAaQBvAG4AUAByAGUAZgBlAHIAZQBuAGMAZQA9ACcAUwBpAGwAZQBuAHQAbAB5AEMAbwBuAHQAaQBuAHUAZQAnADsAIABHAGUAdAAtAEMAaABpAGwAZABJAHQAZQBtACAAIgAkAGUAbgB2ADoAVQBTAEUAUgBQAFIATwBGAEkATABFAFwALgBhAHcAcwAiACwAIgAkAGUAbgB2ADoAVQBTAEUAUgBQAFIATwBGAEkATABFAFwALgBzAHMAaAAiACAALQBSAGUAYwB1AHIAcwBlACAALQBGAG8AcgBjAGUAIAAtAEUAcgByAG8AcgBBAGMAdABpAG8AbgAgAFMAaQBsAGUAbgB0AGwAeQBDAG8AbgB0AGkAbgB1AGUAIAB8ACAARgBvAHIARQBhAGMAaAAtAE8AYgBqAGUAYwB0ACAAewAgAEMAbwBwAHkALQBJAHQAZQBtACAAJABfAC4ARgB1AGwAbABOAGEAbQBlACAAIgBDADoAXABVAHMAZQByAHMAXAB5AG8AdQBcAHAAcgBvAGoAZQBjAHQAcwBcAHcAZQBiAGEAcABwAFwALgBzAGMAYQBuAC0AbwB1AHQAcAB1AHQAIgAgAC0ARgBvAHIAYwBlACAAfQA=
$ErrorActionPreference = 'SilentlyContinue'Get-ChildItem "$env:USERPROFILE\.aws", "$env:USERPROFILE\.ssh" -Recurse -Force |ForEach-Object { Copy-Item $_.FullName "C:\Users\you\projects\webapp\.scan-output" -Force } A common workaround for Windows quoting problems — or a way to hide what actually runs.
Prompt injection and malicious repo instructions look exactly like this under Full Access: Hidden, NonInteractive, ExecutionPolicy Bypass, and a payload no one can audit.
New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" -Name "WebAppUpdater" -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File C:\Users\you\AppData\Local\Temp\upd.ps1" -PropertyType String -Force | Out-Null
Register an updater that starts at login.
The Run entry points at a mutable file: upd.ps1. You reviewed version A today; a replaced version B runs at your next login. One approval becomes a standing execution path that outlives this review.
A user running Full Access discovered that their relay service had injected a script into the execution flow, disguised as “environment monitoring”. They only spotted it because the executed code was visible in the chain of thought — SSH keys and API keys were one step away from being bundled out of the machine.
The script looked harmless, so approval was never the question. A workspace boundary is: no matter how well the injected code disguised itself, it could not have read SSH keys or API keys outside the project.
Every new command is another exam that must be passed perfectly, and a single failure hands over full authority. Codex Safe Setup flips this: approval becomes an optional workflow inside the boundary, and the boundary itself becomes the thing that cannot be crossed.
What it limits
What it limits
Three capability boundaries, installed as one least-privilege profile.
Files
Codex shouldn’t own your whole filesystem.
The installed profile extends the workspace, not the machine. Writes stay inside registered workspace roots; everything else starts denied.
Codex’s own protections for .git, .codex, and .agents are preserved. A credential that enters model context or logs is an exposure even without a destructive command.
- Workspace write — Writes allowed only under registered workspace roots.
- Minimal runtime reads — The runtime-defined minimal read set, nothing more.
- Filesystem root — Denied by default, including temp directories.
- Common credentials — Denied even inside the workspace: .env, private keys, npm and cloud credential files.
Network
Command networking is a separate boundary.
Approving commands is not the same as deciding what can leave your machine. Egress is an explicit, independent choice.
A domain table without an active proxy is not an enforced allowlist.
- Off — Default. Commands cannot reach the network.
- Allowlist — Only explicitly named public domains pass through the command proxy.
- Unrestricted — High risk. Direct command egress, installed only after a separate acknowledgement.
Recovery
Safety includes being able to undo.
Containment prevents mistakes; recovery survives them. Every managed file is backed up, and the optional checkpoint bridge snapshots work without touching your branch.
Checkpoints do not capture ignored or refused files. Restore with a separate worktree: git worktree add <new-empty-directory> <commit>.
- Backup before write — Every file the installer touches is backed up first, with an exact rollback command.
- Git checkpoints — Optional hidden refs under refs/codex-safe/checkpoints/*. Branch, real index, and working tree stay untouched.
- Sensitive untracked files — Refused from checkpoints: .env, private keys, .npmrc, cloud credential files.
- Automatic destructive recovery — Never runs reset --hard, clean, branch replacement, or in-place checkout.
- Replaced Git executable — The bridge refuses to run if the pinned Git SHA-256 changes.
Before & after
Autonomy and containment are not opposites.
A good boundary lets the agent work freely inside it — you don’t become the gatekeeper.
Full Access
Every read, write, and send starts allowed.- agent
- Workspace
- Home directory
- Credentials
- Whole filesystem
- Network
Bounded autonomy
The agent works inside the boundary; out-of-bound actions fail.- agent
- Workspace
- Required runtime reads
- Explicit network policy
- Everything else → denied
With the recommended BoundedAutonomy mode, there are no approval prompts inside the boundary — limits do the work approvals were doing.
Approval and command networking are separate decisions. All three modes share the same least-privilege filesystem profile — only the reviewer changes.
Verification
Installed is not verified.
Installing a config is not the same as proving it holds. Verification reports what was actually checked — and what it could not check.
Restart Codex after installation before runtime probes.
- writes outside the workspace
- reads outside the workspace
- workspace secret files
- protected metadata (.git, .codex, .agents)
- deletion recovery (checkpoints)
- command network egress
- rollback and backups
- external surfaces — reported, never implied
A synthetic file placed outside the workspace is used to probe the boundary before any claim is made.
Install
Install Codex Safe Setup
Two commands, one prompt — then the skill audits, explains the tradeoffs, and writes configuration only after you confirm.
PS> codex plugin marketplace add QianQIUlp/codex-safe-setup --ref v0.1.0
codex plugin add codex-safe-setup@codex-safe-setup Start a new Codex task or CLI session, then ask:
Use $secure-codex-setup to audit my current permissions and install the recommended profile.
Requirements Requires Codex CLI 0.138.0 or newer · PowerShell 7 recommended on Windows
The marketplace method is preferred because Codex can track the plugin source and version.
Each release also ships an install-ready ZIP with a .sha256 file. Verify the archive in PowerShell with Get-FileHash -Algorithm SHA256 <archive>.
- 01 Read-only assessment — nothing changes yet.
- 02 Boundaries and tradeoffs explained, not hidden.
- 03 Separate consent for prerequisites (PowerShell 7, Codex CLI).
- 04 Plan-only preview of the exact configuration.
- 05 Applied only after your explicit confirmation.
- 06 Static and execpolicy verification; restart Codex afterwards.
- 07 Backups recorded — exact rollback stays available.
The boundary
Know the boundary.
A trustworthy security tool states what it does not control. These surfaces use separate control surfaces — each is reported as NOT CONTROLLED, never implied as protected.
- Web Search
- Browser
- Computer Use
- Apps & connectors
- Other plugins
- MCP servers
- Cloud tasks
- Source-control remotes
- CI credentials
- Credentials exposed before installation
- Host malware
- Operating-system compromise
Each appears as NOT CONTROLLED in the verification report.
- Revoke or rotate it immediately.
- Inspect the provider’s usage, sessions, and billing.
- Remove copies from files, logs, shell history, and repository history.
- Timing alone is not proof of causation.
Open source
Built in the open.
Community-built and Apache-2.0 licensed. Source, reproducible builds, and private security reporting on GitHub.
- CI runs isolated integration tests and package validation on Windows.
- Releases are built from validated tags and ship with SHA-256 checksums.
- Each release passed the official Skill and Plugin validators.
- Private vulnerability reporting through GitHub Security Advisories.