Webview bundle assumes crypto.randomUUID exists, breaking iOS mobile browser startup
What happened?
When the Codex desktop webview bundle is served to an iPhone browser environment, the app can get stuck on the startup Codex logo or enter a partially initialized state.
I reproduced this on mobile, including the native iPhone browser and WeChat's embedded iOS WebView. The clearest error capture came from the WeChat WebView case, but the issue is not limited to WeChat.
The root cause appears to be that the frontend bundle calls crypto.randomUUID() directly during initialization. In the affected iOS mobile browser/WebView environment, window.crypto exists, but crypto.randomUUID is not available.
Adding a small crypto.randomUUID fallback before the main webview bundle loads fixes the issue.
Environment
- Codex desktop webview bundle:
26.707.30751 - Client: iPhone mobile browser / iOS embedded WebView
- One observed user agent from the captured error case:
Mozilla/5.0 (iPhone; CPU iPhone OS 26_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.75 ...
Symptoms
- The initial HTML/CSS/JS assets load successfully.
/__backend/ipcWebSocket connects successfully.- The app may remain stuck on the Codex startup logo, or enter a partially initialized state where project context and sending messages do not work correctly.
- After adding a temporary frontend error probe, the client reported an unhandled rejection in a bundle stack around code equivalent to:
rendererInstanceId = crypto.randomUUID();
The stack pointed into a chunk similar to:
app-initial~app-main~appgen-settings-page~settings-page~skills-settings~plugins-settings~...
What I tested
I initially suspected top-level await in the entry bundle, but after reverting that change and keeping only the crypto.randomUUID compatibility fix, the app still worked. So the confirmed issue appears to be the missing crypto.randomUUID, not top-level await.
Workaround that fixed it locally
Adding this before the main app bundle loads resolves the startup issue:
if (window.crypto && typeof window.crypto.randomUUID !== "function") {
window.crypto.randomUUID = function () {
const bytes = new Uint8Array(16);
if (typeof window.crypto.getRandomValues === "function") {
window.crypto.getRandomValues(bytes);
} else {
for (let i = 0; i < bytes.length; i += 1) {
bytes[i] = Math.floor(Math.random() * 256);
}
}
bytes[6] = (bytes[6] & 0x0f) | 0x40;
bytes[8] = (bytes[8] & 0x3f) | 0x80;
const hex = [];
for (let i = 0; i < 256; i += 1) hex[i] = (i + 0x100).toString(16).slice(1);
return (
hex[bytes[0]] + hex[bytes[1]] + hex[bytes[2]] + hex[bytes[3]] + "-" +
hex[bytes[4]] + hex[bytes[5]] + "-" +
hex[bytes[6]] + hex[bytes[7]] + "-" +
hex[bytes[8]] + hex[bytes[9]] + "-" +
hex[bytes[10]] + hex[bytes[11]] + hex[bytes[12]] +
hex[bytes[13]] + hex[bytes[14]] + hex[bytes[15]]
);
};
}
Suggested fix
Avoid directly assuming crypto.randomUUID exists in frontend code. A shared UUID helper could use crypto.randomUUID() when available and fall back to crypto.getRandomValues() when it is not.
This would improve compatibility with iOS mobile browsers and embedded WebView environments where crypto.randomUUID is not available.