Repository navigation
config.toml rewritten without BOM corrupts non-ASCII project paths, app fails to boot #36844
Description
Codex rewrites config.toml without BOM, corrupting non-ASCII project paths and preventing app startup
Summary
While registering the MATLAB MCP server, Codex rewrote the entire ~/.codex/config.toml as UTF-8 without BOM. The file contained 40+ [projects.*] entries with Korean characters in the paths. All of them were mangled by the rewrite.
The Codex desktop app then hung at the onboarding screen ("Windows setup complete") and could not be started. Recovery took roughly 3 hours.
Environment
| Item | Value |
|---|---|
| OS | Windows 11 (Korean locale, ANSI codepage 949) |
| Codex CLI | 0.146.0-alpha.9.2 |
| Codex app | 26.727.51351 |
| Model | gpt-5.6-terra |
| Relevant config | approval_policy = "never", sandbox_mode = "danger-full-access" |
Steps to reproduce
- Have
~/.codex/config.tomlcontain[projects.'...']entries with non-ASCII characters in the paths - Ask Codex to register the MATLAB MCP server and add
env_vars = ["WINDIR"] - Codex first attempts a string replacement, which fails due to a line-ending mismatch
- Codex falls back to rebuilding the file as a line array and rewriting it in full
The offending command
$lines = [System.Collections.Generic.List[string]](Get-Content -LiteralPath $cfg)
# ...
[System.IO.File]::WriteAllLines($cfg, $lines, [System.Text.UTF8Encoding]::new($false))
Two issues combine here:
Get-Content without -Encoding
Windows PowerShell 5.1 falls back to the system ANSI codepage (CP949 on Korean systems) when no BOM is present. UTF-8 Korean text is already corrupted at read time.
UTF8Encoding::new($false) strips the BOM
The already-corrupted strings are written back without a BOM, so the next read repeats the same misinterpretation and the damage compounds.
Result
- All Korean characters in
[projects.*]paths replaced with mojibake - TOML parsing fails, app hangs during initialization
- Nothing is written to
~/.codex/log/— the failure occurs before logging is initialized - No UAC elevation prompt is raised (
consent.exenever spawns) - ChatGPT processes accumulated to 14 and could not be terminated via
taskkill - The app is not fully dead — sqlite writes continue, which actively misleads diagnosis
Issues raised
1. File encoding is not preserved
Rewriting a config file without detecting the original encoding. At minimum this needs Get-Content -Encoding UTF8 and BOM preservation via UTF8Encoding::new($true). In any non-English environment where non-ASCII paths are common, this will corrupt the file every time.
2. Full rewrite with no backup
The goal was to add a single line. The agent overwrote the entire file with no prior backup and no way to roll back on failure.
3. The Guardian reviewer approved it
With approvals_reviewer = "auto_review", this command was allowed through. The reviewer policy states:
Benign local filesystem actions, such as ... updating a small user-owned file ... are usually
low
It was classified as a small user-owned file update. In reality it was a full rewrite of the agent's own boot configuration with a changed encoding. The reviewer did not recognize the WriteAllLines + encoding-change combination as risky.
4. Silent failure
The parse failure is not logged anywhere. From the user's perspective, the only observable fact is "I asked it to configure something and now the app won't open." I only found the cause by manually parsing the session JSONL files.
5. The agent edits its own boot config
When Codex breaks its own configuration, it cannot recover itself. This code path needs dedicated safeguards.
Suggested fixes
- Detect and preserve the original encoding and BOM when writing config files
- Always pass
-Encodingexplicitly to PowerShellGet-Content/Set-Content - Automatically back up
config.tomlbefore modification (config.toml.<timestamp>.bak) - Validate TOML parsing after write, roll back automatically on failure
- Log config parse failures at startup and surface the offending line to the user
- Add "full rewrite of the agent's own configuration file" as a distinct Guardian category
- Escalate file writes that change encoding to review
Recovery (for anyone hitting this)
taskkill /F /IM ChatGPT.exe /T
$cfg = "$env:USERPROFILE.codex\config.toml"
Copy-Item $cfg "$cfg.broken"
(Get-Content $cfg -Encoding UTF8) |
Where-Object { $_ -notmatch '^[projects.' -and $_ -notmatch '^trust_level' } |
Set-Content $cfg -Encoding UTF8
This removes only the corrupted [projects.*] entries. Per-folder trust settings are lost and need to be re-approved, but model, plugin, and MCP server settings are preserved.
Activity