stablyai/orca · critical · Error

Electron escaped the disposable validation boundary

Error message

Electron escaped the disposable validation boundary

What it means

Thrown after Electron launches inside the disposable validation boundary when Electron's reported home, nodeHome, or userData paths do not all match the disposable layout (layout.homeDir / layout.userDataDir). This is a containment guarantee: if Electron reads the real HOME or userData, credentials could leak outside the sandboxed temp root, so the run aborts.

Source

Thrown at config/scripts/run-codex-real-account-validation.mjs:534

    await writeReport(reportPath, report)
    console.log(`Disposable HOME: ${layout.homeDir}`)
    console.log(`Disposable userData: ${layout.userDataDir}`)
    console.log(`Sanitized report: ${reportPath}`)

    if (!options.dryRun) {
      const mainPath = buildAppIfNeeded(repoRoot, options.skipBuild)
      app = await electron.launch({ args: [mainPath], env: launchEnv })
      report.electronPaths = await app.evaluate(({ app: electronApp }) => ({
        home: electronApp.getPath('home'),
        userData: electronApp.getPath('userData'),
        nodeHome: process.getBuiltinModule('node:os').homedir()
      }))
      if (
        !samePath(report.electronPaths.home, layout.homeDir) ||
        !samePath(report.electronPaths.nodeHome, layout.homeDir) ||
        !samePath(report.electronPaths.userData, layout.userDataDir)
      ) {
        throw new Error('Electron escaped the disposable validation boundary')
      }
      app.process().once('exit', () => abortController.abort())
      await writeReport(reportPath, report)
      if (!options.closeAfterLaunch) {
        await runInteractiveSession({
          layout,
          launchEnv,
          report,
          reportPath,
          tripwire,
          signal: abortController.signal
        })
      }
    }
  } finally {
    abortController.abort()
    try {
      await closeValidationElectronApp(app)

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Verify launchEnv sets HOME and any userData-deriving vars to layout.homeDir before electron.launch.
  2. Ensure no leftover Electron app config (Library/Application Support) is being read; use a clean userData dir.
  3. Confirm samePath normalizes symlinks/case on your platform, or point the disposable root at a non-symlinked path.
  4. Check the Electron version does not pin userData via app.setPath calls in main before the boundary check.

Example fix

// before
app = await electron.launch({ args: [mainPath], env: launchEnv })
// after
launchEnv = { ...launchEnv, HOME: layout.homeDir, USERPROFILE: layout.homeDir }
app = await electron.launch({ args: [mainPath], env: launchEnv, env: { ...launchEnv, ORCA_USER_DATA_DIR: layout.userDataDir } })
Defensive patterns

Strategy: validation

Validate before calling

import path from 'node:path'
function samePath(a, b) { return path.resolve(a) === path.resolve(b) }
// validate launchEnv before launching Electron
function assertBoundaryEnv(layout, launchEnv) {
  if (!launchEnv.HOME || !samePath(launchEnv.HOME, layout.homeDir)) {
    throw new Error(`launchEnv.HOME must equal ${layout.homeDir}`)
  }
}
assertBoundaryEnv(layout, launchEnv)

Type guard

function hasBoundaryPaths(paths, layout, samePath) {
  return (
    samePath(paths.home, layout.homeDir) &&
    samePath(paths.nodeHome, layout.homeDir) &&
    samePath(paths.userData, layout.userDataDir)
  )
}

Try / catch

try {
  report.electronPaths = await app.evaluate(/* getPath/getPath/homedir */)
  if (!hasBoundaryPaths(report.electronPaths, layout, samePath)) {
    throw new Error('Electron escaped the disposable validation boundary')
  }
} catch (err) {
  await closeValidationElectronApp(app)
  throw err
}

Prevention

When it happens

Trigger: electron.launch succeeds but electronApp.getPath('home'), getPath('userData'), or node:os.homedir() resolves outside layout.homeDir/layout.userDataDir. SamePath() returns false for any of the three checks.

Common situations: HOME or XDG_* env vars not propagated to the Electron launch env; Electron version that overrides userData from a config file or persisted app path; running on a platform where the temp root resolves through a symlink that samePath does not normalize; a stale userData left over in the disposable dir.

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/e382cc80651e9cbd. Report an issue: GitHub.