콘텐츠로 이동
OmniRoute source

Socket.dev / supply-chain finding attestation (한국어)

소스 파일:

  • src/mitm/cert/install.ts — 공개 installCert() / uninstallCert(), 플랫폼별 installCertWindows/Mac/Linux.
  • src/mitm/systemCommands.ts — 설치 경로에서 사용하는 공통 execFile / spawn / PowerShell 헬퍼.

트리거: 사용자가 /dashboard/cli-tools/mitm의 로컬 대시보드에서 “MITM 프록시 활성화”를 클릭합니다. 이 라우트는 루프백 전용입니다 — CLAUDE.md의 엄격한 규칙 #17과 src/server/authz/routeGuard.ts::isLocalOnlyPath()를 참조하십시오. 터널을 통해 노출된 JWT로는 이 코드 경로를 트리거할 수 없습니다.

수행되는 권한 작업(플랫폼별):

OS 명령
Windows UAC를 통한 certutil -addstore Root <cert>
macOS sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain <cert>
Linux sudo cp <cert> <distro-trust-dir> + sudo update-ca-certificates (Debian) / sudo update-ca-trust (RHEL/SUSE)
Linux+Firefox/Chromium certutil -d sql:<profile>을 통한 프로필별 NSS DB 업데이트

이 명령들은 mitmproxy, Charles Proxy, Fiddler 및 Caddy에서 사용하는 것과 동일한 명령입니다. OmniRoute에 이러한 명령이 존재한다는 사실은 docs/security/STEALTH_GUIDE.md에 문서화되어 있습니다.

v3.8.6 완화 조치:

  • runElevatedPowerShell()은 더 이상 -EncodedCommand <base64utf16le>을 사용하지 않습니다. 권한 상승 페이로드는 호출별 임시 .ps1 파일(모드 0o600, 비공개 mkdtempSync 디렉터리 내부)에 기록되고 -File을 통해 참조됩니다. 이 파일은 finally에서 링크 해제됩니다. 이를 통해 Socket.dev의 AI 분류기가 플래그한 전형적인 PowerShell을 통한 base64 권한 상승 핑거프린트를 제거합니다.
  • installCertWindows에는 이 문서를 가리키는 인라인 SECURITY-AUDITOR-NOTE: 블록이 포함되어 있습니다.

유지하는 이유: MITM 프록시는 docs/security/STEALTH_GUIDE.md와 docs/frameworks/MITM-PROXY.md에서 사용하는 문서화된 기능입니다. 이를 제거하면 에이전트 브리지 기능 세트가 손상됩니다.


§2 — Zed 자격 증명 가져오기 (app/api/providers/zed/import/route.js)

섹션 제목: “§2 — Zed 자격 증명 가져오기 (app/api/providers/zed/import/route.js)”

소스 파일:

  • src/app/api/providers/zed/discover/route.ts (v3.8.6에서 새로 추가됨)
  • src/app/api/providers/zed/import/route.ts
  • src/lib/zed-oauth/keychain-reader.ts
  • src/lib/zed-oauth/credentialFingerprint.ts (v3.8.6에서 새로 추가됨)

트리거: 사용자가 로컬 대시보드의 Providers 페이지에서 “Import from Zed”를 클릭합니다. 엔드포인트는 requireManagementAuth로 보호됩니다. Zed 편집기 자체는 문서화된 서비스 이름을 사용하여 공급자 API 키를 OS 키체인에 기록합니다. 자세한 내용은 https://zed.dev/docs/ai/llm-providers 를 참조하세요.

v3.8.5 동작(Socket.dev가 플래그한 버전):

POST /import는 자격 증명을 검색하고 한 번의 요청으로 로컬 SQLite 저장소에 자동 저장했습니다. 계정별 확인이나 지문 없이 단순히 “N개의 토큰을 찾았으며 모두 가져왔습니다.“라고 처리했습니다.

v3.8.6 완화 조치 — 2단계 확인:

  1. **POST /api/providers/zed/discover**는 { candidates: [{ provider, service, account, fingerprint }] }를 반환합니다. 원본 토큰은 절대 전송되지 않습니다. 지문은 sha256(service|account|token).slice(0,16)입니다.
  2. 대시보드는 후보 목록을 렌더링하고, 운영자는 가져올 항목을 선택한 다음 { confirmedAccounts: [{ service, account, fingerprint }] }를 **POST /api/providers/zed/import**로 전송합니다.
  3. 가져오기 엔드포인트는 서버에서 키체인을 다시 읽고 (service, account, fingerprint)를 기준으로 필터링합니다. 변조되거나 재전송된 검색 응답이 가져오기 엔드포인트를 속여 관련 없는 토큰을 저장하도록 할 수 없습니다. 검색 이후 실제 토큰이 변경되었다면 지문이 더 이상 일치하지 않으므로 해당 자격 증명을 건너뜁니다.

OMNIROUTE_ZED_IMPORT_LEGACY_ONE_STEP=true 환경 변수 플래그는 아직 자동화를 업데이트하지 않은 운영자를 위해 v3.8.5 동작을 유지합니다. 이 플래그는 v3.9에서 제거될 예정입니다.

유지하는 이유: Zed 가져오기는 이미 Zed를 사용 중이며 공급자 키를 다시 붙여 넣지 않고 OmniRoute에 복제하려는 사용자를 위한 가장 편리한 온보딩 경로입니다.


§3 — execFile / spawn / 권한 상승 PowerShell (21843.js)

섹션 제목: “§3 — execFile / spawn / 권한 상승 PowerShell (21843.js)”

소스 파일: src/mitm/systemCommands.ts.

플래그된 이유: 이 청크는 execFileWithPassword, runElevatedPowerShell 및 공유 quotePowerShell 헬퍼를 다시 내보냅니다. Socket.dev의 AI 분류기는 이를 범용 “호스트 실행 + 권한 상승 툴킷”으로 인식합니다. OmniRoute 내에서는 MITM 인증서 설치 경로(§1)와 sudo 명령 실행을 위한 execFileWithPassword에서만 사용됩니다.

v3.8.6 완화 조치:

  • runElevatedPowerShell 리팩터링(§1 참조).
  • runElevatedPowerShell과 execFileWithPassword 양쪽의 인라인 SECURITY-AUDITOR-NOTE: 블록은 허용 목록에 등록된 호출자와 고정된 실행 파일 목록을 문서화합니다.
  • execFileWithPassword의 spawn() 호출에는 이 헬퍼가 전달받을 수 있도록 허용된 실행 파일 목록과 함께 nosemgrep 마커가 포함됩니다. 사용자 입력에서 finalCommand/finalArgs로 이어지는 경로는 없습니다.

§4 / §6 — 9router 서비스 감독자 (api/services/9router/{start,restart}/route.js)

섹션 제목: “§4 / §6 — 9router 서비스 감독자 (api/services/9router/{start,restart}/route.js)”

소스 파일:

  • src/app/api/services/9router/_lib.ts — 감독자 팩터리.
  • src/app/api/services/9router/{start,stop,restart,status,install,update,auto-start}/route.ts.
  • src/lib/services/ServiceSupervisor.ts — 범용 프로세스 생성 / 상태 폴링 / 로그 버퍼.

트리거: 사용자가 로컬 대시보드의 내장 서비스 페이지에서 “Install” / “Start”를 클릭합니다.

이미 적용된 보호 조치:

  • src/server/authz/routeGuard.ts에 따라 모든 /api/services/* 경로는 LOCAL_ONLY입니다(하드 규칙 #17). 루프백 적용은 모든 인증 검사보다 먼저 이루어지므로 유출된 JWT로도 해당 경로에 접근할 수 없습니다.
  • 9router DB 행은 status='not_installed', auto_start=0으로 시드됩니다(src/lib/db/migrations/071_services.sql:19 참조). 서비스는 최초 실행 시 시작되지 않습니다.
  • spawn()은 src/lib/services/installers/ninerouter.ts의 resolveSpawnArgs(apiKey, PORT)가 반환한 바이너리 경로로 호출되며, 이는 지원되는 바이너리의 고정된 허용 목록입니다.
  • Stdout/stderr는 메모리에 버퍼링됩니다(5 MB 제한, _lib.ts 참조). 사용자가 대시보드에서 로깅을 활성화하지 않는 한 디스크에는 기록되지 않습니다.

v3.8.6 완화 조치: 기능 변경은 없습니다. 최소 빌드 프로필 (OMNIROUTE_BUILD_PROFILE=minimal)은 권한이 필요한 경로를 번들에서 물리적으로 제거하려는 사용자를 위해 src/lib/services/installers/ninerouter.ts를 스텁으로 대체합니다.

유지하는 이유: 9router는 선택적으로 로컬에 설치할 수 있는 동반 서비스(WordPress 스타일 플러그인과 유사)이며, 엄격한 옵트인 방식입니다.


§5 — OmniRoute Cloud Sync 자격 증명 다시 쓰기 (api/keys/[id]/route.js)

섹션 제목: “§5 — OmniRoute Cloud Sync 자격 증명 다시 쓰기 (api/keys/[id]/route.js)”

소스 파일:

  • src/lib/cloudSync.ts — syncToCloud() / updateLocalTokens().
  • src/app/api/keys/[id]/route.ts — syncKeysToCloudIfEnabled()를 호출합니다.

트리거: isCloudEnabled()가 true를 반환하고(대시보드에서 설정) CLOUD_URL도 구성된 경우입니다. 둘 다 비활성화된 경우에는 Cloud 엔드포인트로 외부 네트워크 호출이 이루어지지 않습니다.

v3.8.5 동작(Socket.dev가 정확히 포착한 버그):

updateLocalTokens()는 cloudUpdatedAt > localUpdatedAt일 때 Cloud 응답의 accessToken, refreshToken, providerSpecificData로 기존 값을 덮어썼습니다. HMAC도, 서명도, 체크섬도 없었습니다. 잘못 구성되었거나 악의적인 CLOUD_URL(또는 채널상의 MITM)이 공급자 OAuth 토큰을 은밀하게 바꿀 수 있었습니다.

v3.8.6 완화 조치:

  1. HMAC 검증: verifyCloudSignature(rawBody, sigHeader)는 JSON을 파싱하기 전에 X-Cloud-Sig 헤더(HMAC-SHA256(OMNIROUTE_CLOUD_SYNC_SECRET, rawBody))를 확인합니다. 비밀 값이 설정되어 있으면 서명이 필수입니다. 설정되어 있지 않으면(레거시 모드) 경고를 기록하고 응답을 수락합니다. 단, v3.9부터는 비밀 값이 필수가 됩니다.
  2. 비밀 필드 옵트인: accessToken / refreshToken / providerSpecificData는 OMNIROUTE_CLOUD_SYNC_SECRETS=true인 경우에만 덮어씁니다. 기본 모드에서는 자격 증명이 아닌 메타데이터(expiresAt, status, lastError*, rateLimitedUntil, updatedAt)만 동기화합니다. 이는 원격 토큰 동기화에 의존하던 사용자에게 호환성을 깨뜨리는 변경 사항이며, 해당 사용자는 명시적으로 옵트인해야 합니다.

이 기능을 유지하는 이유: Cloud Sync는 OmniRoute Cloud 테넌트가 팀 자격 증명을 중앙에서 관리할 수 있는 유일한 방법입니다. 이 수정으로 위협 모델이 다음과 같이 명확해집니다. “서버는 서명하고, 클라이언트는 검증하며, 운영자는 옵트인한다.”


Socket 친화적인 아티팩트가 필요한 사용자는 다음과 같이 빌드하십시오.

터미널 창
OMNIROUTE_BUILD_PROFILE=minimal npm run build

webpack NormalModuleReplacementPlugin은 네 개의 모듈을 스텁에 별칭으로 연결합니다.

모듈 스텁
src/mitm/cert/install.ts src/mitm/cert/install.stub.ts
src/lib/zed-oauth/keychain-reader.ts src/lib/zed-oauth/keychain-reader.stub.ts
src/lib/cloudSync.ts src/lib/cloudSync.stub.ts
src/lib/services/installers/ninerouter.ts src/lib/services/installers/ninerouter.stub.ts

각 스텁은 동일한 인터페이스를 내보내지만, 모든 함수는 런타임에 featureDisabledError(name)를 발생시킵니다. 비활성화된 모듈에 의존하는 라우트는 민감한 코드 경로를 활성화하는 대신 명확한 메시지와 함께 HTTP 503을 반환합니다.

생성된 번들은 omniroute-secure로 게시하기 위한 것입니다. 게시 절차는 docs/ops/PUBLISHING_SECURE.md를 참조하십시오.


장기적으로는 npm package를 개별적으로 감사할 수 있는 모듈로 분리할 계획입니다. 관련 추적 이슈는 GitHub 이슈 트래커의 v4 마일스톤을 참조하세요.


OmniRoute 소스 코드 (a58000c7685f)

HagiCode

HagiCode는 구조화된 워크플로, 다중 에이전트 실행, Hero Dungeon 뷰를 갖춘 에이전트 코딩 작업 공간입니다.

더 스마트하고 빠르며 즐거운 에이전트 워크플로로 유용한 소프트웨어를 만드세요.

HagiCode 라이트 테마 메인 화면
  • Smart구조화된 워크플로는 의도를 아이디어부터 배포까지 실행 가능한 경로로 바꿉니다.
  • Efficient다중 에이전트 워크플로로 조사, 구현, 검토를 병렬로 진행합니다.
  • FunHero Dungeon은 긴 코딩 세션을 시각적이고 협업적인 경험으로 만듭니다.
HagiCode 방문