config.toml rewritten without BOM corrupts non-ASCII project paths, app fails to boot
<html>
<body>
<!--StartFragment--><html><head></head><body><h1>Codex rewrites config.toml without BOM, corrupting non-ASCII project paths and preventing app startup</h1>
<h2>Summary</h2>
<p>While registering the MATLAB MCP server, Codex rewrote the entire <code>~/.codex/config.toml</code> as <strong>UTF-8 without BOM</strong>. The file contained 40+ <code>[projects.*]</code> entries with Korean characters in the paths. All of them were mangled by the rewrite.</p>
<p>The Codex desktop app then hung at the onboarding screen ("Windows setup complete") and could not be started. Recovery took roughly 3 hours.</p>
<h2>Environment</h2>
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"
<h2>Steps to reproduce</h2>
<ol>
<li>Have <code>~/.codex/config.toml</code> contain <code>[projects.'...']</code> entries with non-ASCII characters in the paths</li>
<li>Ask Codex to register the MATLAB MCP server and add <code>env_vars = ["WINDIR"]</code></li>
<li>Codex first attempts a string replacement, which fails due to a line-ending mismatch</li>
<li>Codex falls back to rebuilding the file as a line array and rewriting it in full</li>
</ol>
<h2>The offending command</h2>
<pre><code class="language-powershell">$lines = [System.Collections.Generic.List[string]](Get-Content -LiteralPath $cfg)
...
[System.IO.File]::WriteAllLines($cfg, $lines, [System.Text.UTF8Encoding]::new($false))
</code></pre>
<p>Two issues combine here:</p>
<p><strong><code>Get-Content</code> without <code>-Encoding</code></strong>
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.</p>
<p><strong><code>UTF8Encoding::new($false)</code> strips the BOM</strong>
The already-corrupted strings are written back without a BOM, so the next read repeats the same misinterpretation and the damage compounds.</p>
<h2>Result</h2>
<ul>
<li>All Korean characters in <code>[projects.*]</code> paths replaced with mojibake</li>
<li>TOML parsing fails, app hangs during initialization</li>
<li><strong>Nothing is written to <code>~/.codex/log/</code></strong> — the failure occurs before logging is initialized</li>
<li>No UAC elevation prompt is raised (<code>consent.exe</code> never spawns)</li>
<li>ChatGPT processes accumulated to 14 and could not be terminated via <code>taskkill</code></li>
<li>The app is not fully dead — sqlite writes continue, which actively misleads diagnosis</li>
</ul>
<h2>Issues raised</h2>
<h3>1. File encoding is not preserved</h3>
<p>Rewriting a config file without detecting the original encoding. At minimum this needs <code>Get-Content -Encoding UTF8</code> and BOM preservation via <code>UTF8Encoding::new($true)</code>. In any non-English environment where non-ASCII paths are common, this will corrupt the file every time.</p>
<h3>2. Full rewrite with no backup</h3>
<p>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.</p>
<h3>3. The Guardian reviewer approved it</h3>
<p>With <code>approvals_reviewer = "auto_review"</code>, this command was allowed through. The reviewer policy states:</p>
<blockquote>
<p>Benign local filesystem actions, such as ... updating a small user-owned file ... are usually <code>low</code></p>
</blockquote>
<p>It was classified as a small user-owned file update. In reality it was a <strong>full rewrite of the agent's own boot configuration with a changed encoding</strong>. The reviewer did not recognize the <code>WriteAllLines</code> + encoding-change combination as risky.</p>
<h3>4. Silent failure</h3>
<p>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.</p>
<h3>5. The agent edits its own boot config</h3>
<p>When Codex breaks its own configuration, it cannot recover itself. This code path needs dedicated safeguards.</p>
<h2>Suggested fixes</h2>
<ul>
<li>Detect and preserve the original encoding and BOM when writing config files</li>
<li>Always pass <code>-Encoding</code> explicitly to PowerShell <code>Get-Content</code> / <code>Set-Content</code></li>
<li>Automatically back up <code>config.toml</code> before modification (<code>config.toml.<timestamp>.bak</code>)</li>
<li>Validate TOML parsing after write, roll back automatically on failure</li>
<li>Log config parse failures at startup and surface the offending line to the user</li>
<li>Add "full rewrite of the agent's own configuration file" as a distinct Guardian category</li>
<li>Escalate file writes that change encoding to review</li>
</ul>
<h2>Recovery (for anyone hitting this)</h2>
<pre><code class="language-powershell">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
</code></pre>
<p>This removes only the corrupted <code>[projects.*]</code> entries. Per-folder trust settings are lost and need to be re-approved, but model, plugin, and MCP server settings are preserved.</p></body></html><!--EndFragment-->
</body>
</html>