Skip to content

feat(intercept): scope CONNECT destinations and CA lifetime - #5934

Closed
luvs01 wants to merge 2 commits into
lidge-jun:devfrom
luvs01:feat/connect-destination-restrictions
Closed

luvs01 wants to merge 2 commits into
lidge-jun:devfrom
luvs01:feat/connect-destination-restrictions

Conversation

@luvs01

@luvs01 luvs01 commented Sep 26, 2026 •

Copy link
Copy Markdown
Collaborator

Problem and change

The shared CONNECT primitive supports both intercepted hosts and blind forwarding. A consumer that only needs a small set of destinations currently cannot express that restriction: interceptHosts selects how a tunnel is handled, not whether its destination is permitted.

Add optional allowedTargets containing exact host:port authorities. The list is normalized and copied before listening. An empty list denies all destinations; a missing list preserves existing behavior. A disallowed request receives 403 before tunnel selection or dialing, while proxy authentication and loopback refusal remain in force. Malformed policies fail before binding a listener.

Also let a scoped caller choose a shorter CA lifetime with AuthorityOptions.validityDays (whole days from 1 to 3650). The existing 3650-day default and persisted-authority behavior remain unchanged. A temporary trial can now use a one-day authority through the shared implementation instead of copying or dynamically patching certificate-generation code.

Existing Claude consumers do not enable this option and retain their current forwarding behavior. This is a reusable prerequisite for a narrowly scoped desktop integration, not an implementation or claim of Codex composer recovery. It installs no certificate, changes no account or routing setting, and adds no listener by itself.

Validation

  • bun test tests/claude-integration/claude-intercept-proxy.test.ts: 19 passed, 0 failed, 102 assertions, including real loopback sockets, existing TLS/forwarding/authentication behavior, exact destination restrictions, immutable startup policy, empty policy and malformed policy rejection.
  • bun test tests/claude-integration/claude-intercept-local-ca.test.ts: 9 passed, 0 failed, 41 assertions, including one-day validity, unchanged default, malformed lifetimes, signature/leaf compatibility and existing persistence/lease behavior.
  • node node_modules/typescript/bin/tsc --noEmit: passed (the equivalent compiler invoked by the repository typecheck script).
  • Direct Bun invocation of scripts/privacy-scan.ts and scripts/structure-ssot.ts: passed.
  • git diff --check: passed.

Validation used Windows with Bun 1.4.2. Identical dependency lockfiles were checked before reusing a local dependency directory. bun run wrappers encountered a dependency-bin remapping error, so the same compiler and validation entrypoints were invoked directly. An initial test process started before dependency linking failed on zod/v4 before any tests ran; after fresh-process resolution was verified, the focused run above passed.

The full/import-graph suite was not run for these two optional primitive parameters because another same-host run selected 1,284 test files and occupied the shared test lock until its 900-second limit. This PR remains draft; focused behavior is covered, but Linux/macOS execution and required exact-head CI are not claimed. Independent security review is required before integration.

Review readiness

  • Required exact-head validation complete with remaining platform coverage documented.
  • Branch refreshed against the current integration branch.
  • Applicable Codex/CodeRabbit findings resolved.
  • Ready for maintainer review confirmed.

@coderabbitai

coderabbitai Bot commented Sep 26, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the enhancement New feature or request label Sep 26, 2026
@github-actions

Copy link
Copy Markdown
Contributor

✅ Deterministic PR hygiene checks passed.

@lidge-jun

Copy link
Copy Markdown
Owner

리뷰 · 우선순위 52 / 80

Claude가 인터넷으로 나갈 때는 CONNECT 이름:포트로 통로를 엽니다. 지금 프록시는 가로챌 이름만 고릅니다. 나머지 목적지는 그대로 바깥 서버로 보냅니다. "이 주소만 허락한다"는 칸은 없었습니다.

이 PR은 allowedTargets를 더합니다. 포트를 열기 전에 목록을 복사합니다. 대문자는 소문자로 바꾸고, 이름 끝의 점 하나는 지웁니다. 요청을 읽을 때와 같은 규칙입니다. 목록을 안 넘기면 예전처럼 다 보냅니다. 빈 목록이면 모든 목적지를 403으로 막습니다. 목록에 없는 주소도, 통로를 고르거나 바깥에 연결하기 전에 403입니다. 인증이 켜져 있으면 인증이 먼저입니다. 자기 컴퓨터 주소(127.0.0.1 같은 것)는 목록에 적어도 403입니다. 모양이 이상한 목록은 포트를 열기 전에 실패해야 합니다.

지금 돌아가는 Claude 쪽은 이 목록을 넘기지 않습니다. 그래서 지금 프록시 동작은 그대로입니다. 인증서를 설치하지 않고, 계정이나 경로 설정도 바꾸지 않습니다. 바탕 브랜치는 dev입니다. types.ts와 config.ts를 나누는 일이 아닙니다. 같은 목록을 넣는 다른 열린 PR은 없습니다.

라인 - src/claude/intercept/connect-proxy.ts startConnectProxy. .:443은 끝의 점을 지운 뒤 이름이 빈 글자가 됩니다. ..:443은 이름이 .만 남습니다. * / \ ? # @ % 검사에 안 걸립니다. 예외 없이 통과하고, 빈 이름의 비교 키는 :443입니다. "이상한 목록은 포트를 열기 전에 실패한다"와 다릅니다.

라인 - 같은 함수. 포트가 이미 쓰이면 돌려준 Promise가 실패합니다. 목록이 이상하면 함수가 그 자리에서 예외를 던집니다. try 안에서 await하면 잡힙니다. startConnectProxy(...).catch(...)만 하면 그 catch로는 안 들어갑니다. 테스트는 그 자리에서 던지는 쪽을 확인합니다.

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

src/claude/intercept/runtime.ts의 데스크톱 피커 프록시는 이 목록을 아직 받지 않습니다. 인증도 없습니다. 이 PR을 머지해도 그 프록시는 예전처럼 막힌 목적지가 없습니다. 작성자는 나중 연동에 쓸 재료라고 했고, PR은 초안입니다.

목록에 있는 이름도, interceptHosts에 있고 포트가 443이면 로컬 인증서로 끝냅니다. 바깥 서버로만 보내고 싶으면 두 칸을 같이 봐야 합니다.

맞춰 보는 것은 글자입니다. chatgpt.com:443과 그 서버의 IP, www가 붙은 이름, 다른 포트는 서로 다릅니다. IPv6도 2001:db8::1과 2001:db8:0:0:0:0:0:1은 다른 항목입니다. 이름을 허용하면, 그 순간 DNS가 알려 주는 주소로 연결합니다. IP를 못 박지는 않습니다.

이 댓글을 쓸 때 PR은 초안이었고, CI의 테스트 잡은 아직 줄에 서 있었습니다.

너의 추천

빈 이름과 점만 있는 이름은 포트를 열기 전에 거절하세요. 목록 오류를 포트 오류처럼 Promise 실패로 바꿀지, 지금처럼 그 자리에서 던질지 하나로 정하세요. 피커에 목록을 붙이는 코드는 이 PR에 넣지 마세요. 다른 PR은 닫지 마세요. 초안은 빈 이름을 막은 뒤에 유지하면 됩니다.

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

@luvs01 luvs01 changed the title feat(intercept): restrict CONNECT destinations for scoped consumers feat(intercept): scope CONNECT destinations and CA lifetime Sep 26, 2026
lidge-jun added a commit that referenced this pull request Sep 26, 2026
This batch leaves six non-GUI enhancements on the current `dev` base as one squashed commit per contributor PR. Idle Codex accounts can start a fresh five-hour window on a real request; the Windows tray gains Chinese text; CONNECT can enforce an exact destination allowlist and a shorter CA lifetime; an on-demand native queue helper gains cross-platform offline CI; Gemini video retains its agentic mode; and GJC model exports expose supported reasoning levels.

| PR | Change | Author |
| --- | --- | --- |
| #5949 | Idle five-hour window activation | codingbo; Terry Tan credited for earlier overlapping work |
| #5884 | Windows tray Chinese localization | Yum-wu |
| #5934 | CONNECT destination allowlist and CA lifetime option | luvs01 |
| #5829 | On-demand native queue helper and offline workflow | luvs01; Epinephrine |
| #4663 | Gemini agentic video passthrough | Abhishek Sharma |
| #5431 | GJC reasoning controls in model exports | 이재현 |

Integration commit `116cc6c37c` documents GJC's exported effort controls in the English guide and all seven translated guides. Commit `b93e2524b5` updates the older GJC schema guard for those exported fields; commit `b900ce73c1` fixes the queue helper's help-probe watchdog and adds a timing regression. No file under `gui/` changed.

**Left out:** #5893 was reverted in `5a96cade33` and remains open. Its macOS system-proxy exceptions (`*.local` and CIDR ranges) were copied into `NO_PROXY`, but Bun fetch does not honor those patterns; a populated lowercase `no_proxy` can also override the merged value. It needs translation or CIDR routing across transports and a proxy-contact regression before integration.

Review the remaining security-sensitive diff at `src/codex/routing.ts` and `src/codex/routing/idle-window.ts` (account selection), `src/claude/intercept/connect-proxy.ts` and `local-ca.ts` (CONNECT policy and certificates), `src/adapters/google.ts` (video URI forwarding), and `.github/workflows/codex-queue-helpers.yml` plus `scripts/codex-queue.sh` and `.ps1` (workflow permissions and explicit message destination). The new workflow grants `contents: read`, pins checkout to a full SHA, disables credential persistence, and runs the Node test on Linux, macOS and Windows. Independent review of the revised head is pending before merge.

Co-authored-by: codingbo <cnsdbo@163.com>
Co-authored-by: Terry Tan <tmy1995hflc@gmail.com>
Co-authored-by: Yum-wu <1172989563@qq.com>
Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>
Co-authored-by: Epinephrine <luvs01@hanmail.net>
Co-authored-by: Abhishek Sharma <abhicse24@gmail.com>
Co-authored-by: 이재현 <wingwogus@naver.com>
@lidge-jun

Copy link
Copy Markdown
Owner

Thanks! This landed on dev through enhancement merge train batch 10A, #5988 (merge 1972cdb). Your change is one commit on dev with you as the author and a Co-authored-by trailer. Closing since the content is now on dev.

@lidge-jun lidge-jun closed this Sep 26, 2026
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.

2 participants