中文

Codex Security TypeScript SDK

从 TypeScript 运行 Codex Security 扫描、选择目标和提供商、检查结果并管理扫描生命周期。

使用 Codex Security TypeScript SDK,从应用或开发工具对仓库和代码变更运行安全扫描。SDK 会返回类型化的安全发现、覆盖范围详情和扫描产物路径。对于耗时较长的扫描,它还支持预检、成本限制、进度回调和取消。

SDK 使用 ECMAScript 模块(ESM),并在 Node.js 22 或更高版本的服务端环境中运行。扫描还需要 Python 3.10 或更高版本。

设置 SDK

安装 SDK:

npm install @openai/codex-security

开始扫描前,请设置 OPENAI_API_KEYCODEX_API_KEY、复用现有的文件式 Codex 登录,或使用 AWS 凭据以及显式的 model_providermodel 覆盖来配置 Amazon Bedrock

为取得最佳效果,请使用已通过 Trusted Access for Cyber 验证的账号。登录或提供 API key 不会授予 Trusted Access。

运行扫描

创建一个 CodexSecurity 客户端,运行标准仓库扫描,并在工作完成后关闭客户端。传入 outputDir,选择外层 Git 工作树之外的私有结果目录。

如果省略 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 会启动扫描、等待扫描完成、验证已封存的产物,并返回 ScanResultclose 会释放隔离运行时,而且可以重复调用。

使用预检检查输入

在开始扫描之前,使用 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 解析仓库内的每个路径并删除重复项。

扫描提交的更改

使用 DiffTarget.refs 扫描两个本地可用的 Git 修订版之间提交的更改:



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

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

head revision 默认为 HEAD。Diff 目标要求仓库参数指向 Git 工作树根目录。

扫描工作树

使用 DiffTarget.workingTree 扫描针对基本修订的暂存和未暂存更改:

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

base revision 默认为 HEAD。开始差异或工作树扫描前,请先获取选定的 revision。

选择深度模式

为需要更广泛评审的仓库或路径扫描设置 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 已封存的扫描 manifest,包括目标、范围、生产者和产物记录。
findings 安全发现文件。各项安全发现位于 findings.findings
coverage 已评审范围、排除、延后处理的工作、悬而未决的问题和完整性。
scanDir 扫描目录。
threadId 扫描对应的 Codex thread 标识符。
turnResult turn 的状态、响应和可用的用量元数据。
cost 估算的模型和 token 成本;不可用时为 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);
}

覆盖完整性为 completepartialunknown。在使用扫描作为安全决策的证据之前,请查看延迟的表面、排除和未解决的问题。

result.toJSON() 返回一个可直接序列化为 JSON 的对象,其中包含 manifest、安全发现、覆盖范围、扫描与 thread 标识符、reportPathartifactsDirsarifPathturn 元数据。

跟踪或取消扫描

传递 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) worker 预检或调度状态发生变化。
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 配置中。扫描默认使用 gpt-5.6-sol 和 extra-high 推理强度;要使用其它模型或推理强度,请在 codexOverrides 中设置 modelmodel_reasoning_effort。要使用 Amazon Bedrock,请在 codexOverrides 中设置 model_providermodel

客户端还公开支持的认证方法:

方法 目的
loginApiKey(apiKey) 使用 API key 验证隔离运行时。
loginChatGPT() 启动浏览器登录流程并返回登录句柄。
loginChatGPTDeviceCode() 启动设备代码登录流程并返回登录句柄。
account() 返回当前的认证状态。
logout() 清除隔离的认证。

登录句柄提供 waitForInstructionsauthUrlverificationUrluserCodewaitcancel,以便应用可以呈现并完成所选的登录流程。SDK 可以复用文件式 Codex 登录,API key 则很适合 CI 和服务端自动化。

当 API key 和已保存的登录同时可用时,SDK 默认使用 API key。要改用 ChatGPT 登录,请为扫描显式选择:

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

设置 auth: "api-key" 可强制使用环境中的 API key。preflight 接受相同的 auth 选项。

处理扫描错误

根据应用可以采取的操作,捕获对应的错误类:

错误 意义
AuthenticationRequiredError 扫描需要受支持的凭据。
ConfigurationError Codex 配置或覆盖不合适。
InvalidTargetError 仓库、路径、模式或 Git 目标不合适。
OutputDirectoryError 输出位置或其权限不合适。
OutputInsideProtectedRootError 输出目录位于扫描的仓库或工作树内。
PluginPythonUnavailableError 可用的 Python 解释器不可用。
PluginBootstrapError 插件运行时无法启动。
ScanCostLimitExceededError 扫描超出了其估计的成本限制。
IncompleteScanError 扫描在产生所需结果之前结束。
ContractValidationError 完成的扫描返回了结构化合约错误。
ScanInterruptedError 中断停止了扫描并可能留下了部分输出。

继续阅读 CLI 快速入门CI 指南CLI 参考