Desktop: full-CDP silently disabled when CODEX_HOME is a symlink
Summary
Codex Desktop's Browser Developer Mode can show Enable full CDP access as enabled while silently omitting the cdp tab capability from both Browser backends when CODEX_HOME (~/.codex) is a symlink.
The trusted Browser runtime does receive the privileged nodeRepl.config bridge. However, its call to readToml("browser/config.toml") rejects with:
Codex TOML directory must not be a symlink
The Browser client catches that exception, replaces it with a generic internal disabled result, and omits the cdp capability. The settings UI continues to display the toggle as enabled because it reads the same config through a different path that succeeds.
Environment
- Codex Desktop:
26.715.71837(CFBundleVersion5702) - Bundle ID:
com.openai.codex - Bundled CLI:
codex-cli 0.145.0-alpha.30 - Platform:
Darwin 25.3.0 arm64 arm/ macOS26.3(25D125) - Browser bundled plugin:
26.715.71837 codex features listreports bothin_app_browserandbrowser_use_full_cdp_accessas stable/true
Reproduction
- Use a symlink for
CODEX_HOME. In this reproduction:
``text``
~/.codex -> ~/.dotfiles/codex/codex.symlink
- In Codex Settings → Browser, enable Developer Mode / Enable full CDP access.
- Confirm
~/.codex/browser/config.tomlcontains:
``toml``
full_cdp_access_enabled = true
- Restart/reinitialize Browser Use and inspect the capabilities returned by
agent.browsers.list().
Actual behavior
Both healthy, connected backends omit the tab-level cdp capability:
- Chrome (
extension): browser capabilityviewport; tab capabilitypageAssetsonly. - Codex In-app Browser (
iab): browser capabilitiesvisibility,viewport; tab capabilitypageAssetsonly.
The settings UI still shows full CDP access as enabled. No actionable error is shown, and codex doctor does not identify the rejected configuration.
Expected behavior
- A symlinked
CODEX_HOMEshould work, provided the resolved path remains within the intended user-controlled configuration directory and passes appropriate ownership/permission validation. - If symlinks truly cannot be supported safely, the settings UI should refuse the change or show a clear diagnostic instead of displaying an enabled state that the Browser runtime will silently reject.
codex doctorshould report this configuration/runtime mismatch and include the underlying rejection reason.
Live diagnosis
I attached a temporary in-process debugger to the active Node REPL runtime and set breakpoints inside the trusted, hash-approved bundled Browser client.
The full-CDP gate calls these privileged methods in parallel:
nodeRepl.config.readToml("browser/config.toml")
nodeRepl.config.readRequirements()
Observed results:
[
{
"status": "rejected",
"reason": {
"name": "Error",
"message": "Codex TOML directory must not be a symlink"
}
},
{
"status": "fulfilled",
"value": {
"requirements": null
}
}
]
This establishes that:
- The privileged bridge is present in trusted Browser code.
- Enterprise requirements are not disabling the feature.
- The TOML read fails specifically because
~/.codexis a symlink. - The Browser client catches the exception and returns:
``text``
Full CDP access could not be verified from browser config and enterprise policy.
- Capability enrichment consequently omits
cdp.
The public/model-facing globalThis.nodeRepl intentionally lacks config, so checking globalThis.nodeRepl?.config from ordinary submitted code is not a valid test for whether the trusted privileged bridge exists.
UX and diagnostic problems
- The UI reports the persisted setting, not whether the runtime can actually use it.
- The actionable native error is swallowed and replaced with a generic disabled state.
- A normal developer configuration layout is rejected without documentation or a diagnostic.
- There is no
codex doctorcheck for a symlinkedCODEX_HOMEor for an enabled-but-unavailable full-CDP capability.
Relevant evidence
| Artifact | SHA-256 |
| --- | --- |
| /Applications/ChatGPT.app/Contents/Resources/app.asar | 11292b6a04d8aef36c30940b94ce3a744844dc5a52797228fbebb87f8529f102 |
| /Applications/ChatGPT.app/Contents/Resources/cua_node/bin/node_repl | 280df9eed10a975c7d5db7ee418b7da4df6de79158968183d2572e78bac746d2 |
| bundled browser-client.mjs | 2793c6809f8a4c90923435aa3a6d1e6f8cabb145212f06328b860b076b899525 |
The exact symlink rejection string is present in the shipped native node_repl executable. I could not find that implementation or either exact error string in the public openai/codex source tree.
Related issues
- #24017 reports persisted Browser approvals being ignored and inferred that
nodeRepl.configwas missing. - #30947 reports Browser policy failures and similarly inferred that the privileged bridge was missing.
Those issues may have different platform-specific causes. This report does not claim the symlink rejection explains either one, but the restricted-versus-privileged nodeRepl distinction and swallowed readToml exception may provide a deeper diagnostic path.
1 Comment
I also submitted this through the Codex Desktop in-app feedback flow.
In-app feedback ID:
019f9755-e508-7d62-ae34-e7162c0f58b5