Skip to content

feat(proxy): Windows system-proxy discovery behind proxy "auto" (#1525) - #3209

Merged
lidge-jun merged 1 commit into
devfrom
codex/windows-proxy-auto-1525
Sep 1, 2026
Merged

feat(proxy): Windows system-proxy discovery behind proxy "auto" (#1525)#3209
lidge-jun merged 1 commit into
devfrom
codex/windows-proxy-auto-1525

Conversation

@lidge-jun

Copy link
Copy Markdown
Owner

Summary

  • First slice of Feature: auto-detect Windows system proxy with smart fallback ("proxy": "auto") #1525, scoped exactly as the reviewer asked: startup-time Windows WinINET static-proxy discovery behind "proxy": "auto", with clear logs and no live mutation or direct fallback.
  • New src/lib/windows-system-proxy.ts reads HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings (ProxyEnable, ProxyServer) through argv reg.exe with windowsHide, a 2 s timeout, and the shared ANSI decoder; parses bare host:port or per-scheme lists (https= then http=), ignores SOCKS-only, and normalizes to an http:// URL (userinfo kept for the environment, stripped from the log).
  • applyProxyEnv treats the literal auto (trimmed, case-insensitive) as discovery: existing HTTP_PROXY/HTTPS_PROXY still win without consulting the registry; a discovered proxy is mirrored exactly like a static URL; non-Windows, disabled, SOCKS-only, or unreadable settings log one privacy-safe line and use direct egress. The literal is never copied into the environment (today it would be).
  • Static URLs, ${ENV} references, noProxy, and loopback NO_PROXY are byte-for-byte unchanged; the top-level schema is passthrough so no zod change and no config backup churn.
  • Docs: server.md proxy row and the proxy JSDoc. Deferred, per review: PAC/WPAD, ProxyOverrideNO_PROXY, periodic re-check, reachability probes, direct fallback.

Closes #1525

Verification

  • bun x tsc --noEmit clean; bun run privacy:scan passed.
  • bun test tests/proxy-env.test.ts → 21 pass / 0 fail (5 new: parser forms, ProxyEnable/platform gating, Windows mirror with credential-free log, four non-proxy outcomes leave env untouched with one line, env precedence skips the registry). Tests inject the registry reader; CI never spawns reg.exe.
  • Full suite runs in CI on this PR.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

…o" (#1525)

Slice 1 of #1525. When config.proxy is the literal "auto", applyProxyEnv
reads the WinINET static proxy (HKCU Internet Settings ProxyEnable /
ProxyServer, https= then http= entry) once at process start and mirrors
it into HTTP_PROXY/HTTPS_PROXY when those are unset, logging only the
proxy origin. Non-Windows, disabled, SOCKS-only, or unreadable settings
degrade to direct egress with one log line; the literal is never copied
into the environment. Static URLs, ${ENV} references, user env
precedence, and loopback NO_PROXY are unchanged. PAC/WPAD, live
refresh, and direct fallback are deferred per the reviewer scope.
@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner September 1, 2026 19:51
@lidge-jun
lidge-jun merged commit 5bc6939 into dev Sep 1, 2026
6 checks passed
@lidge-jun
lidge-jun deleted the codex/windows-proxy-auto-1525 branch September 1, 2026 19:51
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-01T19:56:46.361045Z c98e383 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c98e383140

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/config.ts
console.log("[opencodex] proxy \"auto\": existing HTTP_PROXY/HTTPS_PROXY environment wins; system proxy not consulted");
proxy = undefined;
} else {
const found = readWindowsSystemProxy(auto.reader, auto.platform);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Cache automatic proxy discovery across startup callers

During an ordinary ocx start with Codex sync enabled, startServer calls applyProxyEnv at src/server/index.ts:641, and the later startup sync reaches src/codex/sync.ts:199 and calls it again. Because this line performs discovery afresh on every invocation, a disabled or unreadable system proxy can spawn reg.exe twice and add another timeout-sized delay and duplicate log; successful discovery instead emits a second misleading “existing environment wins” message because the first invocation created those variables. Cache the automatic-discovery result/log per process or give startup a single owner for this operation.

Useful? React with 👍 / 👎.

| `port` | `number` | `10100` | Proxy listen port. |
| `hostname?` | `string` | `"127.0.0.1"` | Bind address. Non-loopback binds require `OPENCODEX_API_AUTH_TOKEN`. |
| `proxy?` | `string` | — | Outbound HTTP(S) proxy URL or `${ENV_VAR}`. Applied to `HTTP_PROXY` / `HTTPS_PROXY` only when those variables are unset; loopback remains in `NO_PROXY`. |
| `proxy?` | `string` | — | Outbound HTTP(S) proxy URL, `${ENV_VAR}`, or `"auto"`. Applied to `HTTP_PROXY` / `HTTPS_PROXY` only when those variables are unset; loopback remains in `NO_PROXY`. `"auto"` reads the Windows system proxy (WinINET `ProxyEnable`/`ProxyServer`, `https=` then `http=` entry) once at process start and logs the host it chose. On other platforms, or when the system proxy is off, SOCKS-only, or unreadable, it uses direct egress and says so. PAC/WPAD and live proxy changes are not followed; restart the service after changing the system proxy. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Synchronize the translated proxy references

The English row now documents the valid "auto" value, but every translated counterpart (fr, ja, ko, ru, tr, zh-cn, and zh-tw) still defines the accepted forms as only a proxy URL or ${ENV_VAR}. This leaves localized configuration references contradicting the canonical page and omits the Windows-only behavior, direct-egress cases, and restart requirement; update those rows alongside the English source.

AGENTS.md reference: docs-site/AGENTS.md:L7-L10

Useful? React with 👍 / 👎.

@lidge-jun

Copy link
Copy Markdown
Owner Author

리뷰 · 우선순위 42 / 80

이 PR은 이미 dev에 들어가 있습니다. 머지 커밋은 5bc6939d8이고, 지금 HEAD d23eab43a(#3224) 조상에 있습니다. 이 댓글은 늦은 웨이크(PR opened 트리거)라서, 이미 올라간 코드와 남은 구멍을 정리하는 회고 리뷰입니다. 이슈 #1525도 같이 닫혀 있습니다.

지금 devconfig.proxy는 예전에 정적 URL이나 ${ENV}만 받았습니다. Windows에서 VPN/프록시 포트를 자주 바꾸면 설정이 금방 낡아서, 서비스가 502 Provider unreachable만 내고 직접 고칠 때까지 멈췄습니다. #1525가 원한 전체 그림은 (1) 시작 때 시스템 프록시 읽기, (2) 도달성 검사 후 직접 접속 폴백, (3) 약 60초마다 다시 읽기입니다. 이 PR은 그중 슬라이스 1만 넣었습니다.

슬라이스 1이 하는 일은 짧고 분명합니다. proxy 값이 대소문자 무시하고 잘랐을 때 "auto"이면, src/lib/windows-system-proxy.tsHKCU\Software\Microsoft\Windows\CurrentVersion\Internet SettingsProxyEnable / ProxyServerreg.exe로 한 번 읽습니다. 타임아웃 2초, windowsHide, 공유 ANSI 디코더를 씁니다. https= 항목을 먼저 보고 없으면 http=를 씁니다. 맨손 host:port도 됩니다. SOCKS만 있으면 HTTP_PROXY로 못 옮기니 직접 접속으로 내려갑니다. Windows가 아니거나 꺼져 있거나 못 읽으면 로그 한 줄만 남기고 직접 접속합니다. 찾은 URL은 기존 정적 프록시처럼 HTTP_PROXY / HTTPS_PROXY에 넣고, 로그에는 origin만 남겨 비밀번호가 안 나오게 합니다. 이미 환경 변수에 프록시가 있으면 레지스트리를 안 보고 그대로 둡니다. 문자열 "auto" 자체는 환경에 절대 안 넣습니다. PAC/WPAD, ProxyOverrideNO_PROXY, 주기 재검사, 도달성 폴백은 의도적으로 미뤘습니다.

테스트는 tests/proxy-env.test.ts에 파서·플랫폼 게이트·자격증명 없는 로그·실패 네 갈래·환경 우선을 넣었고, 레지스트리 리더를 주입해서 CI가 reg.exe를 안 띄웁니다. 영문 server.mdsrc/types/config.ts JSDoc도 "auto"를 설명합니다. 스키마는 그대로 passthrough라 zod/백업 흔들림이 없습니다. types.ts / config.ts 분할 캠페인과 겹치는 구조 개편이 아니라, 프록시 한 칸의 동작만 늘린 것이라 닫고 다시 쌓을 대상이 아닙니다.

라인 3646-3649 (src/config.ts · applyProxyEnvWith) - if (proxy) { 안쪽 두 줄 들여쓰기가 한 단 빠졌습니다. 동작은 맞지만 읽기/리뷰가 헷갈립니다. 다음에 손댈 때 들여쓰기만 맞춰 주세요.
라인 3621-3644 / 호출부 src/server/index.ts:642 + src/codex/sync.ts:126,146,199 - applyProxyEnv가 한 프로세스에서 여러 번 불릴 수 있습니다. 서버 시작 뒤 Codex sync가 다시 부르면, 첫 호출이 만든 HTTP_PROXY 때문에 두 번째는 “existing environment wins” 로그를 남기거나, 실패 경로면 reg.exe를 또 띄울 수 있습니다. 프로세스당 한 번만 발견하거나 startup 한 곳이 주인이 되는 편이 맞습니다.
경로 docs-site 번역본 (fr/ja/ko/ru/tr/zh-cn/zh-tw) - 영문 server.md"auto"를 적었고, 번역 표는 아직 URL / ${ENV}만 말합니다. AGENTS.md 문서 규칙상 같이 맞춰야 합니다.
심볼 parseWindowsProxyServer / normalize - userinfo는 환경에 남기고 로그만 origin으로 깎는 선택은 맞습니다. SOCKS-only를 직접 접속으로 내리는 것도 HTTP_PROXY 한계상 맞습니다. 다만 #1525 원문의 “프록시 죽으면 직접 폴백 + 60초 재검사”는 이 슬라이스에 없어서, 운영자가 "auto"만 켜고 재시작 없이 VPN을 바꾸면 여전히 낡은 라우팅을 탑니다. 문서에 “시스템 프록시 바꾼 뒤 서비스 재시작”이 적혀 있으니 의도는 분명하지만, 원 이슈 기대와는 아직 절반입니다.
테스트 auto never leaks the literal - darwin / disabled / socks / unreadable 네 갈래가 env를 안 건드리는지 잠근 것은 좋습니다. 이중 호출(캐시) 회귀는 아직 없습니다.

메인테이너의 판단이 필요한 지점

  • 이미 dev에 있으니 이 PR 자체는 추가 머지 판단이 필요 없습니다. 회고만 남깁니다.
  • 프로세스당 discovery 캐시(또는 startup 단일 소유)를 바로 후속 이슈/PR로 뺄지, 슬라이스 2(도달성·재검사)와 묶을지.
  • 번역 server.md 행을 지금 작은 문서 PR로 맞출지, 다음 문서 묶음에 넣을지.
  • #1525를 닫은 채 슬라이스 2·3을 새 이슈로 열지, 아니면 #1525를 다시 열어 “남은 범위”로 쓸지. (지금은 닫힘)
  • types/config 분할과는 무관합니다. 이 PR이나 후속을 분할 때문에 닫을 이유는 없습니다.

너의 추천
이미 올라간 슬라이스 1은 범위가 깨끗하고 테스트·로그 프라이버시도 좋습니다. 추가 머지 작업은 없습니다. 다음에 손대면 (1) applyProxyEnv discovery를 프로세스당 한 번으로 묶고, (2) 번역 server.mdproxy 행을 영문과 맞추고, (3) 들여쓰기만 고치세요. 도달성 폴백·주기 재검사는 별도 이슈로 열어 #1525 slice 2처럼 적는 편이 기여자에게 덜 헷갈립니다. SOCKS5 실수송 PR(#2921 draft)과는 겹치지 않게, 이번 "auto"는 WinINET 정적 HTTP 프록시만 담당한다고 이슈 본문에 한 줄 더 박아 두면 좋습니다.

이 댓글은 grok-bot이 작성했습니다

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant