For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
기본 탐색 메뉴
Theme

Codex Security TypeScript SDK

TypeScript에서 Codex Security 스캔을 실행하고, 대상을 선택하고, 결과를 확인하고, 스캔 수명 주기를 관리하세요.

Codex Security TypeScript SDK를 사용하면 애플리케이션이나 개발자 도구에서 리포지터리와 코드 변경 사항을 대상으로 보안 스캔을 실행할 수 있습니다. SDK는 타입이 정의된 보안 이슈, 스캔 매니페스트, 저장된 보고서의 경로를 반환합니다.

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

압축된 Codex 세션(.jsonl.zst)을 읽거나 재개하려면 Node.js 22.x에서는 22.15.0 이상을 사용하세요. Node.js 24 또는 26도 사용할 수 있습니다. 압축하지 않은 .jsonl 세션은 지원되는 모든 Node.js 버전에서 사용할 수 있습니다.

범용 코딩 에이전트에 대해서는 Codex SDK 가이드를 참고하세요. 터미널 및 CI 워크플로우에 대해서는 Codex Security CLI 빠른 시작을 참고하세요.

SDK 설정하기

SDK를 설치하세요.

npm install @openai/codex-security

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

일부 사이버 보안 요청을 처리하거나 보호된 보안 이슈에 접근하려면 ChatGPT 계정 또는 API 조직에 Trusted Access for Cyber 권한이 필요합니다.

스캔 실행하기

SDK는 로컬 운영 체제에서 사용자에게 부여된 권한으로 실행되며 승인을 기다리지 않습니다. 스캔 프로세스가 환경을 상속할 수 있으므로 시작하기 전에 스캔과 무관한 자격 증명을 제거하세요. 로컬 스캔 권한을 참고하세요.

다음 예제를 scan.mjs로 저장하세요. 리포지터리 경로와 결과 디렉터리 경로를 명령줄 인수로 차례대로 전달하세요. 표준 리포지터리 스캔을 실행하고 작업이 끝나면 클라이언트를 닫으세요. outputDir에 리포지터리가 속한 Git 작업 트리 외부의 비공개 결과 디렉터리를 지정하세요.

outputDir를 생략하면 Codex Security는 자체 영구 상태 디렉터리에 결과를 저장합니다. 결과에는 소스 코드 일부와 취약점 세부 정보가 포함될 수 있습니다. 결과를 읽을 수 있는 사용자와 보관 기간을 설정하세요.

import { CodexSecurity } from "@openai/codex-security";

const [repository, outputDir] = process.argv.slice(2);
if (!repository || !outputDir) {
  throw new Error("Usage: node scan.mjs <repository> <results-directory>");
}
const security = new CodexSecurity();

try {
  const result = await security.run(repository, {
    outputDir,
  });

  console.log(result.reportPath);
  console.log(result.manifest.scan.status);
  console.log(result.findings.findings.length);
} finally {
  await security.close();
}

Node.js로 실행하세요.

node scan.mjs /path/to/repository /path/outside/repository/results

이 예제는 보고서 경로, 스캔 상태, 보안 이슈 수를 출력합니다. 보고서를 열어 근거를 확인하세요.

run은 저장된 아티팩트를 검증한 뒤 ScanResult를 반환합니다. 이때 result.manifest.scan.status가 "completed"여야 합니다. 요청한 대상은 result.manifest.scan.scope에서, 경고는 result.manifest.scan.warnings에서 확인하세요. 완료 상태만으로는 어떤 파일을 검토했는지 알 수 없습니다. 런타임이나 입력에 문제가 있거나 결과 무결성 검증에 실패하면 오류가 발생할 수 있습니다.

이후 예제에서는 열려 있는 security 클라이언트를 재사용하세요. close() 호출은 finally 블록에 두어 런타임 리소스를 해제하세요. 추가로 필요한 import 문은 scan.mjs 맨 위에 넣으세요.

사전 검사로 입력 확인하기

preflight를 사용하면 스캔을 시작하기 전에 리포지터리, 대상, 모드, 지식 베이스 문서, 출력 위치, Codex 설정을 확인할 수 있습니다. 다음 예제는 리포지터리 루트에서 security.md를 읽습니다.

import { join } from "node:path";

const knowledgeBase = join(repository, "security.md");

const plan = await security.preflight(repository, {
  target: ["services/billing", "packages/auth"],
  knowledgeBasePaths: [knowledgeBase],
  outputDir: outputDir,
});

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(repository, {
  outputDir: outputDir,
  archiveExisting: true,
});

console.log(plan.archiveDir);

반환된 archiveDir에서 아카이브 이름이 어떻게 지정되는지 확인할 수 있습니다. run이 고유한 저장 위치를 별도로 생성하므로 최종 경로는 다를 수 있습니다. 실제 아카이브 경로는 onOutputArchived로 확인하세요.

try {
  await security.run(repository, {
    outputDir: outputDir,
    archiveExisting: true,
    onOutputArchived(archiveDir) {
      console.log("Archived results:", archiveDir);
    },
  });
} finally {
  await security.close();
}

이렇게 하면 이전 결과를 아카이브로 옮긴 뒤 빈 출력 디렉터리에서 스캔을 시작합니다.

스캔 대상 선택하기

SDK는 리포지터리, 경로, 커밋 간 변경 사항, 작업 트리를 스캔할 수 있습니다. 기본 대상은 리포지터리 전체입니다.

선택한 경로 스캔하기

리포지터리 내부 경로를 배열로 전달하세요.

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

경로는 파일이나 디렉터리를 가리킬 수 있습니다. SDK는 리포지터리 안에서 각 경로의 실제 위치를 확인하고 중복을 제거합니다.

커밋된 변경 사항 스캔하기

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

import { DiffTarget } from "@openai/codex-security";

const target = DiffTarget.refs({
  base: "HEAD~1",
  head: "HEAD",
});

try {
  const result = await security.run(repository, { target });
} finally {
  await security.close();
}

head의 기본값은 HEAD입니다. Git 작업 트리의 루트를 리포지터리 경로로 전달하고, 스캔하기 전에 head로 지정한 리비전을 체크아웃하세요.

작업 트리 스캔하기

DiffTarget.workingTree를 사용하면 스테이징된 변경 사항과 스테이징되지 않은 변경 사항을 기준 리비전과 비교해 스캔할 수 있습니다.

import { DiffTarget } from "@openai/codex-security";
const target = DiffTarget.workingTree({ base: "HEAD" });
try {
  const result = await security.run(repository, { target });
} finally {
  await security.close();
}

기준 리비전의 기본값은 HEAD입니다. 커밋 간 변경 사항이나 작업 트리를 스캔하기 전에 선택한 리비전을 가져오세요.

심층 모드 선택하기

리포지터리나 경로를 더 폭넓게 검토하려면 mode: "deep"을 설정하세요.

try {
  const result = await security.run(repository, {
    target: ["services/billing"],
    mode: "deep",
    workers: 2,
    subagents: 0,
    stopAfterNoNew: 3,
    maxDiscoveryRuns: 10,
    maxTimeMinutes: 90,
  });
} finally {
  await security.close();
}

심층 모드에서는 리포지터리와 경로를 스캔할 수 있습니다. 커밋 간 변경 사항과 작업 트리 스캔에는 표준 모드를 사용하세요. 심층 모드에서 workers는 동시에 실행할 스캔 워커 수를 제한하고, subagents는 워커당 하위 에이전트 수를 설정합니다. stopAfterNoNew에 지정한 횟수만큼 워커를 연속으로 실행해도 새 보안 이슈가 발견되지 않으면 탐색을 중지합니다. maxDiscoveryRuns는 전체 워커 실행 횟수를 제한합니다.

maxTimeMinutes를 설정해 심층 탐색 시간을 제한하세요. 기본값과 최댓값은 모두 5,760분(96시간)입니다. 제한 시간에 도달하면 탐색이 중지되고 SDK가 실행을 마친 워커의 결과를 합칩니다. 표준 스캔에서는 maxTimeMinutes를 조사 시간의 권장 한도로 사용합니다. 보고서 작성은 그 이후에 끝날 수 있습니다. 사용자 지정 검증과 스캔 후 지침 실행은 이 시간 한도에 포함되지 않습니다.

보안 지식 베이스 추가하기

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

import { join } from "node:path";

const knowledgeBase = join(repository, "security.md");

try {
  const result = await security.run(repository, {
    knowledgeBasePaths: [knowledgeBase],
  });
} finally {
  await security.close();
}

SDK는 파일과 디렉터리를 모두 입력으로 받으며 디렉터리를 재귀적으로 검색합니다. 지원 형식에는 UTF-8 텍스트(JSON 및 SARIF 포함), PDF, DOCX가 있습니다. SDK는 링크로 지정된 입력 경로를 거부하며 디렉터리 안에서도 링크인 항목은 건너뜁니다.

SDK는 문서에서 추출한 텍스트를 스캔 아티팩트와 같은 위치의 비공개 .scan-knowledge.json 파일에 저장합니다. 이 파일을 스캔 디렉터리와 함께 보관하세요. 중단된 심층 스캔을 재개할 때 codex-security scans resume 명령어는 원본 문서가 변경되거나 삭제되었더라도 저장된 텍스트를 사용합니다. 정식 보고서에는 문서 텍스트가 포함되지 않습니다.

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

scanPrompt로 스캔에서 집중할 부분을 지정하고 postScanPrompt로 후속 작업을 요청하세요.

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

후속 작업이 실패하면 SDK는 완료된 스캔을 보존하고 onWarning으로 오류를 알립니다. 후속 작업이 완료된 스캔의 아티팩트를 변경했다면 SDK가 원래 상태로 복원합니다. 후속 작업은 스캔 비용 추적이 끝난 뒤 실행되므로 maxCostUsd 한도가 적용되지 않습니다.

자체 환경에서 보안 이슈 검증하기

validationPrompt를 전달하면 자체 테스트 절차로 보안 이슈 후보를 검증할 수 있습니다. 예를 들어 체크아웃 디렉터리 외부에서 직접 관리하는 스크립트를 지정하고 로컬 테스트 서버를 대상으로 실행하도록 프롬프트를 작성하세요. 리포지터리 경로와 결과 디렉터리 경로 다음에 검증 스크립트 경로와 서버 URL을 차례대로 전달하세요.

const [validationScript, validationUrl] = process.argv.slice(4);
if (!validationScript || !validationUrl)
  throw new Error("Pass a validation script path and service URL.");
const result = await security.run(repository, {
  outputDir,
  validationPrompt: `Run ${validationScript} against ${validationUrl} and report which findings reproduce.`,
});
node scan.mjs /path/to/repository /path/outside/repository/results /path/to/validate.sh http://localhost:3000

validationPrompt는 리포지터리, 경로, 커밋 간 변경 사항 또는 작업 트리의 표준 스캔에서 사용하세요. 각 표준 컴포넌트 스캔에 같은 절차를 적용하려면 scanOptions.validationPrompt를 runComponentScans에 전달하세요. 심층 스캔은 사용자 지정 검증을 허용하지 않습니다.

스캔 예산 설정하기

maxCostUsd를 설정하면 예상 모델 비용이 한도를 초과할 때 스캔을 중지합니다. onCost로 스캔 실행 중 비용을 추적하고 estimatedUsdRange를 출력하세요.

try {
  const result = await security.run(repository, {
    maxCostUsd: 5,
    onCost(cost) {
      console.log(cost.estimatedUsdRange);
    },
  });

  console.log(result.cost?.estimatedUsdRange);
} finally {
  await security.close();
}

한도는 짧은 컨텍스트를 기준으로 산정한 estimatedUsd에 적용됩니다. 이미 진행 중인 요청으로 인해 추정 비용이 한도를 초과할 수 있습니다. 긴 컨텍스트 요금이 적용되면 estimatedUsdRange가 한도를 넘을 수도 있습니다. 이 한도로 실제 청구 금액을 제한할 수는 없습니다.

심층 스캔에서 Codex Security가 완료된 워커의 결과를 집계한 뒤 한도에 도달하면 run은 manifest.scan.status가 "completed"인 결과를 반환하고 onWarning으로 예산 경고를 알릴 수 있습니다.

스캔이 유효한 완료 결과를 생성할 수 없으면 run은 ScanCostLimitExceededError를 발생시키고 그때까지 생성된 출력을 보존합니다.

프로젝트 컴포넌트 스캔하기

runComponentScans를 사용해 서비스나 패키지를 병렬로 스캔하고 보안 이슈를 한데 모으세요. 각 컴포넌트에 이름과 리포지터리 기준 상대 경로를 하나 이상 지정하세요. 리포지터리가 속한 Git 작업 트리 외부에서 새 디렉터리나 비어 있는 디렉터리를 출력 위치로 선택하세요.

import { runComponentScans } from "@openai/codex-security";

const result = await runComponentScans({
  repository: repository,
  outputDir: outputDir,
  components: [
    { name: "API", paths: ["services/api", "packages/auth"] },
    { name: "Web", paths: ["services/billing"] },
  ],
  workers: 2,
  onProgress: ({ name, status }) => console.log(name, status),
});

console.log(result.reportPath);
if (result.failed > 0) {
  throw new Error(`${result.failed} component scans failed.`);
}

workers로 동시에 스캔할 컴포넌트 수를 설정하세요. 기본값은 4입니다.

Codex가 컴포넌트를 제안하게 하려면 auto: true를 전달하고 components는 생략하세요. planOnly: true를 추가하면 스캔을 실행하지 않고 계획을 components.json에 저장합니다.

import { runComponentScans } from "@openai/codex-security";

const plan = await runComponentScans({
  repository: repository,
  outputDir: outputDir,
  auto: true,
  planOnly: true,
});

console.log(plan.planPath);

실행 결과에 스캔에 실패한 컴포넌트가 있다면 result.retryPlanPath가 가리키는 JSON 파일을 읽으세요. 파일의 components 배열을 runComponentScans에 전달하고 새 outputDir를 지정하세요. 재시도 보고서에는 해당 컴포넌트만 포함되므로 두 실행의 보고서를 모두 검토하세요.

스캔 결과 활용하기

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

속성 내용
manifest 대상, 범위, 생성 주체, 아티팩트 기록을 포함하는 봉인된 스캔 매니페스트입니다.
findings 현재 스캔에서 발견한 보안 이슈입니다. 각 보안 이슈 객체는 findings.findings에서 읽을 수 있습니다.
repositoryFindings 스캔 기록이 있을 때 확인할 수 있는, 리포지터리의 여러 스캔에서 발견된 미해결 보안 이슈입니다.
review 검토에서 제외한 경로 패턴입니다(review.excludedPaths).
scanDir 스캔 디렉터리입니다.
threadId 스캔에 사용한 Codex 스레드의 식별자입니다.
turnResult 턴 상태, 응답, 확인 가능한 사용량 메타데이터입니다.
cost 예상 모델 및 토큰 비용입니다. 확인할 수 없으면 null입니다.
reportPath report.md의 경로입니다.
threatModel 저장된 위협 모델입니다. 없으면 null입니다.
threatModelPath 저장된 위협 모델 문서의 경로입니다. 확인할 수 없으면 null입니다.
manifestPath scan-manifest.json의 경로입니다.
findingsPath findings.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
  );
}

보안 이슈에는 선택적 필드인 codeEvidence, rootCause, validation, attackPath, remediationTests, preventiveControls가 포함될 수 있습니다.

리포지터리 전체의 보안 이슈를 확인할 때는 confirmedInLatestScan으로 최신 스캔에서 확인한 이슈와 이전 스캔에서 발견되어 아직 해결되지 않은 이슈를 구분할 수 있습니다.

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

result.toJSON()을 사용해 매니페스트, 보안 이슈, 기록된 검토 제외 항목, 아티팩트 경로, 턴 메타데이터를 직렬화하세요.

저장된 위협 모델 읽기

threatModel과 threatModelPath를 사용하기 전에 값이 각각 null인지 확인하세요. Codex Security가 Markdown 파일을 작성하지 못한 경우에도 저장된 모델을 내보낼 수 있습니다. 파일 이름을 추측하지 말고 내보내기에서 반환한 경로를 사용하세요.

저장된 아티팩트 내보내기

Codex를 시작하거나 자격 증명을 불러오거나 모델을 호출하지 않고도 저장된 결과를 내보낼 수 있습니다. 다음 예제는 저장된 위협 모델을 표준 출력으로 내보냅니다. 기존 스캔 결과 디렉터리의 경로를 첫 번째 명령줄 인수로 전달하세요.

import { exportArtifact } from "@openai/codex-security";

const directory = process.argv[2];
if (!directory) {
  throw new Error(
    "Pass an existing scan results directory as the first argument."
  );
}

await exportArtifact({
  source: { directory },
  artifact: "threat-model",
  output: "-",
});

저장된 스캔을 ID로 선택하려면 source: { scanId: "SCAN_ID" }를 대신 사용하세요. 아티팩트를 파일로 저장하려면 output에 대상 경로를 지정하세요.

위협 모델은 Markdown으로 내보냅니다. 스캔에 저장된 위협 모델이 없으면 내보내기에서 오류를 반환합니다. 보안 이슈를 내보내려면 artifact: "findings"를 설정하세요. 형식은 format: "sarif"(기본값), "json", "csv", "servicenow-avit" 중에서 선택하세요.

결과에는 출력 경로인 path가 포함되며, 위협 모델을 파일로 내보내면 같은 스캔 결과에 저장된 출처 정보인 provenance도 포함됩니다. 두 필드 모두 null이 되는 경우는 output: "-"로 표준 출력에 쓸 때입니다. 내보내기에는 Python 3.10 이상이 필요합니다.

ServiceNow Manual AVIT Ingestion을 사용하려면 artifact: "findings"와 format: "servicenow-avit"를 설정하세요. 애플리케이션 템플릿을 준비한 뒤 해당 경로를 avitTemplate에 전달하세요. output에는 CSV 파일을 저장할 리포지터리 외부의 비공개 경로를 지정하세요. source.directory로 기존 스캔 결과 디렉터리를 선택하세요.

기존 보안 이슈 검증하기

validate를 사용해 다른 도구나 워크플로우에서 발견한 보안 이슈를 소스 코드와 대조해 확인하세요. 이 메서드는 새 스캔을 시작하거나 애플리케이션 또는 해당 테스트를 실행하지 않습니다. 실행 시점의 근거가 필요하면 해당 이슈를 별도로 재현하세요.

const validation = await security.validate({
  repositoryPath: repository,
  finding: {
    title: "Possible SQL injection",
    location: "src/index.js:1",
  },
});

console.log(validation.disposition);
console.log(validation.report);

보안 이슈를 비어 있지 않은 텍스트나 JSON 객체로 전달하세요. 파일에 저장되어 있다면 파일을 읽어 그 내용을 전달하세요.

disposition은 보안 이슈의 판정 결과를 reportable, suppressed, not_applicable, deferred 중 하나로 나타냅니다. validation.report의 Markdown 텍스트는 판정 근거와 추가로 확인해야 할 사항을 설명합니다. 보고서 파일이 필요하면 이 문자열을 저장하세요.

스캔 추적 또는 취소하기

ScanOptions 콜백을 전달해 스캔 시작, 워커 진행 상황, 연결 재시도를 확인하세요.

try {
  const result = await security.run(repository, {
    outputDir: outputDir,
    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);
} finally {
  await security.close();
}

스캔을 취소하려면 요청 또는 작업 컨트롤러에서 AbortSignal을 전달하세요. 다음 예제는 30분이 지나도 스캔이 실행 중이면 스캔을 중단하고 그때까지 저장된 출력이 있는 디렉터리의 경로를 출력합니다.

import { ScanInterruptedError } from "@openai/codex-security";

try {
  await security.run(repository, {
    outputDir: outputDir,
    signal: AbortSignal.timeout(30 * 60 * 1000),
  });
} catch (error) {
  if (error instanceof ScanInterruptedError) {
    console.error(error.scanDir);
  } else {
    throw error;
  }
} finally {
  await security.close();
}

스캔이 중단되면 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({
  // To override the bundled plugin, add pluginPath: "/path/to/plugin".
  pythonPath: "python3",
  codexOverrides: {
    model: "gpt-6.1-sol",
    model_reasoning_effort: "medium",
  },
});

번들로 제공되는 플러그인을 다른 플러그인으로 대체하려면 pluginPath에 해당 플러그인의 디렉터리나 ZIP 파일을 지정하세요. pythonPath는 플러그인에서 사용할 인터프리터를 지정합니다. codexOverrides는 지원되는 값을 격리된 Codex 환경의 설정에 병합합니다. Amazon Bedrock을 사용하려면 model_provider와 model을 codexOverrides에 설정하세요.

codexOverrides.approval_policy를 "never"로 설정하면 권한 요청을 거부합니다. 그 외에는 스캔에서 승인 요청을 자동으로 검토합니다. 파일 시스템 접근 권한과 상속되는 자격 증명에 대해서는 로컬 스캔 권한을 참고하세요.

OpenRouter 또는 Fireworks를 사용하려면 해당 API 키를 제공하고 codexOverrides에 제공업체 설정 전체를 지정하세요. OPENROUTER_API_KEY를 설정하고 사용 가능한 OpenRouter 모델 ID를 다음 TypeScript 함수에 전달하세요.

function createOpenRouterClient(model: string) {
  return new CodexSecurity({
    codexOverrides: {
      model,
      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로 바꾸세요. name은 Fireworks AI로, env_key는 FIREWORKS_API_KEY로 설정하세요. https://api.fireworks.ai/inference/v1을 base_url로 사용하고 Fireworks 모델을 선택하세요.

클라이언트는 다음 인증 메서드도 제공합니다.

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

로그인 핸들은 waitForInstructions, authUrl, verificationUrl, userCode, wait, cancel을 제공합니다. 애플리케이션은 이를 사용해 선택한 로그인 절차를 사용자에게 안내하고 완료할 수 있습니다. SDK는 파일에 저장된 Codex 로그인 정보를 재사용할 수 있습니다. CI 및 서버 측 자동화에는 API 키를 사용하세요.

API 키와 저장된 로그인 정보가 모두 있으면 SDK는 기본적으로 API 키를 사용합니다. 대신 ChatGPT 로그인 정보를 사용하려면 스캔에서 다음과 같이 지정하세요.

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

환경 변수의 API 키를 필수로 지정하려면 auth: "api-key"를 설정하세요. preflight에서도 같은 auth 옵션을 사용할 수 있습니다.

스캔 오류 처리하기

애플리케이션에서 취할 수 있는 조치에 맞춰 SDK가 내보내는 다음 오류 클래스의 예외를 처리하세요.

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

이어서 CLI 빠른 시작, CI 가이드 또는 CLI 레퍼런스를 참고하세요.