요약
Windows에서 cxc provider(및 SessionStart provider-bridge 훅)가 정상 동작 중인 opencodex를 항상 mode: "error"로 보고한다. ocx 프록시는 건강한데 detect 단계에서 실패한다.
환경
- Windows 11 / PowerShell
- Node v24.16.0
- codex 0.135.0
- codexclaw 0.2.24+codex.20260908031619 (dev, 9cd5276)
- opencodex: npm 전역 설치 (
C:\nvm4w\nodejs)
재현
$ cxc provider
{"provider":"ocx","mode":"error","ocxPath":"C:\\nvm4w\\nodejs\\ocx","reason":"ocx status exited null"}
$ ocx status
✅ Proxy: running (PID 11208)
Health: http://127.0.0.1:10100/healthz ok (live)
routing=opencodex-local, service=installed-but-unhealthy, shim=absent
원인
components/provider-bridge/src/cli.ts 두 군데가 겹친다.
1. whichOcx()가 where ocx 출력의 첫 줄을 그대로 쓴다.
npm 전역 설치는 확장자 없는 sh shim과 .cmd 런처를 같이 깔고, where는 확장자 없는 쪽을 먼저 내놓는다.
$ where.exe ocx
C:\nvm4w\nodejs\ocx
C:\nvm4w\nodejs\ocx.cmd
확장자 없는 파일은 Windows에서 실행 가능한 이미지가 아니라 spawnSync가 ENOENT로 실패한다.
2. .cmd를 골라도 그대로는 실패한다.
Node 18.20.2 / 20.12.2 이후(CVE-2024-27980) .cmd와 .bat은 shell 옵션 없이 spawn하면 EINVAL이다.
두 경우 모두 res.status === null이 되어 detect.ts:82의 ocx status exited ${result.status ?? "null"} 분기로 떨어진다.
검증
node -e "spawnSync(p, ['status','--json'])"
C:\nvm4w\nodejs\ocx status=null err=ENOENT stdoutLen=0
C:\nvm4w\nodejs\ocx.cmd status=null err=EINVAL stdoutLen=0
C:\nvm4w\nodejs\ocx.cmd (shell:true) status=0 err=undefined stdoutLen=3931
.cmd + 셸 경유일 때만 status --json 페이로드가 정상적으로 돌아온다.
영향
- Windows + npm 설치 opencodex 조합에서는 provider 모드로 진입할 수 없다. 항상 error.
- SessionStart 훅의 provider 상태 줄과 이를 소비하는 카탈로그(L25) / GUI(L27)가 건강한 프록시를 error로 인식한다.
mode: "native" 폴백도 아니라서 "감지는 됐는데 읽지 못함"으로 잘못 보고된다. 사용자 입장에서는 원인 파악이 어렵다.
제안
whichOcx(): win32에서 where 출력의 여러 줄 중 PATHEXT에 포함된 확장자(.cmd, .exe, .bat)를 우선 선택한다.
runOcxStatus(): win32에서 대상이 .cmd/.bat이면 ComSpec을 경유해 실행한다. spawnSync(process.env.ComSpec, ["/d","/s","/c", quoted]) 형태가 안전하다. shell: true에 args를 넘기는 방식은 DEP0190 경고와 인용 문제가 따라온다.
- 회귀 테스트:
which가 확장자 없는 경로를 먼저 반환하는 케이스와 .cmd EINVAL 케이스를 detect deps 주입으로 커버한다.
detect-only 계약(Q-P2-2)은 그대로 유지된다. 실행 경로 해석만 고치면 된다.
요약
Windows에서
cxc provider(및 SessionStart provider-bridge 훅)가 정상 동작 중인 opencodex를 항상mode: "error"로 보고한다. ocx 프록시는 건강한데 detect 단계에서 실패한다.환경
C:\nvm4w\nodejs)재현
원인
components/provider-bridge/src/cli.ts두 군데가 겹친다.1.
whichOcx()가where ocx출력의 첫 줄을 그대로 쓴다.npm 전역 설치는 확장자 없는 sh shim과
.cmd런처를 같이 깔고,where는 확장자 없는 쪽을 먼저 내놓는다.확장자 없는 파일은 Windows에서 실행 가능한 이미지가 아니라
spawnSync가 ENOENT로 실패한다.2.
.cmd를 골라도 그대로는 실패한다.Node 18.20.2 / 20.12.2 이후(CVE-2024-27980)
.cmd와.bat은shell옵션 없이 spawn하면 EINVAL이다.두 경우 모두
res.status === null이 되어detect.ts:82의ocx status exited ${result.status ?? "null"}분기로 떨어진다.검증
.cmd+ 셸 경유일 때만status --json페이로드가 정상적으로 돌아온다.영향
mode: "native"폴백도 아니라서 "감지는 됐는데 읽지 못함"으로 잘못 보고된다. 사용자 입장에서는 원인 파악이 어렵다.제안
whichOcx(): win32에서where출력의 여러 줄 중 PATHEXT에 포함된 확장자(.cmd,.exe,.bat)를 우선 선택한다.runOcxStatus(): win32에서 대상이.cmd/.bat이면 ComSpec을 경유해 실행한다.spawnSync(process.env.ComSpec, ["/d","/s","/c", quoted])형태가 안전하다.shell: true에 args를 넘기는 방식은 DEP0190 경고와 인용 문제가 따라온다.which가 확장자 없는 경로를 먼저 반환하는 케이스와.cmdEINVAL 케이스를 detect deps 주입으로 커버한다.detect-only 계약(Q-P2-2)은 그대로 유지된다. 실행 경로 해석만 고치면 된다.