한국어

Codex Security TypeScript SDK

TypeScript에서 Codex Security 스캔을 실행하고, 대상과 제공업체를 선택하고, 결과를 검사하고, 스캔 수명 주기를 관리합니다.

Codex Security TypeScript SDK를 사용하여 애플리케이션 또는 개발자 도구에서 리포지토리와 코드 변경 사항에 대한 보안 스캔을 실행하세요. SDK는 형식이 지정된 발견 항목, 커버리지 세부 정보 및 스캔 아티팩트 경로를 반환합니다. 장시간 스캔을 위해 사전 검사, 비용 한도, 진행 상황 콜백 및 취소도 지원합니다.

SDK는 ECMAScript 모듈(ESM)을 사용하며 Node.js 22 (22.13.0 이상), 24 또는 26을 사용하는 서버 측에서 실행됩니다. 스캔에는 Python 3.10 이상도 필요합니다. Python 3.10에는 tomli 패키지도 필요합니다.

SDK 설정하기

SDK를 설치하세요.

npm install @openai/codex-security

스캔을 시작하기 전에 OPENAI_API_KEY 또는 CODEX_API_KEY를 설정하거나, 파일 기반의 기존 Codex 로그인을 사용하거나, 다른 제공업체를 구성하세요. Amazon Bedrock은 AWS 자격 증명을 사용하며, OpenRouter와 Fireworks는 제공업체별 API key와 구성을 사용합니다.

최상의 결과를 얻으려면 Trusted Access for Cyber 인증을 받은 계정을 사용하세요. 로그인하거나 API key를 제공해도 Trusted Access가 부여되지는 않습니다.

스캔 실행하기

신뢰하고 평가 권한이 있는 리포지토리만 스캔하세요. SDK는 로컬 운영 체제 권한으로 실행되며 승인을 기다리지 않습니다. 스캔 프로세스는 환경을 상속할 수 있으므로 시작하기 전에 관련 없는 자격 증명을 제거하세요. 로컬 스캔 권한을 참조하세요.

CodexSecurity 클라이언트 하나를 만들고, 표준 리포지토리 스캔을 실행한 후 작업이 완료되면 클라이언트를 닫으세요. 이를 포함하는 Git 작업 트리 외부의 비공개 결과 디렉터리를 선택하려면 outputDir를 전달하세요.

outputDir를 생략하면 Codex Security는 자체 영구 상태 디렉터리에 결과를 저장합니다. 결과에는 소스 코드 발췌문과 취약점 세부 정보가 포함될 수 있으므로 적절한 권한과 보존 정책을 선택하세요.



const security = new CodexSecurity();

try {
  const result = await security.run("/path/to/repository", {
    outputDir: "/path/outside/repository/results",
  });

  console.log(result.reportPath);
  console.log(result.coverage.completeness);
  console.log(result.findings.findings.length);
} finally {
  await security.close();
}

run은 스캔을 시작하고 완료될 때까지 기다린 다음, 봉인된 아티팩트를 검증하고 ScanResult를 반환합니다. close는 격리된 런타임을 해제하며 반복 호출을 지원합니다.

사전 검사로 입력 확인하기

스캔을 시작하기 전에 preflight를 사용하여 리포지토리, 대상, 모드, 지식 베이스 문서, 출력 위치 및 Codex 구성을 확인하세요.

const plan = await security.preflight("/path/to/repository", {
  target: ["services/billing", "packages/auth"],
  knowledgeBasePaths: ["/path/to/architecture.md"],
  outputDir: "/path/outside/repository/results",
});

console.log(plan.repository);
console.log(plan.target.kind);
console.log(plan.mode);
console.log(plan.outputDir);

사전 검사는 Codex 런타임과 자격 증명을 변경하지 않습니다. 또한 플러그인과 Python 검색은 스캔 자체에서 수행하도록 남겨 둡니다. 따라서 장시간 실행되거나 자격 증명이 필요한 작업 전에 사용자 입력을 확인하는 데 유용합니다.

기존 결과 디렉터리의 보관을 미리 보려면 archiveExisting: true를 설정하세요.

const plan = await security.preflight("/path/to/repository", {
  outputDir: "/path/outside/repository/results",
  archiveExisting: true,
});

console.log(plan.archiveDir);

반환된 archiveDir는 보관 파일 이름을 미리 보여 줍니다. run이 자체적으로 고유한 대상을 생성하므로 최종 경로는 달라질 수 있습니다. 실제 보관 경로는 onOutputArchived를 사용하여 캡처하세요.

await security.run("/path/to/repository", {
  outputDir: "/path/outside/repository/results",
  archiveExisting: true,
  onOutputArchived(archiveDir) {
    console.log("Archived results:", archiveDir);
  },
});

스캔은 이전 결과를 보관하고 빈 출력 디렉터리에서 시작합니다.

스캔 대상 선택하기

SDK는 리포지토리, 경로, 커밋된 diff 및 작업 트리 대상을 지원합니다. 기본 대상은 전체 리포지토리입니다.

선택한 경로 스캔하기

리포지토리 내부 경로의 배열을 전달하세요.

const result = await security.run("/path/to/repository", {
  target: ["services/billing", "packages/auth"],
});

경로는 파일 또는 디렉터리를 지정할 수 있습니다. SDK는 각 경로를 리포지토리 내부에서 해석하고 중복을 제거합니다.

커밋된 변경 사항 스캔하기

DiffTarget.refs를 사용하여 로컬에서 사용할 수 있는 두 Git 리비전 사이의 커밋된 변경 사항을 스캔하세요.



const target = DiffTarget.refs({
  base: "origin/main",
  head: "HEAD",
});

const result = await security.run("/path/to/repository", { target });

헤드의 기본값은 HEAD입니다. Diff 대상에서는 리포지토리 인수가 Git 작업 트리 루트여야 합니다.

작업 트리 스캔하기

DiffTarget.workingTree를 사용하여 기준 리비전을 상대로 스테이징된 변경 사항과 스테이징되지 않은 변경 사항을 스캔하세요.

const target = DiffTarget.workingTree({ base: "HEAD" });
const result = await security.run("/path/to/repository", { target });

기준의 기본값은 HEAD입니다. diff 또는 작업 트리 스캔을 시작하기 전에 선택한 리비전을 가져오세요.

심층 모드 선택하기

더 폭넓은 검토가 필요한 리포지토리 또는 경로 스캔에는 mode: "deep"을 설정하세요.

const result = await security.run("/path/to/repository", {
  target: ["services/billing"],
  mode: "deep",
  workers: 2,
  subagents: 0,
  stopAfterNoNew: 3,
  maxDiscoveryRuns: 10,
  maxTimeHours: 1.5,
});

심층 모드는 리포지토리와 경로 대상을 지원합니다. diff 및 작업 트리 스캔에는 표준 모드를 사용하세요. 선택적 설정은 동시에 실행되는 독립적인 표준 스캔 작업자 수, 작업자당 하위 에이전트 수, 새로운 발견 항목 없이 연속으로 완료되는 작업자 스캔 수, 작업자 실행의 총 횟수와 기간을 제어합니다. 이 설정에는 mode: "deep"이 필요합니다.

maxTimeHours의 기본값은 96이며, 소수 시간을 포함해 96 이하의 양수를 허용합니다. 기한에 도달하면 Codex Security는 완료되지 않은 작업자를 중지하고, 완료된 스캔 결과를 유지하며, 이를 최종 보고서로 집계합니다. 시간 제한이 있는 스캔을 전체 커버리지의 증거로 간주하기 전에 result.coverage.completeness를 검토하세요.

보안 지식 베이스 추가하기

아키텍처 문서, 위협 모델 또는 보안 정책을 knowledgeBasePaths를 통해 전달하세요.

const result = await security.run("/path/to/repository", {
  knowledgeBasePaths: [
    "/path/to/architecture.md",
    "/path/to/security-policies",
  ],
});

SDK는 파일 또는 디렉터리를 허용하며 디렉터리를 재귀적으로 검색합니다. 지원되는 문서 형식은 .md, .markdown, .txt, .pdf.docx입니다. SDK는 링크된 입력 경로를 거부하고 링크된 디렉터리 항목을 건너뛰며, 추출된 문서 콘텐츠를 저장된 스캔 결과 외부에 유지합니다.

스캔 및 후속 작업 지침 추가하기

scanPrompt를 사용하여 스캔의 초점을 맞추고 postScanPrompt를 사용하여 후속 작업을 요청하세요.

const result = await security.run("/path/to/repository", {
  scanPrompt: "Focus on tenant isolation and authorization checks.",
  postScanPrompt: "Write confirmed findings to post-scan-summary.md.",
});

후속 작업이 실패하면 SDK는 완료된 스캔을 유지하고 onWarning을 통해 오류를 보고합니다. 후속 작업으로 변경된 완료된 스캔 아티팩트는 모두 복원됩니다.

스캔 예산 설정하기

예상 모델 비용이 한도를 초과할 때 스캔을 중지하려면 maxCostUsd를 설정하세요. 스캔 실행 중 비용을 추적하려면 onCost를 사용하세요.

const result = await security.run("/path/to/repository", {
  maxCostUsd: 5,
  onCost(cost) {
    console.log(cost.estimatedUsd);
  },
});

console.log(result.cost?.estimatedUsd);

한도는 지출을 추정하지만 엄격한 상한은 아니므로 이미 진행 중인 요청은 한도를 약간 초과하여 완료될 수 있습니다. Codex Security가 완료된 작업자 결과를 집계한 후 심층 스캔이 한도에 도달하면 runcoverage.completeness"partial"로 설정된 결과를 반환하고 onWarning을 통해 예산 경고를 보고합니다.

스캔에서 완료된 부분 결과를 생성할 수 없으면 runScanCostLimitExceededError를 throw하고 사용 가능한 출력을 보존합니다.

스캔 결과 활용하기

ScanResult는 구조화된 문서, 스캔 메타데이터 및 아티팩트 경로를 제공합니다.

속성 내용
manifest 대상, 범위, 생성자 및 아티팩트 레코드를 포함한 봉인된 스캔 매니페스트.
findings 현재 스캔의 발견 항목. findings.findings에서 발견 항목 객체를 읽습니다.
repositoryFindings 스캔 기록을 사용할 수 있을 때 리포지토리 스캔 전체의 미해결 발견 항목.
coverage 검토한 영역, 제외 항목, 보류된 작업, 미해결 질문 및 완전성.
scanDir 스캔 디렉터리.
threadId 스캔의 Codex 스레드 식별자.
turnResult 턴 상태, 응답 및 사용 가능한 사용량 메타데이터.
cost 예상 모델 및 토큰 비용. 사용할 수 없으면 null.
reportPath report.md의 경로.
manifestPath scan-manifest.json의 경로.
findingsPath findings.json의 경로.
coveragePath coverage.json의 경로.
artifactsDir 지원 아티팩트 디렉터리.
sarifPath 생성된 SARIF 경로. SARIF가 없으면 null.
pluginVersion 스캔 생성자가 기록한 버전.

이후 스캔에서 동일한 플러그인을 요구하려면 expectedPluginVersion: result.pluginVersion를 전달하세요. 설치된 플러그인 버전이 다르면 SDK가 스캔을 거부합니다.

구조화된 발견 항목과 커버리지를 직접 사용하세요.

for (const finding of result.findings.findings) {
  const location = finding.locations[0];
  if (location === undefined) continue;

  console.log(
    finding.severity.level,
    `${location.path}:${location.startLine}`,
    finding.title
  );
}

for (const deferred of result.coverage.deferred) {
  console.log(deferred.id, deferred.reason);
}

발견 항목에는 선택적 codeEvidence, rootCause, validation, attackPath, remediationTestspreventiveControls 필드가 포함될 수 있습니다.

리포지토리 전체 발견 항목의 경우 confirmedInLatestScan은 최신 스캔에서 확인된 발견 항목과 이전에 발견되어 여전히 미해결 상태인 항목을 구분합니다.

for (const finding of result.repositoryFindings ?? []) {
  console.log(finding.title, finding.confirmedInLatestScan);
}

커버리지 완전성은 complete, partial 또는 unknown입니다. 스캔을 보안 결정의 증거로 사용하기 전에 보류된 영역, 제외 항목 및 미해결 질문을 검토하세요.

result.toJSON()은 매니페스트, 리포지토리 및 현재 스캔의 발견 항목, 커버리지, 스캔 및 스레드 식별자, reportPath, artifactsDir, sarifPath, 비용 및 턴 메타데이터를 하나의 JSON 지원 객체로 반환합니다.

스캔 추적 또는 취소하기

스캔 시작, 작업자 진행 상황 및 연결 재시도를 보고하려면 ScanOptions 콜백을 전달하세요.

const result = await security.run("/path/to/repository", {
  outputDir: "/path/outside/repository/results",
  onScanStarted() {
    console.log("Scan started");
  },
  onProgress(progress) {
    console.log(progress.phase, progress.filesCompleted, progress.filesTotal);
  },
  onWorkerStatus(status) {
    console.log(status.kind, status);
  },
  onSessionEvent(session) {
    console.log(session.threadId, session.worker, session.event["type"]);
  },
  onReconnect(attempt, maxAttempts) {
    console.log(`Reconnect attempt ${attempt} of ${maxAttempts}`);
  },
  onObserverError(observer, error) {
    console.error(`${observer} failed`, error);
  },
});

console.log(result.reportPath);

요청, 작업 컨트롤러 또는 시간 초과로 취소할 때 AbortSignal을 전달하세요.



const controller = new AbortController();

try {
  const scan = security.run("/path/to/repository", {
    outputDir: "/path/outside/repository/results",
    signal: controller.signal,
  });

  controller.abort();
  await scan;
} catch (error) {
  if (error instanceof ScanInterruptedError) {
    console.error(error.scanDir);
  } else {
    throw error;
  }
}

중단된 스캔은 scanDir에 부분 출력을 남길 수 있습니다. 결과를 조사해야 한다면 해당 디렉터리를 보존하세요.

스캔 설정 진행 상황을 표시하는 애플리케이션에서는 ScanOptions 수명 주기 콜백도 사용할 수 있습니다.

콜백 호출 시점
onAuthentication(authentication) 스캔에서 인증 방법을 선택할 때.
onOutputArchived(archiveDir) 기존 결과가 보관 디렉터리로 이동할 때.
onOutputDirReady(scanDir) 비공개 스캔 디렉터리가 준비될 때.
onScanStarted() 스캔 설정이 완료되고 실행이 시작될 때.
onTrustedAccessStatus(status) Trusted Access 상태를 사용할 수 있게 될 때.
onReconnect(attempt, maxAttempts) SDK가 연결이 끊긴 스캔 스트림에 다시 연결할 때.
onActivity(activity) 명령, 도구, 추론 단계 또는 메시지가 업데이트될 때.
onProgress(progress) 스캔 단계 또는 검토한 파일 수가 변경될 때.
onWorkerStatus(status) 작업자의 사전 검사 또는 디스패치 상태가 변경될 때.
onSessionEvent(session) 스캔 또는 작업자 세션에서 이벤트가 발생할 때.
onCost(cost) 업데이트된 예상 스캔 비용을 사용할 수 있을 때.
onWarning(warning) 스캔에서 경고를 보고할 때.
onObserverError(observer, error) 다른 스캔 수명 주기 콜백에서 오류가 발생할 때.

Trusted Access 상태는 granted, not_granted 또는 unknown입니다. 액세스 권한이 없거나 알 수 없는 경우에도 onWarning이 트리거됩니다.

onSessionEvent는 수정되지 않은 이벤트를 수신하며 소스 코드나 자격 증명이 포함될 수 있습니다. 공유 로그나 다른 서비스로 보내기 전에 필터링하세요.

런타임 및 자격 증명 구성하기

특정 플러그인, 인터프리터 또는 Codex 설정이 필요할 때 런타임 구성을 전달하세요.

const security = new CodexSecurity({
  pluginPath: "/path/to/codex-security-plugin",
  pythonPath: "/path/to/python",
  codexOverrides: {
    model: "gpt-5.6-terra",
    model_reasoning_effort: "high",
  },
});

pluginPath는 플러그인 디렉터리 또는 ZIP을 허용합니다. pythonPath는 플러그인 인터프리터를 선택합니다. codexOverrides는 지원되는 값을 격리된 Codex 구성에 병합합니다. 스캔은 기본적으로 extra-high 추론 노력이 적용된 gpt-5.6-sol을 사용합니다. 다른 모델 또는 추론 노력을 사용하려면 codexOverrides에서 modelmodel_reasoning_effort를 설정하세요. Amazon Bedrock을 사용하려면 codexOverrides에서 model_providermodel을 설정하세요.

codexOverrides는 스캔의 파일 시스템 액세스를 제한하거나 승인 정책을 변경할 수 없습니다. 로컬 스캔 권한을 참조하세요.

OpenRouter 또는 Fireworks의 경우 일치하는 API key와 완전한 제공업체 구성을 codexOverrides에 제공하세요. 예를 들어 OPENROUTER_API_KEY를 설정하고 OpenRouter를 구성하세요.

const security = new CodexSecurity({
  codexOverrides: {
    model: "anthropic/claude-sonnet-4.5",
    model_provider: "openrouter",
    model_providers: {
      openrouter: {
        name: "OpenRouter",
        base_url: "https://openrouter.ai/api/v1",
        env_key: "OPENROUTER_API_KEY",
        wire_api: "responses",
      },
    },
  },
});

Fireworks의 경우 두 openrouter 키를 모두 fireworks로 변경하고, nameFireworks AI로, env_keyFIREWORKS_API_KEY로 설정하고, https://api.fireworks.ai/inference/v1base_url로 사용한 다음 Fireworks 모델을 선택하세요.

클라이언트는 지원되는 인증 방법도 제공합니다.

메서드 용도
loginApiKey(apiKey) API key로 격리된 런타임을 인증합니다.
loginChatGPT() 브라우저 로그인 흐름을 시작하고 로그인 핸들을 반환합니다.
loginChatGPTDeviceCode() 기기 코드 로그인 흐름을 시작하고 로그인 핸들을 반환합니다.
account() 현재 인증 상태를 반환합니다.
logout() 격리된 인증을 지웁니다.

로그인 핸들은 애플리케이션이 선택한 로그인 흐름을 표시하고 완료할 수 있도록 waitForInstructions, authUrl, verificationUrl, userCode, waitcancel을 제공합니다. SDK는 파일 기반 Codex 로그인을 재사용할 수 있습니다. API key는 CI와 서버 측 자동화에 적합합니다.

API key와 저장된 로그인을 모두 사용할 수 있으면 SDK는 기본적으로 API key를 사용합니다. 대신 ChatGPT 로그인을 사용하려면 스캔에서 이를 선택하세요.

const result = await security.run("/path/to/repository", {
  auth: "chatgpt",
});

환경 API key를 요구하려면 auth: "api-key"를 설정하세요. preflight는 동일한 auth 옵션을 허용합니다.

스캔 오류 처리하기

애플리케이션에서 취할 수 있는 조치에 맞는 내보낸 오류 클래스를 catch하세요.

오류 의미
AuthenticationRequiredError 스캔에 지원되는 자격 증명이 필요합니다.
ConfigurationError Codex 구성 또는 재정의가 적합하지 않습니다.
InvalidTargetError 리포지토리, 경로, 모드 또는 Git 대상이 적합하지 않습니다.
OutputDirectoryError 출력 위치 또는 해당 권한이 적합하지 않습니다.
OutputInsideProtectedRootError 출력 디렉터리가 스캔 대상 리포지토리 또는 작업 트리 내부에 있습니다.
PluginPythonUnavailableError 사용 가능한 Python 인터프리터가 없습니다.
PluginBootstrapError 플러그인 런타임을 시작하지 못했습니다.
ScanCostLimitExceededError 스캔이 예상 비용 한도를 초과했습니다.
IncompleteScanError 필요한 결과를 생성하기 전에 스캔이 종료되었습니다.
ContractValidationError 완료된 스캔이 구조화된 계약 오류를 반환했습니다.
ScanInterruptedError 중단으로 스캔이 정지되었으며 부분 출력이 남았을 수 있습니다.

CLI 빠른 시작, CI 가이드 또는 CLI 참조로 계속 진행하세요.