fix(audit): 전수조사 버그 수정 — 코어/보안/플랫폼 + 코드리뷰 발견 교정 - #176
Merged
Conversation
전수조사 확정 버그 중 코어(CEF-free) 계층 일괄 수정. `zig build test` 통과.
보안(high):
- fs 게이트 symlink confused-deputy 차단 — lexical 통과 후 realpath 정규화로
allowedRoots 재검사(path·root 양쪽 정규화로 macOS /tmp→/private/tmp 회귀 방지,
realpath 불가 시 lexical 유지). main.zig isPathAllowedForFrontend/rendererPathAllowed.
- plugin 권한 에스컬레이션 — coreInvoke 가 current_invoker 미갱신해 중첩 크로스콜이
발신자 권한으로 평가되던 것을 public invoke 와 동형으로 갱신. loader.zig.
- updater 빈 sha256 무검증 우회 + redirect 다운그레이드 — 원격(http/https) 다운로드에
sha256 강제(Sha256Required)로 둘을 함께 차단(file:// 면제). auto_updater.zig.
high/medium:
- 핫 리로드 후 자동 라우팅 영구 차단 — clearRoutesFor 가 ""센티널 대신 엔트리 제거.
- coreInvoke UAF — dlclose 중 use-after-unmap 방지(외부 스레드만 공유락, 재진입은
threadlocal flag 로 nested-shared 데드락 회피).
- EventBus.off TOCTOU UAF — inflight 배리어를 스냅샷과 같은 mutex 구간에서 증가.
- EventBus 64개 캡 무발화 + once>64 영구손실 — 스냅샷 힙 폴백 + 발화범위만 once 제거.
- EventBusSink.offCancelable inflight 배리어 추가(events.zig 동형).
- embed set_permissions fail-open — 정책 빌드 성공 시에만 스왑(parse/OOM 시 기존 유지).
- config 비-객체 JSON 패닉 가드 / 빈 backends:[] 무음폐기 / dupeStr OOM sentinel 보존.
- shell.openExternal file:// 을 PATH 게이트로(percent-encoding 거부).
- updater app 포맷 sha256 스킵(.app=디렉토리) / PowerShell single-quote 이스케이프 /
POSIX quit-install PID 재사용 30s 상한.
- plugin sanitizeSource 캐시 디렉토리 충돌 — source 64bit 해시 접미사.
low(누수/correctness):
- coreFree {}/"" 힙 응답 누수(포인터 동일성 식별) / registerEmbedRuntime 키 누수.
- util unescapeJsonStr \uXXXX 비표준(+/_) 거부 + NUL 경로 거부 + 플랫폼 separator.
회귀 가드(watcher_test/util test)를 고친 동작에 맞게 갱신.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…/packaging CEF·임베드 런타임 계층 버그 일괄 수정. zig build + zig build test 통과(macOS). 메모리/누수: - cef_session_cookies: setCefString UTF-16 버퍼 미해제(set/remove/get 호출마다 누수) → clearCefString(cef_util 공용 헬퍼 신설) 으로 해제. proxy 와 대칭. - cef_session_proxy: setProxyOnUi 의 CEF alloc 실패 에러 경로 dict/value ref 누수 → consume 이전 경로만 releaseRefCounted. - cef_tray: setMenu 가 createMenu(alloc/init +1)를 setMenu: 후 release 안 해 메뉴 트리 통째 누수 → 반납(상태 아이템 단독 소유). - cef_page_output: capturePage early-return/pool-full 시 deferred 슬롯 누수 + 렌더러 Promise hang → 슬롯 회수 + 실패 발화. printToPDF cef_path 누수 해제 + 미지원 시 발화. correctness: - cefCompletePending 에 browser_handle 매칭 추가 — 동일 path 의 cross-window capture 응답 오라우팅 방지(capture=handle, PDF=글로벌이라 0=기존 동작). - cef_clipboard availableFormats: 콤마를 루프 인덱스가 아닌 wrote 플래그로(선행/이중 콤마 malformed JSON 제거) + 오버플로 시 ']' best-effort. - python.zig: tupleStr/tupleObj 가 예외 set 한 채 유효 객체 반환 → SystemError. PyErr_Clear 추가. pyInvoke 비-UTF-8 응답 NULL → 에러 JSON 폴백. pyOn/luaOn id==0 등록 실패 시 listener 롤백(누수 + shutdown off(0) 방지). 동시성: - cef_session_cookies: ensureCookieVisitorPool 비원자 lazy init race → double-checked locking(atomic spinlock). 보안/로버스트(저위험분): - cef_auth_handler: escape 버퍼 overflow→silent CEF 기본 fallback → 입력 최악 6배로 확장(cert-error/login/client-cert). client-cert MAX_CERTS 16→32 + totalCertCount 통지. packaging(Linux): - tar.gz sentinel/backends 가 exe(stage/bin)보다 한 단계 위에 배치돼 런타임이 못 찾던 것 → stage/bin 으로. CEF 런타임 .so 미동반(clean 머신 실행 불가) → copyDirContents 로 동반(Windows 패턴).⚠️ 런타임은 Linux CI 검증 필요. - bundle_macos libnode/libpython 버전 하드코딩 ↔ build.zig 단일 출처 drift → python_test 에 CI 드리프트 가드(bump 가 bundle 빠뜨리면 실패). 보류(docs/audit-windows-followups.md): Windows globalShortcut slots race(comptime-prune 검증 불가), auth deferred 콜백 navigation 정리/disable-중-drain(헤드리스 검증 불가 + UAF 위험). plugin permission cmd-vs-name 게이트(권한 모델 의도 확인 필요). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
전수조사 수정 diff 를 9-앵글 max-effort 리뷰(find→verify→sweep) → 확정 버그 교정. zig build + zig build lib + zig build test 통과. 수정한 회귀/버그(리뷰가 잡은 것): - lua.zig: luaOn id==0 롤백이 destroy(listener) 후 listener.id 를 읽던 UAF(HIGH) — 로컬 lid 사용 + 롤백 분기에서 0 푸시·early-return(python 패턴 정렬). - main.zig shellOpenExternalGate: file:// 가 shell.allowedPaths 미설정 시 path 게이트의 legacy-allow 로 무게이트 통과하던 보안 회귀(HIGH) — allowedPaths 설정 시에만 path 게이트, 미설정이면 URL 게이트 폴백. Windows file:///C: 드라이브 경로 선행 '/' 보정. - main.zig canonicalizePath: rdir 이 max_path_bytes 를 채우면 join bufPrint overflow → null → realPathWithinRoots fail-to-lexical 로 symlink 검사 우회(HIGH) — join 제거, 부모 디렉토리 canonical 만 반환(base 는 traversal 없는 단일 컴포넌트). - embed.zig: 모바일 permission_check shell_open_external 이 file:// 를 path 게이트로 라우팅 안 해 allowedExternalUrls 미설정 시 무제약(HIGH) — 데스크톱 게이트 미러링. - loader.zig coreInvoke: embed_runtimes(Node/Lua/Python) 경로가 current_invoker 미갱신 → 중첩 크로스콜 권한이 잘못된 발신자로 평가(MED) — dlopen 경로 동형 갱신. - cef_page_output.zig: printToPDF/capturePage early-return 의 동기 emit 은 deferred 등록 *이전* 이라 무효 + 스퓨리어스 이벤트 — 제거(누수 수정 cef_path/슬롯은 유지). 극단 엣지의 deferred hang 근본 수정(vtable bool 전파)은 후속 문서화. NOTE(재설계 필요, docs/audit-windows-followups.md C): page_output 엣지 hang, EventBusSink 교차 리스너 UAF(events.zig 동일 패턴), 핫리로드 충돌-센티널 잔존, PDF cross-window 상관(글로벌 콜백 제약). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
3차 커밋(리뷰 수정분)을 집중 재리뷰 → 확정 회귀 교정. build/lib/test 통과. - main.zig realPathWithinRoots: canon_root 를 canonicalizePath(부모 폴백)가 아니라 realPathInto 만으로 구함(MED 회귀) — allowedRoot 디렉토리가 미존재 시 부모로 폴백해 canon_root 가 한 단계 얕아져(예: ~/Documents/myapp 미생성 → ~/Documents) 허용 범위가 넓어지던 것 차단. 존재=canonical / 미존재=lexical 원본(이때 canon_path 도 미존재 체인 이라 fail-to-lexical 로 불일치 없음). - cef_page_output.zig: capturePage 슬롯 풀-full 의 동기 emit 도 제거(deferred 등록 전 이라 무효 — 앞서 제거한 두 경로와 일관). 근본 해결은 C.1 후속. - embed.zig: file:// 게이트 주석 정확화 — embed 는 모바일(POSIX) 전용이라 데스크톱 Windows 드라이브 보정 불요(게이트 의미는 동형). 재리뷰의 나머지(lua 롤백=검증자 '정확' 판정, embed/main Windows 드라이브 비대칭·UNC 엣지=Windows 정직경계, loader span 수명=호출 구간 유효)는 무조치. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
개요
전 기능 전수조사(문서 싱크 / 구현 패리티 / 버그)를 수행하고, 확정된 버그를 수정했습니다. 다단계 적대적 검증(find → verify)으로 109개 발견을 추렸고, 확정 버그 ~47개 중 검증 가능한 것을 수정, 검증 불가/재설계 필요 항목은 문서화했습니다. 수정 diff 자체도
/code-review max(9 앵글)로 재검토해 수정 과정에서 도입한 버그 6건을 다시 교정했습니다.zig build+zig build lib+zig build test모두 통과(실제 실패 0).커밋
주요 수정 (보안)
/tmp→/private/tmp회귀 방지). 리뷰 후 join overflow→fail-open 우회도 교정(부모 canonical만 반환).coreInvoke가current_invoker미갱신해 중첩 크로스콜이 잘못된 발신자로 평가되던 것을 dlopen·embed 경로 모두 갱신.file://게이트 — 로컬 파일은allowedPaths설정 시 PATH 게이트, 미설정이면 URL 게이트 폴백(리뷰가 잡은 legacy-allow 무게이트 회귀 교정). 데스크톱·모바일(embed) 동형.주요 수정 (메모리/동시성/로직)
핫리로드 라우팅 영구차단 · coreInvoke UAF · EventBus.off TOCTOU UAF · 64개 캡 무발화+once 손실 · embed set_permissions fail-open · config 패닉/빈backends/dupeStr · session 쿠키 UTF-16 누수+init race · proxy ref 누수 · tray NSMenu 누수 · capturePage/printToPDF 슬롯 누수 · cross-window 오라우팅 · clipboard malformed JSON · python/lua(PyErr_Clear/UTF-8/id==0 UAF) · plugin 캐시 충돌 · Linux 패키징(sentinel 위치 + CEF .so 동반) · bundle_macos 버전 드리프트 가드.
코드리뷰가 잡은 회귀 (3차에서 교정)
on()id==0 롤백 UAF (destroy 후 listener.id 읽기)file://게이트 legacy-allow 무게이트 회귀의도적 보류 (
docs/audit-windows-followups.md)검증 불가/재설계 필요로 본 PR 범위 밖:
오탐
NUL byte DoS 1건은 검증 시 상류 2겹 가드 발견해 실재하지 않음으로 판정, 수정 안 함.
🤖 Generated with Claude Code