Skip to content

fix: harden proxy, cleanup, daemon, and import paths from history review - #195

Merged
Loongphy merged 5 commits into
mainfrom
fix/review-hardening
Nov 8, 2026
Merged

Loongphy merged 5 commits into
mainfrom
fix/review-hardening

Conversation

@Loongphy

@Loongphy Loongphy commented Nov 8, 2026

Copy link
Copy Markdown
Owner

Summary

Follow-up fixes from the strict v0.3.1..main history review.

Proxy subsystem

  • Split bare WinHTTP PAC failover lists (host:port; host2:port) on ; and use the first entry — previously the whole list reached curl as one invalid --proxy value.
  • Map WinINET protocol keys to curl schemes (socks→socks4, plus socks4/socks5/socks5h) and translate *.domain bypass entries to curl noproxy suffixes.
  • scutil parser now keeps only the nine keys it consumes, so unrelated fields can no longer evict HTTP/HTTPS/SOCKS settings past the old field budget.
  • System-proxy probe uses a blocking Io.Mutex instead of a spin loop, and the proxy-URL allocation no longer leaks on the noproxy error path.

Reliability

  • codex-auth app falls back to the cached codext CLI when the release lookup fails (offline / GitHub rate-limit), instead of hard-failing.
  • clean preserves the managed codext-cli cache and the default backup export directory; stale entries are collected before deletion (also in removed-account backup pruning) so iterating-while-deleting cannot skip siblings.
  • config.toml rewrites go through temp-file + rename: symlink-aware target resolution plus atomic replace on POSIX (Windows keeps backup-swap), so a crash can't leave a missing or truncated settings file.
  • Daemon executable resolution skips empty PATH segments and reports not-found instead of a bare name the OS would resolve against the working directory; ExecutableRequired maps to not_running only when the control socket is gone — a live endpoint stays unknown.
  • The app-running probe distinguishes "not running" from probe failure (non-zero exit included), so a failed check can no longer trigger a second app instance.
  • Live TUI Enter on a non-selectable row keeps the view open.

Validation & display safety

  • import --alias shares the alias set rules (format + conflicts) and validates before writing snapshots; a rejected alias on the single aliased array item fails the import so --purge never saves a registry missing that account.
  • API/auth-derived display text is sanitized (C0/C1/DEL + invalid UTF-8 → space); stored account_name/alias are cleaned on load, and a control-containing stored alias is dropped rather than silently renamed. aliasFormatIssue rejects the same codepoints.
  • New app error codes are registered in the preflight handled-error table; install failures print their cause.
  • POSIX PATH checks require the execute bit so a data file can't shadow a real tool.

Test plan

  • zig build clean
  • zig build test test-helpers — full suite green (incl. new tests: PAC failover, socks mapping, bypass translation, scutil overflow, clean whitelist, collect-then-delete, import alias rules, sanitize, aliasFormatIssue)
  • zig build -Doptimize=ReleaseSafe
  • Isolated CODEX_HOME e2e: import --alias 123 → InvalidAlias; clean preserves backup/ + codext-cli/
  • Local Greptile review: 5/5 confidence, zero comments (three rounds of findings addressed)
  • PR CI
  • pkg.pr.new preview smoke test (Linux + Windows via pwsh)

Proxy handling:
- Split bare WinHTTP PAC failover lists (`host:port; host2:port`) on ';'
  and use the first entry instead of passing an invalid proxy to curl.
- Map WinINET protocol keys to curl schemes: socks->socks4, socks4,
  socks5, socks5h; keep http/https.
- Translate '*.domain' bypass entries to curl noproxy suffixes and stop
  leaking the proxy URL when noproxy allocation fails.
- Replace the system-proxy probe spin loop with a blocking Io.Mutex.
- scutil --proxy: keep only the nine keys the parser consumes so
  unrelated fields can no longer evict HTTP/HTTPS/SOCKS settings.

Reliability:
- `codex-auth app` falls back to the cached codext CLI when the release
  lookup fails instead of hard-failing offline.
- `clean` preserves the managed `codext-cli` cache and default `backup`
  export directory; stale entries are collected before deletion so
  iterating-while-deleting cannot skip siblings (same fix for removed
  account backup pruning).
- Rewrites to the user's `config.toml` go through a temp-file rename so
  a crash cannot leave a truncated file.
- The daemon executable resolver skips empty PATH segments and reports
  not-found instead of falling back to a bare name the OS would resolve
  against the working directory; a missing executable maps to the
  silent not_running contract rather than an 'unconfirmed' warning.
- The app-running probe distinguishes 'not running' from probe failures
  so a failed check no longer risks launching a second instance.
- Live TUI Enter on a non-selectable row keeps the view open.

Validation & safety:
- `import --alias` now shares the `alias set` rules (format + conflicts)
  and validates before writing snapshots or mutating the registry.
- Display text from API/auth sources is sanitized (control characters
  and invalid UTF-8 become spaces) before reaching the terminal; email
  normalization is shared instead of duplicated.
- New app error codes are registered in the preflight handled-error
  table so failures report friendly messages.
- PATH executable checks require the execute bit on POSIX so a data
  file cannot shadow a real tool.

Tests cover PAC failover, socks mapping, bypass translation, scutil
overflow, clean whitelist, collect-then-delete, import alias rules,
and display sanitization.
…paths

- config.toml rewrite resolves symlinks to their target and uses a
  single atomic rename on POSIX so an interrupted write can no longer
  leave the settings file missing; Windows keeps the backup-swap dance.
- Stored account_name and alias values are cleaned on registry load:
  names get control characters stripped, and a control-containing alias
  is dropped instead of silently renamed.
- installManagedCodextExecutable prints the package-layout error before
  returning CodextReleaseInstallFailed so the handled error is not mute.
- The stale-entry collectors free the duplicated name when list append
  fails, closing an error-path leak in clean and account backup pruning.
- The Windows app-running probe now also requires a successful exit
  before trusting the PowerShell output, matching the macOS branch.
…g helpers

- A rejected --alias on the single aliased array item now fails the
  import, so a purge run never saves a registry missing that account.
- ExecutableRequired no longer maps blindly to not_running: when the
  control socket still exists the daemon state stays unconfirmed in
  both the switch path and the live daemon worker.
@greptile-apps

greptile-apps Bot commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] The changes affect several bounded codex-auth workflows for proxy use, account management, and app launching.

The PR still needs the Windows settings replacement fixed before merging.

Findings

  1. P1 Interrupted swaps leave settings missing ▶
Fix with agent prompt
### Issue 1
src/workflows/app.zig:533-539
On Windows, `writeConfigFileWindowsReplace` moves `config.toml` to a backup before putting the new file in place. If the process stops between those renames, `config.toml` stays missing because `errdefer` never runs. Codex can then start without the user's settings. Use a Windows replacement operation that keeps the destination present throughout the swap.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

This PR hardens proxy selection, cleanup, imports, app setup, and daemon checks.

  • System proxy settings reach curl in a form it can use.
  • Cleanup keeps managed folders and collects stale entries before deleting them.
  • Imports with an alias follow the same rules as alias set.
  • Account names and other displayed text are cleaned before they are shown.
  • The app command can use the cached Codext CLI when release lookup fails.
  • Codex settings updates replace the config file without truncating it first.
  • A failed app-running check no longer counts as proof the app is stopped.
  • Daemon lookup avoids the current directory and checks the socket before reporting absence.
  • PATH lookup skips files that cannot be run as curl.
  • Enter keeps the live account view open when a row cannot be selected.

Reviews (2) · Last reviewed commit: "test: seed a managed stub executable for..." · Reviewed by Greptile

Comment thread src/workflows/app.zig
Comment on lines +533 to +539
const had_original = blk: {
std.Io.Dir.cwd().rename(path, std.Io.Dir.cwd(), backup_path, app_runtime.io()) catch |err| switch (err) {
error.FileNotFound => break :blk false,
else => return err,
};
break :blk true;
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Interrupted swaps leave settings missing

On Windows, writeConfigFileWindowsReplace moves config.toml to a backup before putting the new file in place. If the process stops between those renames, config.toml stays missing because errdefer never runs. Codex can then start without the user's settings. Use a Windows replacement operation that keeps the destination present throughout the swap.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/workflows/app.zig
Line: 533-539

Comment:
**Interrupted swaps leave settings missing**

On Windows, `writeConfigFileWindowsReplace` moves `config.toml` to a backup before putting the new file in place. If the process stops between those renames, `config.toml` stays missing because `errdefer` never runs. Codex can then start without the user's settings. Use a Windows replacement operation that keeps the destination present throughout the swap.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

@pkg-pr-new

pkg-pr-new Bot commented Nov 8, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

@loongphy/codex-auth-darwin-arm64

npx https://pkg.pr.new/@loongphy/codex-auth-darwin-arm64@49e03cf

@loongphy/codex-auth-darwin-x64

npx https://pkg.pr.new/@loongphy/codex-auth-darwin-x64@49e03cf

@loongphy/codex-auth-linux-arm64

npx https://pkg.pr.new/@loongphy/codex-auth-linux-arm64@49e03cf

@loongphy/codex-auth-linux-x64

npx https://pkg.pr.new/@loongphy/codex-auth-linux-x64@49e03cf

@loongphy/codex-auth-win32-arm64

npx https://pkg.pr.new/@loongphy/codex-auth-win32-arm64@49e03cf

@loongphy/codex-auth-win32-x64

npx https://pkg.pr.new/@loongphy/codex-auth-win32-x64@49e03cf

@loongphy/codex-auth

npx https://pkg.pr.new/@loongphy/codex-auth@49e03cf

commit: 49e03cf

@Loongphy
Loongphy merged commit 000f3a9 into main Nov 8, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant