news 2026/9/23 17:37:13

Codex Security 制品存储策略:persistent / temporary 双栈管理、扫描归属权与证据导入规范

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Codex Security 制品存储策略:persistent / temporary 双栈管理、扫描归属权与证据导入规范
  • 应用安全
  • 漏洞扫描
  • AI 应用

【免费下载链接】codex-security

OpenAI's Codex Security CLI and TypeScript SDK for finding, validating, and fixing security vulnerabilities. npm: https://www.npmjs.com/package/@openai/codex-security

项目地址:https://gitcode.com/gh_mirrors/co/codex-security
点击查看免费下载

导读

artifact-storage.md是 Codex Security 插件(plugin)与独立制品产出型 Skill 必须遵守的制品(artifact)存储策略:它规定哪些文件可以用save_codex_security_artifact/read_codex_security_artifact写入,如何用scanIdtargetPath声明制品归属权,如何在persistent(持久)与temporary(临时)两种存储之间正确选择,以及共享威胁模型缓存、已完成扫描密封结果等边界规则。读完本文,你将掌握在插件托管扫描与独立阶段中安全、合规地创建、读取、导入和引用扫描制品的完整操作契约,并能从源码层面理解其路径校验、原子写入与上下文绑定的实现原理。

适用范围与职责边界

策略开篇先划清了「谁适用、谁不适用」的边界,避免策略被错误套用到其他工作流:

  • 适用:插件管理的扫描(plugin-managed scans)与独立产出制品的 Skill(standalone artifact-producing skills)。
  • 不适用一:显式由 SDK 拥有的工作流(explicitly SDK-owned workflow)保留其 SDK 提供的目录、既有的制品写入与完成行为,应遵循其自身既有指令,而非本策略。
  • 不适用二:受约束的 Deep worker 保留其既有的窄范围制品工具(narrow artifact tools)与只读执行画像(read-only execution profile)。

也就是说,本策略针对的是「由插件 MCP 管理、可写制品」的扫描路径,而 SDK 自有目录与 Deep worker 的受约束沙箱不属于本策略管辖。对应地,仓库中 compact-artifact-tools.ts 同时注册了面向主扫描的save_codex_security_artifact/read_codex_security_artifact,以及面向 Deep worker / reducer 的受限工具集(record_codex_security_scan_draftget_codex_security_deep_reducer_inputsrecord_codex_security_deep_reduction),后者正是「窄工具 + 只读画像」在源码层的体现。

扫描归属权:先取 scanId,再建制品

对于完整扫描(full scan),创建任何制品之前必须先从权威来源取得scanId。不同扫描模式使用不同的启动工具:

扫描模式启动方式说明
Standard 标准扫描start_codex_security_standard_scan插件 MCP 的标准扫描入口
Headless Diff(无扫描上下文的差异扫描)start_codex_security_prompt_only_scan必须携带精确的 target、mode: "diff"scope: "."diffTarget
Deep 深度扫描既有 Deep coordinator(协调器)沿用其既有协调流程

同时必须保留既有的 scan 与 handoff token(交接令牌)。如果所需 MCP 不可用,或所选基线(baseline)不受支持,应当上报阻塞原因(blocker),而不是回退到用 shell 手工编写 canonical 文件——这些规则优先于更早期的终端文件写入回退方案(terminal file-authoring fallbacks)。

在源码中,createScanArtifactContext(artifact-context.ts)通过 workbench 的get-scan --scan-id <scanId>命令解析扫描记录,校验状态是否为runningrequireRunning为 true 时非 running 直接拒绝修改),并核对handoffClaimToken:当扫描设置了期望的 claim token 时,缺省或错误的 token 都会被拒绝("requires its current continuation claim")。这印证了「先有权威 scanId + 正确 claim,才能写制品」的硬性约束。

另一条硬性规则是:结构化输出必须继续走各自既有的工具——inventory(清单)、candidate discovery(候选发现)、validation(验证)、attack paths(攻击路径)、semantic drafts(语义草稿)、checkpoints(检查点)与 completion(完成)。canonical 结果与恢复检查点(recovery checkpoints)即使在扫描运行期间也是持久的;绝不使用补充文件工具(save tool)去替换它们或生成report.md。这一点在 artifact-storage.ts 的supplementalPath校验中落地:persistent存储只允许artifacts/findings/hardening/前缀、report_validation.md与独立集合下的threat_model.md,并且命中 reserved_artifact_paths.json(如artifacts/02_discovery/candidate_ledger.jsonlartifacts/deep_discovery等)时会直接报错 "Use the existing scan tools for canonical artifacts, ledgers and checkpoints."。

补充文件:save / read 工具与两种存储

策略明确要求:Markdown 文档、可选的 finding 详细分析(write-ups)、加固文档/图表(hardening documents/diagrams)、验证证据(validation evidence)与保留的辅助输出(retained helper output),一律通过插件 MCP 的save_codex_security_artifactread_codex_security_artifact读写;不得用 shell 重定向、apply_patch、Python 或其他普通文件写入工具来写这些保留文件。

声明归属权(owner)

每次调用必须且只能声明一种归属:

  • 运行中的扫描:提供scanId,以及(在要求时)当前的handoffClaimToken
  • 独立阶段或扫描完成后的衍生文档:提供targetPath,指向被授权的仓库或输入文档目录。这会创建一个目标绑定的制品集合(target-bound artifact collection),但不会启动扫描,也绝不能编造 scan ID

supplementalContext(compact-artifact-tools.ts)严格执行 "Provide exactly one scanId or standalone targetPath",且handoffClaimToken在没有scanId时会被拒绝。独立路径会经standaloneArtifactContext(artifact-storage.ts)解析目标真实路径,用sha256(realpath)生成稳定的集合标识,并拒绝把制品集合建在目标仓库内部("Artifact storage must be outside the target repository."),同时以0o700权限创建目录。

显式选择存储:persistent 与 temporary

storage字段必须显式给出,二者语义截然不同:

维度persistent(持久)temporary(临时)
用途保留的文档/证据,位于权威扫描目录或独立集合下可丢弃的暂存与执行输出(staging / execution output)
默认根目录$CODEX_SECURITY_STATE_DIR/scans;未设置 state 覆盖时为$CODEX_HOME/state/plugins/codex-security/scansCODEX_HOME默认~/.codex上下文相关的 OS 临时目录
覆盖规则既有的CODEX_SECURITY_SCAN_ROOT覆盖仍然优先于插件创建的输出不依赖持久集合
状态回退若默认 workbench state 不可写,保留制品跟随其临时回退 state 的scans目录,可能被 OS 临时目录清理删除独立 temporary 保存/读取不创建也不要求持久集合
生命周期属于完成结果,可被 canonical 引用不属于完成结果,不得被 canonical findings 或 coverage 引用,可以独立于保留文件消失
已有扫描保留既有扫描的已保存路径(含更早的临时路径)——

server.ts中通过CONFIGURED_SCAN_ROOT = process.env.CODEX_SECURITY_SCAN_ROOT?.trim()CONFIGURED_WORKBENCH_STATE_DIR = process.env.CODEX_SECURITY_STATE_DIR?.trim()(server.ts)读取这两条环境变量,印证了文档中的优先级描述。

一个容易踩坑的细节:相对存储覆盖(relative storage overrides)从插件目录解析,与 MCP 启动目录无关,这与 workbench 的行为保持一致。也就是说,若调用中出现相对路径的存储覆盖,它以插件根目录为基准,而不是以启动 MCP 时的 cwd 为基准。

调用契约与参数约束

  • 准备目录:省略pathcontentsourcePath,工具会准备并返回所选目录;必须使用返回的directory绝不自行构造或猜测物理路径
  • 保存文件:必须提供path,且contentsourcePath恰好二选一("provide path and exactly one of content or sourcePath")。此校验在saveCodexSecurityArtifact开头强制执行(artifact-storage.ts)。
  • 返回值:物理path、canonicalrelativePath、内容摘要(SHA-256)。扫描证据引用(scan evidence references)中应使用持久相对路径。
  • 读取:使用与保存时相同的身份(scanId 或 targetPath)、storage与相对path二进制内容必须显式请求encoding: "base64"。读取 schema 中encoding枚举为utf8/base64,默认utf8(artifact-storage.ts)。

运行中扫描的三个典型调用示例(原文示例,可直接照用):

save_codex_security_artifact({ scanId, handoffClaimToken?, storage: "persistent", path: "artifacts/01_context/threat_model.md", content: "<exact Markdown>" }) save_codex_security_artifact({ scanId, handoffClaimToken?, storage: "temporary" }) save_codex_security_artifact({ scanId, handoffClaimToken?, storage: "persistent", path: "artifacts/02_discovery/validation_artifacts/<candidate_id>/poc.bin", sourcePath: "<returned temporary directory>/poc.bin" })

路径命名规则

path必须是artifacts/findings/hardening/下的可移植相对文件名(portable relative filename);report_validation.md同样受支持;独立集合(standalone collections)额外支持threat_model.md。每个阶段应沿用既有的相对制品布局(各阶段的目录约定见 scan-artifacts.md)。

源码层面的components校验(artifact-storage.ts)还做了跨平台防路径穿越:拒绝空段、...、Windows 非法字符<>:"\|?*、控制字符、以点或空格结尾的段,以及con/prn/aux/nul/com1-9/lpt1-9等保留设备名——保证「可移植相对路径」在 Windows 与 Unix 上都能安全落盘。

边界规则同样重要:源码/配置文件的编辑(source/configuration edits)与外部发布请求体(external-publication request bodies)不属于扫描制品,保留各自既有的工具与授权;显式用户指令仍然优先;如果所需输出目标无法由受管存储表示,应说明该限制,而不是静默替换为其他目标或谎称已写入。

生成证据与遗留辅助工具:temporary 暂存 + persistent 导入

PoC 执行和构建会在沙箱中产生文件,策略对这类「生成式证据」给出严格的两段式流程:

  1. 先准备temporary存储:只在返回的临时工作区(或其可丢弃的仓库副本)中运行经授权的 build/test/generation 命令;PoC 的源文件/输入文件用 save 工具以storage: "temporary"编写。
  2. 再按需导入persistent:最终记录中需要的每个文件,用storage: "persistent"+sourcePath(必须位于同一个返回的临时目录内)导入;生成 inventory、归一化输出或其他文件的工具必须接收临时输出路径。

两条红线:

  • 导入实际字节,而不是模型对二进制输出或日志的转录(Import the actual bytes, not a model transcription)。二进制文件以 base64 方式读取、以源文件路径原样搬运。
  • 没有正当理由不得保留整棵依赖/构建树(Do not retain entire dependency/build trees without a reason)。

在实现上,storageContext(artifact-storage.ts)在tmpdir()下以codex-security-artifacts-<sha256(context.root)>命名临时根;saveCodexSecurityArtifactsourcePath导入分支要求storage === "persistent",并强制源文件必须解析到该上下文临时目录内部(relative()检查绝对路径或..逃逸即拒绝),随后读取实际字节写入目标。

对于独立/遗留的可变账本(legacy mutable ledgers,如 standalone 模式下的老式 ledger),应使用 save 工具替换其完整内容,或导入 helper 产出的临时文件,不得直接向保留的扫描目录追加。当前 Standard 与 Deep 扫描已不再引入遗留 inventory 或 ledger。

共享威胁模型缓存与已完成结果

共享威胁模型的读写规则

对于共享仓库威胁模型(shared repository threat model):

  • 使用targetPath: <repo_root>storage: "persistent"path: "threat_model.md"定位缓存集合;
  • 仅当威胁模型工作流允许缓存复用(cache reuse),且其精确的仓库/版本页脚(footer)匹配时,才读取该集合的缓存文件;
  • 运行中的扫描应把选定的精确文本保存到artifacts/01_context/threat_model.md,并使用该运行扫描的scanId
  • 存储工具并不授权更新共享缓存——工作流中禁止读取或替换共享缓存的既有条件必须被保留。

每个共享威胁模型必须以恰好两行结尾:

Repository: <stable target identity from scan-contract.md> Version: <revision for an immutable Git tree; snapshot digest otherwise>

其中<stable target identity>与修订/快照摘要的语义在 scan-contract.md 定义(git_worktree/directory_snapshot/git_diff/git_revision等目标种类与requiredSnapshotDigest/ revision 字段)。scan-artifacts.md同时规定:后续扫描阶段应以<context_dir>/threat_model.md为事实来源。

密封结果不可变

  • 已完成/密封(completed/sealed)的扫描文件不能通过 save 工具编辑;后续的 write-up 或加固请求应使用独立目标集合(standalone target collection),并把返回的文件单独链接引用,保留原始结果及其引用不变。
  • 临时清理不得删除保留文件或恢复检查点
  • save 工具在**与 finalization 相同的完成锁(completion lock)**下发布运行中扫描的文件;遇到已停止/密封扫描的拒绝(stopped/sealed-scan rejection)时要如实反馈,并保留既有输出。

对应地,createScanArtifactContextrequireRunning时对非 running 扫描直接抛出 "its artifacts cannot be modified",从机制上保证密封结果无法被改写;replaceArtifactText(artifact-io.ts)以同目录.tmp文件 +rename的方式原子替换,并在.lock文件上自旋等待(最多 500 次、每次 20ms),确保并发写入互斥,这也正是「完成锁」语义的底层支撑。

从源码看实现原理

1. 目录准备与根校验

所有制品操作都通过requireArtifactRoot(artifact-io.ts)校验:根必须是绝对路径、非符号链接、真实存在的常规目录,并realpath归一化。读写路径的每个组件都会经过validateArtifactComponents拒绝空串、...、斜杠与\0;文件读取时对每一级做lstat,拒绝符号链接与非常规文件,并二次确认realpath未逃逸绑定根("escaped its bound context")。这意味着即使模型传入恶意路径,也无法借助符号链接把读写引到扫描目录之外。

2. 上下文绑定与权限模型

ArtifactContext(artifact-io.ts)携带rootrepoRootlayoutscanIdhandoffClaimTokenmodetargetContract等字段;createScanArtifactContext只从 workbench 的持久化扫描记录构造(host-bound),注释明确 "Never construct this object from model tool input."。注册工具时(compact-artifact-tools.ts),读工具标记readOnlyHint: trueidempotentHint: true,写工具标记readOnlyHint: false,且全部为modelOnlyMeta(仅模型可见),把「哪些工具可写、哪些只读」暴露给宿主。

3. 环境变量与根目录解析

server.ts在启动时读取CODEX_SECURITY_SCAN_ROOTCODEX_SECURITY_STATE_DIRresolve-scan-root等 workbench 命令无需数据库即可运行(WORKBENCH_COMMANDS_WITHOUT_DATABASE)。这与文档中「默认根$CODEX_SECURITY_STATE_DIR/scans→ 回退$CODEX_HOME/state/plugins/codex-security/scansCODEX_SECURITY_SCAN_ROOT优先」的优先级描述一一对应。

测试验证:策略如何被证明

仓库测试从正反两面验证了上述契约:

  • test_artifact_storage.mjs 验证:默认 scanDir 位于state/scans/<target>下(持久)、temporary 目录位于tmpdir()下且不在scanDir 内;content精确字节往返(含尾部空格);二进制文件先写入 temporary 再以sourcePath导入 persistent,读取时encoding: "base64"得到一致字节;目录外文件(outside.txt)被拒绝导入。
  • test_artifact_storage_regressions.mjs 针对CODEX_SECURITY_SCAN_ROOT/CODEX_SECURITY_STATE_DIR/CODEX_HOME三者的覆盖优先级与回退行为做回归,验证了文档中根目录解析与临时回退 state 的规则。

这些测试与策略文档互相印证:先取权威 scanId、显式选 storage、用 save 工具写入、从返回的 temporary 目录导入、引用 persistent 相对路径、绝不触碰密封结果,是插件托管扫描与独立阶段产出可信、可追溯制品的完整闭环。对于更完整的路径布局(artifacts_dir01_context02_discovery03_coverage04_reconciliation05_findings及最终report.md/hardening/等),可继续阅读 scan-artifacts.md 与 scan-contract.md。

  • 应用安全
  • 漏洞扫描
  • AI 应用

【免费下载链接】codex-security

OpenAI's Codex Security CLI and TypeScript SDK for finding, validating, and fixing security vulnerabilities. npm: https://www.npmjs.com/package/@openai/codex-security

项目地址:https://gitcode.com/gh_mirrors/co/codex-security
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/23 17:34:24

PyTorch从零实现贝叶斯神经网络:量化模型不确定性

简介&#xff1a;本资源是一份面向机器学习进阶学习者与研究者的贝叶斯神经网络实践教程代码包&#xff0c;聚焦于不确定性建模与概率深度学习核心能力培养&#xff0c;适用于小样本学习、模型校准、医学图像置信预测等高可靠性场景。压缩包共12个文件&#xff0c;含6个Python源…

作者头像 李华
网站建设 2026/9/23 17:34:21

信息链全解析:从理论模型到数据管道落地实践

上周有个朋友问我&#xff1a;一个用户需求从提出到最终变成产品功能&#xff0c;中间的环节到底有多少机会“走样”&#xff1f;我说&#xff0c;你先去把信息链&#xff08;Information Chain&#xff09;这个概念吃透&#xff0c;答案自然就出来了。信息链&#xff08;Infor…

作者头像 李华
网站建设 2026/9/23 17:27:49

模型压缩实战:蒸馏与剪枝源码解析及边缘部署优化

简介&#xff1a;这份资源是面向毕业设计与模型压缩入门者的Python代码仓库&#xff0c;聚焦基于知识蒸馏与剪枝的识别算法实现&#xff0c;适合具备一定深度学习基础、需要完成相关课题或复现压缩实验的学生与开发者。压缩包共185个文件&#xff0c;约4.03MB&#xff0c;以79个…

作者头像 李华