日本語

Codex Security TypeScript SDK

TypeScript から Codex Security スキャンを実行し、対象とプロバイダーを選択して結果を確認し、スキャンのライフサイクルを管理します。

Codex Security TypeScript SDK を使用すると、アプリケーションや開発者ツールからリポジトリとコード変更のセキュリティスキャンを実行できます。SDK は、型付けされた検出結果、カバレッジの詳細、スキャン artifact へのパスを返します。長時間のスキャン向けに、preflight チェック、コスト上限、進行状況 callback、キャンセルもサポートしています。

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 の override を使用して Amazon Bedrock を設定します。

最適な結果を得るには、Trusted Access for Cyber の確認済みアカウントを使用してください。サインインまたは API key の指定だけでは Trusted Access は付与されません。

スキャンを実行する

CodexSecurity client を 1 つ作成し、標準のリポジトリスキャンを実行して、処理の完了後に client を閉じます。それを囲む Git worktree の外に非公開の結果ディレクトリを指定するには、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 はスキャンを開始して完了を待ち、sealed artifact を検証して ScanResult を返します。close は分離されたランタイムを解放し、繰り返し呼び出せます。

preflight で入力を確認する

スキャンを開始する前に、preflight を使用してリポジトリ、対象、mode、出力先、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);

preflight は Codex ランタイムと認証情報に手を加えません。また、plugin と Python の検出はスキャン自体に委ねます。そのため、長時間の処理や認証情報を使用する処理の前に、ユーザー入力を確認する用途に適しています。

既存の結果ディレクトリの archive 処理をプレビューするには、archiveExisting: true を設定します。

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

console.log(plan.archiveDir);

返される archiveDir は archive の命名をプレビューします。run は独自の一意な保存先を生成するため、最終的なパスは異なる場合があります。実際の archive パスは onOutputArchived で取得します。

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

スキャンは以前の結果を archive し、空の出力ディレクトリから開始します。

スキャン対象を選択する

SDK は、リポジトリ、パス、コミット済み diff、working tree を対象としてサポートします。デフォルトの対象はリポジトリ全体です。

選択したパスをスキャンする

リポジトリ内のパスを配列として渡します。

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

パスにはファイルまたはディレクトリを指定できます。SDK は各パスをリポジトリ内で解決し、重複を削除します。

コミット済みの変更をスキャンする

ローカルで利用可能な 2 つの Git リビジョン間のコミット済み変更をスキャンするには、DiffTarget.refs を使用します。



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

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

head のデフォルトは HEAD です。diff 対象では、repository 引数に Git worktree のルートを指定する必要があります。

working tree をスキャンする

base リビジョンに対する staged と unstaged の変更をスキャンするには、DiffTarget.workingTree を使用します。

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

base のデフォルトは HEAD です。diff または working tree のスキャンを開始する前に、選択したリビジョンを fetch してください。

deep mode を選択する

より広範なレビューが必要なリポジトリまたはパスのスキャンでは、mode: "deep" を設定します。

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

deep mode はリポジトリとパスを対象としてサポートします。diff と working tree のスキャンには standard mode を使用してください。

セキュリティナレッジベースを追加する

アーキテクチャドキュメント、脅威モデル、セキュリティポリシーを 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);

この上限は推定値であり、厳密な支出上限ではありません。すでに進行中の request は、上限を超えて完了する場合があります。スキャンが上限を超えると、SDK は ScanCostLimitExceededError を throw し、利用可能な結果を保持します。

スキャン結果を操作する

ScanResult は、構造化ドキュメント、スキャン metadata、artifact のパスを公開します。

property 内容
manifest 対象、scope、producer、artifact record を含む sealed scan manifest。
findings 検出結果のドキュメント。検出結果の object は findings.findings から読み取ります。
coverage レビュー済みの surface、除外項目、deferred work、open question、完全性。
scanDir スキャンディレクトリ。
threadId スキャンの Codex thread identifier。
turnResult turn の status、response、利用可能な usage metadata。
cost 推定モデルコストと token コスト。利用できない場合は null
reportPath report.md へのパス。
manifestPath scan-manifest.json へのパス。
findingsPath findings.json へのパス。
coveragePath coverage.json へのパス。
artifactsDir supporting-artifacts ディレクトリ。
sarifPath 生成された SARIF のパス。SARIF がない場合は null
pluginVersion スキャンの producer が記録したバージョン。

構造化された検出結果とカバレッジを直接使用します。

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);
}

カバレッジの完全性は completepartialunknown のいずれかです。スキャンをセキュリティ判断の証拠として使用する前に、deferred surface、除外項目、open question を確認してください。

result.toJSON() は、manifest、検出結果、カバレッジ、スキャンと thread の identifier、reportPathartifactsDirsarifPath、turn metadata を、JSON に変換可能な 1 つの object として返します。

スキャンを追跡またはキャンセルする

スキャンの開始、worker の進行状況、接続の再試行を報告するには、ScanOptions callback を渡します。

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);

request、job controller、timeout からキャンセルする場合は、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 lifecycle callback も使用できます。

callback 呼び出されるタイミング
onOutputArchived(archiveDir) 既存の結果が archive ディレクトリへ移動したとき。
onOutputDirReady(scanDir) 非公開のスキャンディレクトリの準備ができたとき。
onScanStarted() スキャンのセットアップが完了し、実行が始まるとき。
onReconnect(attempt, maxAttempts) SDK が切断されたスキャンストリームを再試行するとき。
onWorkerStatus(status) worker の preflight または dispatch status が変化したとき。
onCost(cost) 更新された推定スキャンコストを利用できるようになったとき。
onObserverError(observer, error) 別の scan lifecycle callback でエラーが発生したとき。

ランタイムと認証情報を設定する

特定の plugin、interpreter、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 は plugin ディレクトリまたは ZIP を受け付けます。pythonPath は plugin interpreter を選択します。codexOverrides は、サポートされる値を分離された Codex 設定にマージします。スキャンでは、デフォルトで extra-high reasoning effort の gpt-5.6-sol を使用します。別のモデルまたは reasoning effort を使用するには、codexOverridesmodelmodel_reasoning_effort を設定します。Amazon Bedrock を使用するには、codexOverridesmodel_providermodel を設定します。

client は、サポートされる認証メソッドも公開します。

method 用途
loginApiKey(apiKey) API key で分離されたランタイムを認証します。
loginChatGPT() ブラウザのサインインフローを開始し、login handle を返します。
loginChatGPTDeviceCode() device-code サインインフローを開始し、login handle を返します。
account() 現在の認証状態を返します。
logout() 分離された認証を消去します。

login handle は waitForInstructionsauthUrlverificationUrluserCodewaitcancel を提供するため、アプリケーションは選択されたサインインフローを提示して完了できます。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 option を受け付けます。

スキャンエラーを処理する

アプリケーションが実行できる対処に対応した、export 済みの error class を catch します。

error 意味
AuthenticationRequiredError スキャンにはサポートされる認証情報が必要です。
ConfigurationError Codex 設定または override が不適切です。
InvalidTargetError リポジトリ、パス、mode、または Git 対象が不適切です。
OutputDirectoryError 出力先またはその権限が不適切です。
OutputInsideProtectedRootError 出力ディレクトリが、スキャン対象のリポジトリまたは worktree 内にあります。
PluginPythonUnavailableError 使用可能な Python interpreter がありません。
PluginBootstrapError plugin ランタイムを起動できませんでした。
ScanCostLimitExceededError スキャンが推定コスト上限を超えました。
IncompleteScanError 必須の結果を生成する前にスキャンが終了しました。
ContractValidationError 完了したスキャンが structured-contract error を返しました。
ScanInterruptedError 中断によってスキャンが停止し、部分的な出力が残っている可能性があります。

続いて、CLI クイックスタートCI ガイド、または CLI リファレンスを参照してください。