Codex Security TypeScript SDK
TypeScript에서 Codex Security 스캔을 실행하고, 대상과 제공업체를 선택하고, 결과를 검사하고, 스캔 수명 주기를 관리합니다.
Codex Security TypeScript SDK를 사용하여 애플리케이션이나 개발자 도구에서 리포지토리 및 코드 변경 사항에 대한 보안 스캔을 실행하세요. SDK는 형식이 지정된 발견 항목, 커버리지 세부 정보, 스캔 아티팩트 경로를 반환합니다. 장시간 실행되는 스캔을 위해 사전 검사, 비용 제한, 진행 상황 콜백, 취소 기능도 지원합니다.
SDK는 ECMAScript modules (ESM)을 사용하며 Node.js 22 이상에서 서버 측으로 실행됩니다. 스캔에는 Python 3.10 이상도 필요합니다.
SDK 설정하기
SDK를 설치하세요.
npm install @openai/codex-security스캔을 시작하기 전에 OPENAI_API_KEY 또는 CODEX_API_KEY을(를) 설정하거나, 기존 파일 기반 Codex 로그인을 사용하거나, AWS 자격 증명과 명시적인 model_provider 및 model 재정의를 사용하여 Amazon Bedrock을 구성하세요.
최상의 결과를 얻으려면 Trusted Access for Cyber 인증을 받은 계정을 사용하세요. 로그인하거나 API key를 제공해도 Trusted Access가 부여되지는 않습니다.
스캔 실행하기
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"],
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는 리포지토리, 경로, 커밋된 차이, 작업 트리 대상을 지원합니다. 기본 대상은 전체 리포지토리입니다.
선택한 경로 스캔하기
리포지토리 내부 경로의 배열을 전달하세요.
const result = await security.run("/path/to/repository", {
target: ["services/billing", "packages/auth"],
});경로는 파일 또는 디렉터리를 식별할 수 있습니다. SDK는 리포지토리 내부의 각 경로를 확인하고 중복을 제거합니다.
커밋된 변경 사항 스캔하기
로컬에서 사용할 수 있는 두 Git 리비전 사이에 커밋된 변경 사항을 스캔하려면 DiffTarget.refs을(를) 사용하세요.
const target = DiffTarget.refs({
base: "origin/main",
head: "HEAD",
});
const result = await security.run("/path/to/repository", { target });헤드의 기본값은 HEAD입니다. 차이 대상에서는 리포지토리 인수가 Git 작업 트리 루트여야 합니다.
작업 트리 스캔하기
베이스 리비전을 기준으로 스테이징된 변경 사항과 스테이징되지 않은 변경 사항을 스캔하려면 DiffTarget.workingTree을(를) 사용하세요.
const target = DiffTarget.workingTree({ base: "HEAD" });
const result = await security.run("/path/to/repository", { target });베이스의 기본값은 HEAD입니다. 차이 또는 작업 트리 스캔을 시작하기 전에 선택한 리비전을 가져오세요.
심층 모드 선택하기
더 광범위한 검토가 필요한 리포지토리 또는 경로 스캔에는 mode: "deep"을(를) 설정하세요.
const result = await security.run("/path/to/repository", {
target: ["services/billing"],
mode: "deep",
});심층 모드는 리포지토리 및 경로 대상을 지원합니다. 차이 및 작업 트리 스캔에는 표준 모드를 사용하세요.
보안 지식 베이스 추가하기
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는 링크된 입력 경로를 거부하고 링크된 디렉터리 항목을 건너뛰며, 추출한 문서 콘텐츠를 저장된 스캔 결과 외부에 유지합니다.
스캔 예산 설정하기
예상 모델 비용이 한도를 초과할 때 스캔을 중지하려면 maxCostUsd을(를) 설정하세요. 스캔 실행 중 비용을 추적하려면 onCost을(를) 사용하세요.
const result = await security.run("/path/to/repository", {
maxCostUsd: 5,
onCost(cost) {
console.log(cost.estimatedUsd);
},
});
console.log(result.cost?.estimatedUsd);한도는 추정치이며 엄격한 지출 상한이 아닙니다. 이미 진행 중인 요청은 한도를 초과해 완료될 수 있습니다. 스캔이 한도를 초과하면 SDK는 ScanCostLimitExceededError을(를) 발생시키고 사용 가능한 결과를 보존합니다.
스캔 결과 사용하기
ScanResult은(는) 구조화된 문서, 스캔 메타데이터, 아티팩트 경로를 제공합니다.
| 속성 | 내용 |
|---|---|
manifest |
대상, 범위, 생성자, 아티팩트 레코드를 포함한 봉인된 스캔 매니페스트. |
findings |
발견 항목 문서. findings.findings에서 발견 항목 객체를 읽습니다. |
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 |
스캔 생성자가 기록한 버전. |
구조화된 발견 항목과 커버리지를 직접 사용하세요.
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);
}커버리지 완전성은 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");
},
onWorkerStatus(status) {
console.log(status.kind, status);
},
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 수명 주기 콜백도 사용할 수 있습니다.
| 콜백 | 호출 시점 |
|---|---|
onOutputArchived(archiveDir) |
기존 결과가 보관 디렉터리로 이동할 때. |
onOutputDirReady(scanDir) |
비공개 스캔 디렉터리가 준비되었을 때. |
onScanStarted() |
스캔 설정이 완료되고 실행이 시작될 때. |
onReconnect(attempt, maxAttempts) |
SDK가 연결이 끊긴 스캔 스트림을 다시 시도할 때. |
onWorkerStatus(status) |
작업자 사전 검사 또는 디스패치 상태가 변경될 때. |
onCost(cost) |
업데이트된 예상 스캔 비용을 사용할 수 있을 때. |
onObserverError(observer, error) |
다른 스캔 수명 주기 콜백에서 오류가 발생할 때. |
런타임 및 자격 증명 구성하기
특정 플러그인, 인터프리터 또는 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에서 model 및 model_reasoning_effort을(를) 설정하세요. Amazon Bedrock을 사용하려면 codexOverrides에서 model_provider 및 model을(를) 설정하세요.
클라이언트는 지원되는 인증 메서드도 제공합니다.
| 메서드 | 용도 |
|---|---|
loginApiKey(apiKey) |
API key로 격리된 런타임을 인증합니다. |
loginChatGPT() |
브라우저 로그인 흐름을 시작하고 로그인 핸들을 반환합니다. |
loginChatGPTDeviceCode() |
디바이스 코드 로그인 흐름을 시작하고 로그인 핸들을 반환합니다. |
account() |
현재 인증 상태를 반환합니다. |
logout() |
격리된 인증을 지웁니다. |
로그인 핸들은 waitForInstructions, authUrl, verificationUrl, userCode, wait, cancel을(를) 제공하므로 애플리케이션에서 선택한 로그인 흐름을 제시하고 완료할 수 있습니다. 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 옵션을 허용합니다.
스캔 오류 처리하기
애플리케이션에서 수행할 수 있는 조치에 해당하는 내보낸 오류 클래스를 포착하세요.
| 오류 | 의미 |
|---|---|
AuthenticationRequiredError |
스캔에 지원되는 자격 증명이 필요합니다. |
ConfigurationError |
Codex 구성 또는 재정의가 적합하지 않습니다. |
InvalidTargetError |
리포지토리, 경로, 모드 또는 Git 대상이 적합하지 않습니다. |
OutputDirectoryError |
출력 위치 또는 해당 권한이 적합하지 않습니다. |
OutputInsideProtectedRootError |
출력 디렉터리가 스캔한 리포지토리 또는 작업 트리 내부에 있습니다. |
PluginPythonUnavailableError |
사용할 수 있는 Python 인터프리터가 없습니다. |
PluginBootstrapError |
플러그인 런타임을 시작할 수 없습니다. |
ScanCostLimitExceededError |
스캔이 예상 비용 한도를 초과했습니다. |
IncompleteScanError |
필수 결과를 생성하기 전에 스캔이 종료되었습니다. |
ContractValidationError |
완료된 스캔에서 구조화된 계약 오류를 반환했습니다. |
ScanInterruptedError |
중단으로 인해 스캔이 멈췄으며 부분 출력이 남았을 수 있습니다. |