dsh-security-assurance
DeepSeek Harness 策略驱动的仓库安全评估插件,支持包生命周期评估、证据、发现、裁决、导出和 /security 指令。 | Policy-driven repository security assurance plugin for DeepSeek Harness with package lifecycle assessments, evidence, findings, verdicts, exports, and /security routing.
- Stars
- 1
- Language
- TypeScript
- Created
- Aug 31, 2026
- Updated
- Sep 29, 2026
Introduction
DSH Security Assurance
DeepSeek Harness 的策略驱动仓库安全评估插件 · 中文默认,English below
中文
这是什么
dsh-security-assurance 为 DeepSeek Harness 提供证据驱动的仓库安全评估。它通过公开的 Harness/Cordis 接口接入,不修改 Harness Core,并把评估过程封装为可查询、可恢复、可审计的版本化结果。
这是一个安全保障插件,不是通用漏洞扫描器。当前内建能力包括 Node 项目的 package.json 安装生命周期检查、npm 发布面、pnpm 锁文件完整性、GitHub Actions 权限与不可变依赖检查,以及对冻结 npm-audit.json 和 Gitleaks v8 JSON 报告的纯归一化与独立验证。
一次扫描发现不等于可审计的安全结论:输入可能被篡改、截断,或与冻结仓库不一致。Security Assurance 只接收冻结 Subject 上的已验证 slice,并在独立验证和 sealed submission 后给出 verdict。
评估如何形成可信结论
Service 先解析授权 Catalog 选择并冻结完整 Subject,再把已验证 slice 交给合格的 PURE Analyzer 或报告归一化器。Candidate 和 Coverage 必须经过独立复核,Kernel 才能计算 SATISFIED、FAILED 或 INDETERMINATE,并为终态 Assessment 生成摘要绑定的 Submission。
当前版本
- 版本:
0.1.0-rc.17 - 状态:Release Candidate(预发布版)
- 适配:DeepSeek Harness
0.1.2-alpha.1(主目标);0.1.2-alpha.2至0.1.2-rc.1、0.1.3-alpha.1、0.1.3-alpha.2、0.1.5-alpha.1、0.1.5-alpha.2、0.1.5-rc.1、0.1.5-rc.2、0.1.5-rc.3、0.1.7-alpha.2、0.1.7-rc.1、0.1.7-rc.2与0.2.0-rc.1经兼容矩阵验证 - GitHub:v0.1.0-rc.17 Release
支持范围
| 项目 | 当前状态 |
|---|---|
| 评估模式 | REPOSITORY、精确提交或 Mission 产出工作区的 CHANGE,以及默认策略的 TARGETED |
| 支持 Subject | git_revision、workspace_snapshot、change(精确 base/head);Control Plane 可使用 Host 专用 workspace_change |
CHANGE 模式 | 支持精确已提交的 base→head,以及 Control Plane 冻结的 baseline→produced workspace;均扫描完整结果树 |
TARGETED 模式 | 内建 Node 生命周期与 GitHub Actions 策略支持 git_revision、workspace_snapshot 的明确相对文件/目录;只读取目标内的相关清单或 workflow |
| 默认策略 | security/node-package-lifecycle |
| 可选 npm audit 策略 | security/npm-dependency-audit |
| 可选 Gitleaks 策略 | security/secret-leak-audit |
| 可选 GitHub Actions 策略 | security/github-actions-supply-chain |
| 可选 npm 发布面策略 | security/npm-publish-surface |
| 可选 pnpm 锁文件策略 | security/pnpm-lockfile-integrity |
| 评估档案 | security/standard(当前唯一已资格化档案);security/deep 与 Host 自定义档案在独立多轮分析组合落地前 fail closed |
| 受治理角色目录 | 固定为 threat-modeler、discovery-analyst、validation-analyst、attack-path-analyst、challenge-analyst;每个条目都有版本化摘要谱系并绑定进 Start Preflight,但当前仍无已资格化执行 Provider |
| Harness 版本 | 0.1.2-alpha.1(主)、0.1.2-alpha.2、0.1.2-alpha.3、0.1.2-alpha.4、0.1.2-alpha.5、0.1.2-rc.1、0.1.3-alpha.1、0.1.3-alpha.2、0.1.5-alpha.1、0.1.5-alpha.2、0.1.5-rc.1、0.1.5-rc.2、0.1.5-rc.3、0.1.7-alpha.2、0.1.7-rc.1、0.1.7-rc.2、0.2.0-rc.1 |
| Node.js | ^22.19.0 || >=24.0.0(CI 覆盖 22 与 24) |
| 支持平台 | Windows、Linux、macOS |
评估会先读取当前 Host 注册的 Repository 和 Catalog;只有 Service 返回的精确 ID、模式、Subject、Target、Profile 和强化控制才能用于启动,不允许模型猜测路径或标识符。
当前 v0.1 Analyzer 资格只证明 security/standard 路径。若 Repository 绑定 security/deep 或 Host 自定义档案,Catalog 和 Start Preflight 会明确报告不支持;即使调用方省略 preflight 直接调用 Service,也只能形成 INDETERMINATE,不会把 Standard PURE Evidence 冒充为更强档案的 Coverage。
Security Catalog 同时公开固定五角色的有界能力摘要。每个条目都由包内拥有的版本与确定性摘要标识,Start Preflight 会把同一精确目录纳入提案摘要。所有角色均为 PROPOSAL_ONLY,不能审批、接受风险或决定 Verdict;Catalog 条目谱系不等于可执行 Role Definition,在完整定义与已资格化 Subagent Provider 组合落地前,其执行状态保持 UNSUPPORTED,Deep Preflight 会单独报告 NO_ELIGIBLE_ROLE_COMPOSITION。
公共 root 还提供 authority-free 的 RoleContextGrantV1 契约工具。Grant 只绑定受保护的 Subject Inventory、Source Slice 与 Evidence artifact 引用、明确的披露类别、同伴输出可见性以及字节和 Token 上限;不携带源码正文、工作区根路径、父会话、凭据、Store、Cordis Context 或执行能力。创建结果使用确定性摘要并深冻结,接收方解析时会重新计算摘要,并对篡改、预算越界、未披露类别和重复引用 fail closed。该契约本身不会启动 Subagent,也不代表 Provider 已资格化。
同一公共 seam 提供确定性 SourceSliceRequestV1 创建、解析和静态 preflight。请求绑定精确 Context Grant、Subject、Role Attempt、purpose、Coverage obligation、规范化 Subject 相对路径、预期原始字节摘要、egress 选择和申请预算;解析会拒绝篡改。Preflight 会一次性报告陈旧绑定、范围或 egress 扩张及预算越界,但成功状态仅为 MATERIAL_REVIEW_REQUIRED:Service 仍须重新证明 Subject containment、源摘要完整性、敏感度、secret redaction、Data Egress、实际预算和 Role need,之后才可能生成新的不可变 Grant。该工具不读取源码、不调用 Provider,也不签发 capability。
包内受保护读取层现可接收该精确 Grant 与 Request,重新执行静态 admission,并从内容寻址 Subject Snapshot 读取一个目标内文件。它会重新核验完整 Subject、冻结 Target containment、Request/Manifest/实读原始字节三方摘要,以及实际字节预算;返回值深冻结且不从包 root 导出。该本地材料尚未通过敏感度、secret redaction、Data Egress 或 Role need 审查,因此不能发送给 Provider,也不能生成新的 Context Grant。
包内 secret 检查层可对这份本地材料运行有版本的高置信模式集,并只保留类型、UTF-16 位置和使用 Host 提供密钥生成的 HMAC-SHA-256 指纹。原始匹配值与指纹密钥不会进入返回记录;弱密钥、正文摘要漂移或非规范路径会 fail closed。该检查是有意受限的检测器:即使没有命中,结果仍是 ADDITIONAL_REVIEW_REQUIRED,绝不据此宣称正文不含 secret,也不会授权 egress。
同一包内层可将每个已检测值替换为带类型的固定占位符,并分别摘要绑定脱敏后的 UTF-8 正文与完整脱敏记录。接收方会针对原受保护材料重新核对源绑定、检测位置、替换覆盖和两个摘要;记录不保留原始匹配值。REDACTED_MATCHES_REVIEW_REQUIRED 仅说明已知高置信命中已被替换,仍不等于完整 secret clearance 或 Data Egress 授权。
包内敏感度分类方法随后以固定版本对精确材料和脱敏记录进行保守标注:所有源码至少为 PROTECTED_SOURCE,.env、凭据文件和私钥容器等敏感路径提升为 RESTRICTED_SOURCE,已有高置信 secret 命中则提升为 SECRET_BEARING_SOURCE。接收方会重算分类与摘要并拒绝即使摘要自洽的降级。该方法只分类、不放行披露,也不冒充尚未实现的 Policy Compiler 或已编译 Security Policy。
包内 Data Egress 审查随后重新执行 Grant/Request 静态 admission、核对完整材料与脱敏摘要链,并按脱敏后的实际 UTF-8 字节重新计量。它还把同一精确 Slice 的合格 secret-review 摘要纳入自己的摘要链:完整 CLEAR 可清除 secret 复核缺口,SECRET_FOUND 会拒绝 egress,缺失或不确定则继续 fail closed。egress/deny-by-default 必定得到 REJECTED;其他策略在 Broker 资格或目标授权缺失时保持 BROKER_REVIEW_REQUIRED。只有在显式评估时点仍有效的 Host-attested Broker Qualification 与 Host Destination Authorization 精确绑定 Provider、非秘密凭据引用、策略、目的地、类别、Slice 摘要、单次请求配额、超时和审计策略时,才会清除这两个缺口并推进到 BROKER_INVOCATION_REQUIRED。该步骤仍没有 approved 状态,不解析凭据、不访问网络,也不调用 Provider。
在此基础上,包内签发器可重新按签发时点准入同一组 Broker 与目标证据,并生成一个不可序列化、只能使用一次的 Source Slice Egress Capability。它把固定的脱敏正文和非秘密凭据引用绑定到精确 Role Attempt、generation、围栏摘要、Data Egress 策略、请求/token 配额及有效截止时间,只能调用身份完全匹配的注入 Broker Adapter。Attempt 结算、调用取消或超时会中止飞行中的 adapter;Broker 返回的 Provider/目标、schema 或用量漂移均 fail closed。成功和失败都会得到不含请求或响应正文的摘要绑定审计回执。该能力仍为 package-private,尚未注册生产 Broker Adapter 或持久化回执,也不代表 Material Review、Context Grant 或 Verdict 获得批准。
完成态 Broker 回执现在可与 Kernel 所有的预算预留及冻结调用谱系一起交给包内纯结算模块,形成一条不含 Prompt、源码或响应正文的受保护 Model Invocation Record。预算预留在结算前固定 Context Grant、Role Attempt generation 与围栏、egress authorization、Broker request、单次请求/token 上限和截止时间;结算会重验完整回执,并绑定 Provider/backend/deployment/model 与 Moving Provider 状态、Role 和 Prompt 版本、Prompt 与 Tool Schema 摘要、参数和随机性策略、起止时间、实际请求与 token 用量、原始响应字节摘要、finish reason、Broker diagnostics 及父 Attempt。实际 input/output token 会从预留中计费,只有未使用部分被释放;调用参数本可越界、完成时刻达到截止线、摘要或请求替换均 fail closed。包内发布层还可重验完整 Context Grant,由此派生可信 assessment 与 Subject,并在核对精确 Attempt 绑定后,把记录作为规范 JSON 内容寻址对象原子发布到 Evidence 层;摘要绑定收据同时固定 invocation、父 Attempt generation 与围栏、record digest 和 Evidence digest,重复发布同一对象保持幂等,读取时会重验完整绑定。收据不暴露路径或正文,相关模块也不从包 root 导出。包内持久化层现可在隔离会话启动前原子创建不可变的 RUNNING Role Attempt,并在成功返回后以精确 Assessment revision、generation 和围栏执行至多一次的 COMPLETE/PARTIAL 结算;记录固定 Context Grant、Role、Provider/model、Prompt 与 Tool Schema 摘要、父 Attempt、预算、里程碑及结果计数,同时更新 Role Card 投影并追加 Revision Journal。已发布的 Model Invocation Evidence 只有在精确 Role Attempt 仍为 RUNNING,Grant 与围栏一致,且受保护调用记录中的 Role、Provider/model、Prompt 与 Tool Schema 谱系均与 Attempt 相符时才能关联;其关系行通过复合外键指向该 Attempt,随后 Evidence revision 的推进不会阻断 Attempt 完成。精确重放保持幂等,冲突结果、陈旧 revision/围栏、非运行态或 Subject 漂移均整体回滚并 fail closed。已发布的 schema-v1 Store 首次打开时,会依次经过各自拥有一致性备份、完整验证、独占迁移租约和摘要绑定历史的 v2、v3 迁移;含既有逻辑 Evidence 关联却缺少可证明 Attempt 行的 v2 Store 会被拒绝,未知版本同样被拒绝。当前还支持 required Role Attempt 的显式 FAILED 结算:失败代码、用量与已有计数会和 Role Card、Revision Journal 及 Assessment BLOCKED 状态原子提交,公共恢复投影会标识精确 ROLE_EXECUTION Attempt,并要求授权 Resume。Assessment 取消请求会先阻断晚到结果准入;只有调用方证明清理完成且执行静默后,终止提交才会在同一 revision 把仍为 RUNNING 的 Role Attempt 与 Role Card 转为 CANCELED。恢复不会复用或抹去旧 Attempt;同一 Role 的新 Attempt 必须使用新身份,并引用同一 Assessment 内 FAILED/CANCELED 的父 Attempt,缺失、未终止或定义漂移的父谱系均 fail closed。自动执行图调度、生产会话生成、单 Role 清理证明和 Broker 注册仍未实现;它也尚未生成 ADR 0197 定义的 Evidence Link 或准入 canonical Assessment Bundle。失败或用量不可验证的 Broker 回执不会被伪造成完整 Model Invocation Record,Material Review 的 ACTUAL_BUDGET 也尚不会自动转为满足。
模型的终态提案现在还可进入包内 RoleContributionV1 契约:规范摘要固定 Assessment、Subject、Context Grant、精确 Attempt generation 与围栏、Role Definition、全部 Model Invocation record/响应摘要,以及结构化 hypothesis、Candidate Finding、Coverage observation、Evidence 上下文与请求、challenge、Follow-up Request、限制、不确定性、完成状态和精确汇总用量。严格解析会拒绝未知的授权字段、重复或悬空引用、非规范或越界 Source Anchor、用量漂移、超大记录和摘要篡改;持久化准入只冻结该受保护谱系并驱动 Attempt 完成计数,不创建 Finding 或 Coverage Resolution,也没有 Verdict、Risk Acceptance 或任何公共 capability。
已接纳 Role Contribution 中的 Candidate 现在还会经过独立的包内纯准入边界。该边界重新核验 Context Grant、Contribution 与其耐久 Admission Link 的精确 Assessment、Subject、Role、Attempt generation/围栏、调用、用量、计数、revision 和摘要谱系;每个 Source Anchor 必须命中服务侧提供且重新按原始字节核验的冻结 Subject slice,并且 byte span 不得越界;每个 Candidate Evidence ID 必须位于调用方确认的耐久对象集合。整个 Candidate 批次全有或全无,成功结果拥有独立 Candidate/Admission 摘要并深冻结;失败只返回固定代码的受保护诊断。schema v6 进一步把一次调用方标识的准入尝试作为单一 Assessment 事务提交:成功时写入摘要绑定批次及逐 Candidate 记录,失败时只写固定错误码、可安全识别的 Candidate ID 和请求摘要,不保存源码或失败正文。精确成功/拒绝重放在 Store 重开后仍不推进 revision,冲突 attempt、陈旧 revision、已取消或非运行态 Attempt 均 fail closed;先前拒绝可用新的 attempt 在缺失的耐久输入补齐后重试。准入本身仍不会创建 Finding、Coverage Resolution、聚类、Evidence 合并或 ADR 0197 Evidence Link。
在该耐久准入之后,新的包内纯验证边界会先依据 Candidate 的弱点与受影响控制、Assessment 的精确 Policy 摘要和 Mode、生态、执行边界及资格有效期,从完整候选目录中冻结唯一的版本化 Validation Contract Resolution;无合格 Contract 或多个同样适用的 Contract 都会显式保持未决,证据结果不能反向改变选择。三态 Validation Outcome 只由调用方确认耐久的精确 Evidence 身份、用途专属 Evidence Eligibility Decision、Contract 条件、必需 negative controls 及绑定完整 provenance graph 的独立性判定推导:只有满足 Claim 条件才会 VALIDATED,只有合格 Counter-Evidence 满足明确拒绝条件才会 REJECTED,缺证、依赖同源、缺少控制,或正反两方各有任一合格证明(不论哪方谱系更多)一律 UNRESOLVED。schema v7 先用一个 Assessment revision 单独追加 validation attempt 的 Contract Resolution,只有后续事务才能在下一 revision 追加 Outcome,因此不能在看到结果后再选 Contract;两阶段的精确重放都不推进 revision,当前读取按精确的 Contribution 与 Candidate 身份选择最新 Outcome,重开时重新推导并核验 Candidate Admission、Contract、Outcome 与 Revision Journal 的完整绑定。该层仍不调用 Provider、不创建 Finding/Coverage Resolution、不合并 Evidence、不生成 ADR 0197 Evidence Link,也不扩展公共 API。
若原始 Role 输出未通过严格 JSON 与 schema 校验,包内格式修复边界现在只接受预先摘要绑定的一次独立调用。修复计划固定 Context Grant、Role Definition、Attempt generation 与围栏、原始及修复 invocation 身份、Provider/model、确定性参数、单请求/token 预算,以及包所有的无授权语义载荷 schema 和语法指令。发送给修复 Provider 的受保护请求正文只能包含原始响应、目标 schema 与语法指令,其摘要必须与修复 Model Invocation Record 完全一致。修复结果只有在严格载荷校验通过且有序 JSON 标量序列与原始响应完全相同时才可组合;Contribution 的身份、两条调用谱系和精确用量由 Service 补齐,模型不能自报这些字段。原始输出本已有效、Markdown 围栏或启发式抽取、标量增删改序、第二修复身份、越权字段、原始字节、Prompt、Provider、时间或预算漂移都会 fail closed。该包内纯边界尚不调用 Provider、不自动重试、不写 Store,也不改变公共契约。
包内纵向 material-review 操作会从内容寻址 Subject 重新读取精确 Request,自行完成上述检测、脱敏、敏感度分类和 egress 审查,最后只返回不含正文的不可变记录。记录以固定顺序覆盖七项 material check,并绑定 Grant、Request、Subject、原始源、检测、脱敏正文、脱敏记录、敏感度分类、secret review、Broker/Destination authorization 和 egress 审查的完整摘要链。Containment、原始源摘要完整性与保守敏感度分类可在本地标记为 SATISFIED;SECRET_REDACTION 还可由专用作用域下 Kernel 判定合格的 Analyzer Portfolio 与 Contribution 推进,但只有精确绑定脱敏 Slice、资格仍有效并引用 Host 资格记录中独立性 Evidence 的完整 CLEAR 结果才会满足并清除 egress 中对应的 secret 缺口。残留 secret 会同时拒绝 secret 与 egress 检查,缺失、不确定、过期、范围错配或摘要漂移均 fail closed。现有 Gitleaks 资格只覆盖冻结报告归一化,不能冒充这一 clearance。即使 Broker 与目标证据完整,Data Egress 也只会要求后续 Broker invocation;Token 实测与 Role need 仍为 REVIEW_REQUIRED,因此该操作没有整体 approved 状态、不会签发 Grant,也不会调用 Provider。
TARGETED 仍会冻结并摘要绑定完整 Subject,但只把明确目标内、经过验证的相关 slice 交给内建分析器:Node 生命周期策略读取 package.json,GitHub Actions 策略读取 .github/workflows/*.yml|yaml。每个目标必须对应一个现有条目或目录前缀;不存在的目标会在创建 Assessment 前被拒绝。npm 发布面、npm audit、Gitleaks 与 pnpm 锁文件策略暂不声明 TARGETED 支持,因为它们的根部或外部输入目前不能独立证明与目标完全一致。
Harness 支持窗口是一个显式的已验证集合:每日 Harness Compatibility 工作流自动发现官方仓库标签,对主目标在 Ubuntu、macOS、Windows 上、对其余版本在 Ubuntu 上执行双插件联合 E2E(Mission → Developer 工作区变更 → CHANGE Assessment → sealed submission → Quality Gate)和打包 fresh Profile 安装加 Web 探针。新标签会自动进入验证,但未通过矩阵验证前不会被声明支持(ADR 0310)。
独立工具与 Workbench 的 Catalog 契约保持不变,只向模型提供精确提交 change。当 Control Plane 完成 Developer 与 Implementation Evidence 后,Provider 会从不可伪造的执行上下文接收 Host 专用 workspace_change,同时核对分支、baseline HEAD、Git 状态指纹、逐字节产出变更指纹与完整结果树;任何漂移都会在创建 Assessment 前 fail closed。
3 分钟最短安装(Harness Web)
兼容 DeepSeek Harness 0.1.2-alpha.1 至 0.1.2-rc.1、0.1.3-alpha.1、0.1.3-alpha.2、0.1.5-alpha.1、0.1.5-alpha.2、0.1.5-rc.1、0.1.5-rc.2、0.1.5-rc.3、0.1.7-alpha.2、0.1.7-rc.1、0.1.7-rc.2 与 0.2.0-rc.1(显式已验证集合,见上方支持范围),要求 Node.js ^22.19.0 || >=24.0.0 和 Harness CLI。将终端当前目录设为要评估的 Git 仓库,然后直接安装 GitHub Release 中已经构建的包:
- 下载对应 Release 的 tarball。
- 在目标仓库目录安装插件并检查最终组合。
- 启动 Harness Web,然后运行一个明确的
/security评估。
dsh plugin --profile web add https://github.com/bailong-Hakuryu/dsh-security-assurance/releases/download/v0.1.0-rc.17/dsh-security-assurance-0.1.0-rc.17.tgz
dsh --profile web --dump-config
dsh web
也可以先在 Release 页面下载 dsh-security-assurance-0.1.0-rc.17.tgz,再把上面 URL 换成本地文件的绝对路径。
如果还要使用工程 Mission 门禁,请先安装 Engineering Control Plane,再安装本插件:
dsh plugin --profile web add D:\Downloads\dsh-engineering-control-plane-0.2.2.tgz
dsh plugin --profile web add https://github.com/bailong-Hakuryu/dsh-security-assurance/releases/download/v0.1.0-rc.17/dsh-security-assurance-0.1.0-rc.17.tgz
dsh --profile web --dump-config
dsh web
插件会把启动时的工作目录注册为 current-workspace。启动后建议先用 dsh --profile web --dump-config 检查组合;如果端口已被占用,请在 Harness Profile 中选择其他空闲端口。
用户如何调用
插件同时支持被动路由和主动指令:
被动调用(推荐):直接描述目标,模型会先获取可用仓库和评估目录,再按服务返回的选择启动评估。
请对当前仓库进行安全评估,并报告最终 Verdict 和 Findings。
检查当前项目的 package.json 安装生命周期配置。
主动调用:在 Harness Web 或 CLI 输入:
/security 评估当前仓库
/security 检查当前仓库的包安装生命周期
/security 只检查 packages/api 和 packages/web 的包安装生命周期
在 Harness Web 中,这八个工具的调用会显示为专用的安全卡片,而不是通用工具行:一行标题与摘要,配以状态、结论和严重程度标签,展开后可查看详情和原始输入输出。卡片只读取会话中已有的工具调用记录,不调用服务、不持有任何权限(ADR 0322)。涉及某个 Assessment 的卡片会在行尾提供「在工作台中打开」,一键进入该 Assessment 的工作台详情(ADR 0323)。
安全保障工作台:点击 Harness Web 侧栏底部的「安全保障」即可打开工作台,浏览可见的 Assessment、查看进度、Findings、Evidence 元数据与 Bundle,并在已注册仓库上经目录预检后新建 Assessment。工作台使用的权限与上述模型工具相同:读取、启动、恢复、取消 Assessment,以及请求和读取导出。风险决策、紧急授权、敏感 Evidence 披露和导出下载仍只能由部署方的认证解析器授予(ADR 0321)。
npm audit 报告适配
npm audit 由 Host、CI 或操作者在评估外部执行;插件不会在 PURE 分析边界内启动 npm、访问 Registry 或读取实时网络状态。先生成 UTF-8 报告,并确保它在评估启动前包含于所选 Subject:
npm audit --json | Set-Content -Encoding utf8 npm-audit.json
将 Repository 的策略绑定设为 security/npm-dependency-audit。适配器会按冻结字节和摘要读取 npm-audit.json:干净且完整的报告得到 SATISFIED;经独立契约复核的漏洞得到阻塞 Finding 和 FAILED;报告缺失、格式不受支持、Coverage 不完整或 Evidence 被篡改时得到 INDETERMINATE。报告新鲜度仍由生成报告的 Host/CI 负责。
Gitleaks 报告适配
Gitleaks 同样由 Host、CI 或操作者在评估外部执行。推荐启用完全脱敏,并把 UTF-8 JSON 报告纳入评估 Subject:
gitleaks dir . --redact=100 --report-format=json --report-path=gitleaks-report.json
将 Repository 的策略绑定设为 security/secret-leak-audit。PURE 适配器只保留规则 ID、受影响相对路径和位置;Secret、Match、源代码行、秘密哈希、作者邮箱与提交消息不会进入 Candidate、Finding、Evidence、Seal 或导出。完整空报告得到 SATISFIED;独立复核的任意报告项得到 HIGH、阻塞 Finding 和 FAILED;缺失、无效、被篡改或不完整的报告得到 INDETERMINATE。扫描配置、报告新鲜度、Git 历史范围和 allowlist 正确性仍由 Host/CI 负责。
GitHub Actions 供应链策略
将 Repository 绑定到 security/github-actions-supply-chain 后,插件只读取冻结 Subject 中、当前 Target 选中的 .github/workflows/.yml 与 .yaml。PURE 分析器不会执行 workflow 或访问 GitHub;它要求顶层 permissions 显式为只读或空权限,拒绝 job 级写权限,并要求外部 Action/可复用 workflow 使用完整 40 位提交 SHA、container Action 使用 sha256 镜像摘要。本地 ./ Action 不会被误报。
完整解析会在独立验证契约中重新执行。安全或空的目标 workflow 集得到 SATISFIED;已验证违规得到阻塞 Finding 和 FAILED;重复键、alias、无效/不支持的 YAML 或被篡改的 Contribution 得到 INDETERMINATE。该严格策略不判断写权限是否“业务上合理”;确需写权限的发布 workflow 应使用另一份经过评审的 Policy,而不是在本策略里静默放行。
npm 发布面策略
将 Repository 绑定到 security/npm-publish-surface,即可离线验证冻结根部 package.json 的发布声明:公开包身份、公开访问、显式 files allowlist,以及 exports、main、types、bin 目标都必须被该 allowlist 包含。它不会运行 npm pack、枚举文件系统、访问 Registry,也不声称文件真实存在、包来源可信或依赖安全。
一致清单得到 SATISFIED;私有包、受限发布、缺少显式 allowlist、过宽模式或未被 allowlist 包含的入口得到经独立重导验证的阻塞 Finding 和 FAILED;格式错误、重复 JSON 键、非法入口或被篡改的 Contribution 得到 INDETERMINATE。v1 只支持 REPOSITORY 与 CHANGE,并且只证明清单自洽,不替代真实打包工件证明。
pnpm 锁文件完整性策略
将 Repository 绑定到 security/pnpm-lockfile-integrity,即可离线比较冻结 Subject 根部的 package.json 与 pnpm-lock.yaml。PURE Analyzer 要求 packageManager 精确固定到一个 pnpm 语义版本、pnpm v9 根 importer 与三类依赖声明逐项一致,并要求每个外部 package resolution 带有效 SRI。它不会运行 pnpm、安装依赖、访问 Registry 或声称依赖无漏洞。
一致输入得到 SATISFIED;缺失锁文件、清单漂移、未固定包管理器或缺失 SRI 得到经独立重导验证的阻塞 Finding 和 FAILED;重复 JSON 键、YAML 别名、格式错误、未知 lockfile 版本、非 pnpm 包管理器或被篡改的 Contribution 得到 INDETERMINATE。v1 只覆盖根 importer,并且只支持 REPOSITORY 与 CHANGE,不会把 workspace 子包冒充成已检查范围。
工具工作流
| 顺序 | 工具 | 作用 |
|---|---|---|
| 1 | security_repositories | 列出当前会话可见的已授权仓库;启动目录对应的仓库带 hostBindingIds: ["current-workspace"] |
| 2 | security_catalog | 获取指定仓库支持的模式、Subject、Profile 和控制 |
| 3 | security_assessment_start | 用精确选择启动一次持久化评估 |
| 4 | security_assessment_status | 读取版本化状态、Coverage 和 Verdict |
| 5 | security_assessment_findings | 分页读取脱敏 Finding 摘要;锚点纯净时附带仓库内相对位置(路径与 JSON 指针) |
| 6 | security_assessment_resume | 仅按服务公布的合法动作恢复阻塞评估 |
| 7 | security_assessment_cancel | 按精确 revision 取消并等待外部工作静默 |
| 8 | security_assessment_export | 请求固定格式、固定目标的官方导出 |
推荐顺序是 repositories → catalog → start → status → findings。变更操作使用服务返回的精确 revision 和新的 idempotency_key;旧请求不会被自动重放。
返回结果与安全边界
- 所有公共操作返回统一的
SecurityResult<T>envelope。 - 命令返回不可变、带版本的 Receipt;查询返回按身份和 revision 绑定的 Snapshot。
- Findings、Evidence 和导出内容遵循宿主授权、用途和脱敏规则。
- 模型参数不接受凭据、数据库句柄、绝对路径或可执行对象;身份和权限由 Host 当前会话解析。
- Registry、Assessment、Evidence 和导出状态保存在插件私有 SQLite 中,使用幂等键与 revision CAS 防止重复执行。
- 缺失授权、状态冲突、超时、取消或外部失败会 fail closed,不会伪造满足结论。
workspace_snapshot只应对用户明确授权的仓库运行;祖先符号链接/联结会被拒绝,Subject 符号链接只登记不解引用,Git 通过 Harness 受管子进程边界执行。详见 SECURITY-REVIEW.md。
与 Engineering Control Plane 联用
两插件联用时,Control Plane 负责 Mission、工程 Evidence 和最终 Quality Gate;本插件只负责外部安全义务及其证据提交。安全评估失败或不确定会阻塞 Gate,但不会被转换成工程批准。
安装两者后,Control Plane 的可选 Provider 会按精确的 Provider ID、版本和 current-workspace 绑定本插件。两个插件不共享 SQLite、可写 Evidence 路径、事务或 Kernel 对象。
公开入口
| 入口 | 作用 |
|---|---|
dsh-security-assurance | 根 Security Assurance Service;同时导出内建 GitHub Actions、npm 发布面、pnpm 锁文件策略及 npm audit、Gitleaks 归一化契约 |
dsh-security-assurance/tools | 八个严格模型工具 |
dsh-security-assurance/contracts | 版本化公共契约 |
dsh-security-assurance/analyzer | 内建分析器接口 |
dsh-security-assurance/evaluation | 纯函数 Metrics Engine |
dsh-security-assurance/release-file-bindings | 发布文件绑定的版本化纯契约 |
dsh-security-assurance/release-proof | 精确候选证明记录与确定性索引纯契约 |
dsh-security-assurance/release-qualification | 资格草案、组装输入与最终输入的严格纯契约 |
dsh-security-assurance/release-promotion | RC → stable 行为等价交接收据纯契约(不授予发布权限) |
dsh-security-assurance/host-repository-provider | Host Repository 注册适配器 |
dsh-security-assurance/control-plane-provider | 可选 Control Plane 适配器 |
dsh-security-assurance/invariant | 启动就绪诊断 |
dsh-security-assurance/workbench-local | 为已认证的 Harness Web 页面签发与模型工具同等权限的工作台上下文,默认启用 |
dsh-security-assurance/workbench-remote | 需要部署方认证解析器,默认禁用;启用时须禁用 workbench-local |
dsh-security-assurance/client | Harness Web 安全工具卡片与安全保障工作台(仅浏览器端) |
常见排查
仓库列表为空:从目标 Git 仓库目录启动 Harness,并确认 Host Repository Provider 已加载;不要手工编造 Repository ID。
Catalog 显示 UNSUPPORTED:确认使用的是已授权仓库、security/standard Profile,以及 Catalog 为当前策略返回的模式。独立启动的 CHANGE 接受精确已提交的 base/head;未提交工作区只由 Control Plane 的 Host 专用 Subject 接入。TARGETED 支持 security/node-package-lifecycle 与 security/github-actions-supply-chain;npm 发布面、npm audit、Gitleaks 与 pnpm 锁文件策略仍显示 UNSUPPORTED。
端口冲突:关闭占用端口的旧 Harness 进程,或在 Web Profile 中改用空闲端口后重新启动。
评估为 BLOCKED:先读取 security_assessment_status 的 legalNextActions,只执行服务允许的 resume 或 cancel。
开发与验证
pnpm install
pnpm lint
pnpm build
pnpm typecheck
pnpm test
pnpm pack:dry-run
pnpm pack:profile-smoke
pnpm pack:browser-e2e
pnpm release:check
稳定版候选还必须先从真实 tarball、干净源码修订和锁文件生成确定性绑定,再用该绑定核验完整发布证据:
pnpm release:bind -- --input .\release-files.json --output .\release-file-bindings.json
pnpm release:collect -- --input .\release-proof-input.json --output .\release-proof-index.json
pnpm release:assemble -- --input .\release-qualification-draft.json --output .\release-qualification-input.json
pnpm release:qualify -- --input .\release-qualification-input.json --output .\release-qualification
pnpm release:handoff -- --input .\release-handoff-input.json --output .\release-promotion-handoff.json
第一条命令只记录已复核的文件事实,不制造测试或安全证明;packed smoke 可用 DSH_RELEASE_PROOF_OUTPUT 输出绑定同一 tarball 的严格证明记录,第二条命令验证并按规范顺序收集这些记录,逐字节摘要后生成 proof index;第三条命令重新读取 index、binding 与每份 proof record,把状态原样合并到 release:qualify 的严格输入;第四条命令再次读取绑定的真实文件,并且只在 Release Constitution 为 PROMOTE 且最终 Manifest 为 VERIFIED 时返回 0,原子生成 Manifest、公开 Scorecard 和资格结论三件套;第五条命令绑定这三件套与原 RC tarball,逐项比较拟发布 stable tarball,只允许同基线版本替换及 README/CHANGELOG 发布元数据变化,并输出明确写有 authorization: NOT_GRANTED 的交接收据。发布级真实浏览器 E2E 在全新安装的 Harness 中以真实操作驱动候选包自带的本地工作台(ADR 0324):只有当 tarball 本身启用本地授权时才记录 WORKBENCH,否则如实标记为 INCONCLUSIVE,不会把通用 Web 外壳冒充成 Workbench。有效但阻断/不完整的证据返回 2 并保留可审计产物;字节摘要、Git HEAD、已跟踪源码、资格组合或包行为不一致时返回 1 且不生成对应产物。所有 CLI 都不会自动打 tag、签名、上传或发布包。完整输入契约见 v0.1 发布清单。
手动 Release Candidate Evidence workflow 会要求一个完整的 40 位 Control Plane commit SHA,只打包并绑定一次候选,然后让 Linux、macOS、Windows 下载同一组 tarball 生成三份平台证明;最终收集任务从候选包安装公开 CLI,生成可下载的 release-evidence-index。该 workflow 不执行资格提升、打 tag、创建 Release 或发布 npm。
发布验收还须让同一份保留的候选包分别通过 Harness 0.1.5-rc.3、0.1.7-rc.2 与 0.2.0-rc.1 的浏览器证明;按宿主版本重新构建后通过兼容矩阵不能代替该检查。生成的 Host 和 Remote 契约同时支持旧版 schema 与新版 create(),共用严格校验器(ADR 0329)。
当前开发树包含 88 个测试文件、470 个测试,并由发布门禁统一执行静态检查、类型检查、构建、打包和 Harness Profile smoke。公开 CI 在 Ubuntu、macOS 和 Windows 上从两个 tarball 重建 fresh Profile 并执行 Web 探针;每日兼容矩阵另对全部已声明 Harness 版本执行双插件联合 E2E 与打包安装探针。
完整领域模型见 CONTEXT.md,安全政策见 SECURITY.md,候选版审查见 SECURITY-REVIEW.md。
English
What it is
dsh-security-assurance is an evidence-backed repository security assessment plugin for DeepSeek Harness. It integrates through public Harness and Cordis seams without modifying Harness Core, and exposes versioned, queryable, recoverable assessment results.
This is an assurance plugin, not a general vulnerability scanner. Built-in capabilities include the Node package.json install-lifecycle check, npm publish surface, pnpm lockfile integrity, GitHub Actions permission and immutable-dependency checks, and pure normalization plus independent validation of frozen npm-audit.json and Gitleaks v8 JSON reports.
A scan finding is not automatically an auditable security conclusion: input may be tampered with, truncated, or detached from the frozen repository. Security Assurance accepts only verified slices from a frozen Subject, then emits a verdict after independent validation and sealed submission.
Assessment at a glance
The Service resolves an authorized Catalog selection and freezes the complete Subject before exposing verified slices to qualified PURE Analyzers or report normalizers. Candidates and Coverage are independently re-derived before the Kernel can compute SATISFIED, FAILED, or INDETERMINATE and emit a digest-bound Submission for a sealed Assessment.
Current release
- Version:
0.1.0-rc.17 - Status: release candidate
- Target Harness:
0.1.2-alpha.1(primary);0.1.2-alpha.2through0.1.2-rc.1,0.1.3-alpha.1,0.1.3-alpha.2,0.1.5-alpha.1,0.1.5-alpha.2,0.1.5-rc.1,0.1.5-rc.2,0.1.5-rc.3,0.1.7-alpha.2,0.1.7-rc.1,0.1.7-rc.2, and0.2.0-rc.1verified by the compatibility matrix - Release: v0.1.0-rc.17
Support matrix
| Item | Status |
|---|---|
| Assessment mode | REPOSITORY; exact-commit or Mission-produced-workspace CHANGE; and TARGETED for the bundled source policies |
| Subjects | git_revision, workspace_snapshot, exact base/head change; Host-only Control Plane workspace_change |
CHANGE | Exact committed base-to-head pairs or Control Plane-frozen baseline-to-produced workspaces; scans the complete resulting tree |
TARGETED | The bundled Node lifecycle and GitHub Actions policies support explicit relative files/directories in git_revision and workspace_snapshot Subjects; only relevant manifests or workflows inside the Target are evaluated |
| Default policy | security/node-package-lifecycle |
| Optional npm audit policy | security/npm-dependency-audit |
| Optional Gitleaks policy | security/secret-leak-audit |
| Optional GitHub Actions policy | security/github-actions-supply-chain |
| Optional npm publish surface policy | security/npm-publish-surface |
| Optional pnpm lockfile policy | security/pnpm-lockfile-integrity |
| Assessment profile | security/standard (the only currently qualified Profile); security/deep and Host-defined Profiles fail closed until their independent multi-pass composition is implemented |
| Governed role catalog | Fixed to threat-modeler, discovery-analyst, validation-analyst, attack-path-analyst, and challenge-analyst; each entry has versioned digest lineage bound into Start Preflight, but no qualified execution Provider exists yet |
| Harness versions | 0.1.2-alpha.1 (primary), 0.1.2-alpha.2, 0.1.2-alpha.3, 0.1.2-alpha.4, 0.1.2-alpha.5, 0.1.2-rc.1, 0.1.3-alpha.1, 0.1.3-alpha.2, 0.1.5-alpha.1, 0.1.5-alpha.2, 0.1.5-rc.1, 0.1.5-rc.2, 0.1.5-rc.3, 0.1.7-alpha.2, 0.1.7-rc.1, 0.1.7-rc.2, 0.2.0-rc.1 |
| Node.js | ^22.19.0 || >=24.0.0 (CI covers 22 and 24) |
| Platforms | Windows, Linux, macOS |
The Service resolves authorized repositories and catalog choices first. Models must use the exact returned identifiers; paths and IDs are never guessed.
Current v0.1 Analyzer qualifications prove only the security/standard path. A Repository bound to security/deep or a Host-defined Profile is reported as unsupported by Catalog and Start Preflight; even a direct Service caller that omits preflight can produce only an INDETERMINATE result, never stronger-Profile Coverage from Standard PURE Evidence.
The Security Catalog also exposes bounded capability summaries for the fixed five-role catalog. Each entry is identified by a package-owned version and deterministic digest, and Start Preflight includes that same exact catalog in its proposal digest. Every role is PROPOSAL_ONLY and cannot approve, accept risk, or decide a Verdict. Catalog-entry lineage is not an executable Role Definition: execution remains UNSUPPORTED until complete definitions and a qualified Subagent Provider composition exist, and Deep Preflight reports NO_ELIGIBLE_ROLE_COMPOSITION separately.
The public root also provides an authority-free RoleContextGrantV1 contract kit. A Grant binds only protected Subject Inventory, Source Slice and Evidence artifact references, explicit disclosure categories, peer-output visibility, and byte and token ceilings; it carries no source body, workspace root, parent conversation, credentials, Store, Cordis Context, or execution capability. Creation is deterministic and deeply frozen, while receiver-side parsing recomputes the digest and fails closed on tampering, budget overruns, undisclosed categories, or duplicate references. This contract neither starts a Subagent nor claims that a Provider is qualified.
The same public seam provides deterministic SourceSliceRequestV1 creation, parsing, and static preflight. A request binds the exact Context Grant, Subject, Role Attempt, purpose, Coverage obligation, canonical Subject-relative target, expected raw-byte digest, egress selection, and requested budget; parsing rejects tampering. Preflight reports stale bindings, scope or egress expansion, and budget overruns together, but its only successful state is MATERIAL_REVIEW_REQUIRED: the Service must still re-prove Subject containment, source-digest integrity, sensitivity, secret redaction, Data Egress, actual budget, and Role need before it may issue a new immutable Grant. The tool reads no source, calls no Provider, and issues no capability.
A package-private protected reader can now accept that exact Grant and Request, repeat static admission, and read one in-target file from the content-addressed Subject Snapshot. It reverifies the complete Subject, frozen Target containment, the Request/Manifest/observed raw-byte digest chain, and the actual byte budget; its deeply frozen result is not exported from the package root. This local material has not passed sensitivity, secret-redaction, Data Egress, or Role-need review, so it cannot be sent to a Provider or used to issue another Context Grant.
A package-private secret inspection layer can run a versioned set of high-confidence patterns over that local material while retaining only the type, UTF-16 location, and an HMAC-SHA-256 fingerprint made with a Host-supplied key. Raw matches and the fingerprint key never enter the returned record; weak keys, text-digest drift, and non-canonical paths fail closed. The detector is intentionally bounded: even an empty result remains ADDITIONAL_REVIEW_REQUIRED, never a claim that the text is secret-free or an authorization for egress.
The same package-private layer can replace every detected value with a fixed typed placeholder and separately digest-bind the redacted UTF-8 text and the complete redaction record. A receiver rechecks the source bindings, detected locations, replacement coverage, and both digests against the protected material; raw matches are not retained. REDACTED_MATCHES_REVIEW_REQUIRED means only that known high-confidence matches were replaced, not that secret clearance is complete or Data Egress is authorized.
A versioned package-private sensitivity method then classifies the exact material and redaction conservatively: every source is at least PROTECTED_SOURCE, sensitive paths such as .env, credential files, and private-key containers become RESTRICTED_SOURCE, and high-confidence secret matches become SECRET_BEARING_SOURCE. Receivers recompute the classification and digest and reject even a digest-valid downgrade. The method classifies only; it neither permits disclosure nor pretends to be the not-yet-implemented Policy Compiler or a compiled Security Policy.
A package-private Data Egress review then repeats Grant/Request static admission, verifies the complete material-to-redaction digest chain, and meters the actual redacted UTF-8 bytes. It also binds a qualified secret-review summary for the same exact Slice into its own digest chain: complete CLEAR Evidence removes the secret-review gap, SECRET_FOUND rejects egress, and missing or indeterminate review remains fail closed. egress/deny-by-default always yields REJECTED; every other policy remains BROKER_REVIEW_REQUIRED while Broker qualification or destination authorization is missing. Only a Host-attested Broker Qualification and Host Destination Authorization that remain valid at the explicit evaluation instant and exactly bind the Provider, non-secret credential reference, policy, destination, category, Slice digests, single-request quota, timeout, and audit policy remove those two gaps and advance to BROKER_INVOCATION_REQUIRED. This step still has no approved state, resolves no credential, accesses no network, and calls no Provider.
On that foundation, a package-private issuer can re-admit the same Broker and destination Evidence at issuance time and create one non-serializable, one-use Source Slice Egress Capability. It binds the fixed redacted text and non-secret credential reference to the exact Role Attempt, generation, fence digest, Data Egress policy, request/token quotas, and effective deadline, and can invoke only an injected Broker Adapter with the exact qualified identity. Attempt settlement, caller cancellation, or timeout aborts the in-flight adapter; a Broker response with drifted Provider/destination, schema, or usage fails closed. Both success and failure produce a digest-bound audit receipt containing no request or response text. The capability remains package-private: no production Broker Adapter is registered, no receipt is yet persisted, and no Material Review, Context Grant, or Verdict is approved by this operation.
A completed Broker receipt can now be combined with a Kernel-owned budget reservation and frozen invocation lineage in a package-private pure settlement module to form a protected Model Invocation Record containing no Prompt, source, or response body. Before settlement, the reservation fixes the Context Grant, Role Attempt generation and fence, egress authorization, Broker request, single-request/token ceilings, and deadline. Settlement revalidates the complete receipt and binds Provider/backend/deployment/model plus Moving Provider status, Role and Prompt versions, Prompt and Tool Schema digests, parameters and randomness strategy, start/finish times, actual request and token usage, the raw response-byte digest, finish reason, Broker diagnostics, and the parent Attempt. Actual input/output tokens are charged and only the unused reservation is released; potentially over-budget parameters, completion at the deadline, and digest or request substitution fail closed. A package-private publication layer can also revalidate the complete Context Grant, derive its trusted assessment and Subject, verify the exact Attempt bindings, and atomically publish the record as a canonical content-addressed Evidence object. Its digest-bound receipt jointly fixes the invocation, parent Attempt generation and fence, record digest, and Evidence digest; identical publication is idempotent, and readback rechecks the entire binding. Neither the receipt nor the package root exposes a path or body. Package-private persistence can atomically create an immutable RUNNING Role Attempt before an isolated session starts. Published Model Invocation Evidence may be linked only while that exact Role Attempt remains RUNNING, its Grant and fence agree, and the protected invocation record's Role, Provider/model, Prompt, and Tool Schema lineage matches the Attempt. A successful return can then complete only by citing one durably admitted Role Contribution for the same generation and fence; disposition, request/token usage, Evidence count, and Candidate count are derived from that immutable Contribution instead of accepted from the completion caller. Admission closes over every and only the Attempt's linked Model Invocation Evidence and rechecks the exact record and response digests, Role, Provider/model, Prompt, Context Grant, Subject, and budget. The full protected Contribution remains in its own relational row while the Assessment carries only a compact digest-bound projection. Exact admission and completion replay is idempotent, while missing or extra invocations, conflicting contributions, stale revisions/fences, non-running state, cancellation, Subject drift, or budget drift rolls back and fails closed. On first open, a released schema-v1 Store advances through separately backed-up, fully verified, exclusively leased, digest-journaled v2, v3, and v4 migrations. A v2 Store with existing logical Evidence links but no provable Attempt rows is rejected, as are unknown versions. Required Role Attempts can also settle explicitly as FAILED: the failure code, usage, and retained counts are committed atomically with the Role Card, Revision Journal, and BLOCKED Assessment state. The public recovery projection identifies the exact ROLE_EXECUTION Attempt and requires authorized Resume. An Assessment cancellation request first prevents late-result admission; only after the caller proves cleanup and quiescence does the terminal commit change every remaining RUNNING Role Attempt and Role Card to CANCELED in the same revision. Recovery neither reuses nor erases the old Attempt: a new Attempt for the same Role needs a new identity and must cite a FAILED/CANCELED parent in the same Assessment; absent, non-terminal, or definition-drifted parent lineage fails closed. Automatic execution-graph scheduling, production session spawning, per-Role cleanup proof, and Broker registration remain absent. This slice also does not create the ADR 0197 Evidence Link or admit a canonical Assessment Bundle. Failed or unverifiable-usage Broker receipts are not fabricated into complete Model Invocation Records, and Material Review's ACTUAL_BUDGET does not yet become satisfied automatically.
A terminal model proposal can now enter a package-private pure RoleContributionV1 contract. Its canonical digest binds the Assessment, Subject, Context Grant, exact Attempt generation and fence, Role Definition, every Model Invocation record and response digest, structured hypotheses, Candidate Findings, Coverage observations, Evidence context and requests, challenges, Follow-up Requests, limitations, uncertainty, completion disposition, and exact aggregate usage. Strict parsing rejects unknown authority-bearing fields, duplicate or dangling references, non-canonical or unsafe Source Anchors, usage drift, oversized records, and digest tampering. The pure contract grants no authority; the durable admission described above only freezes lineage and completion accounting. Neither layer creates a Finding or Coverage Resolution, calls a Provider, or grants a Verdict, Risk Acceptance, or public capability.
Candidates from an admitted Role Contribution can now pass through a separate package-private pure admission boundary. It revalidates the exact Context Grant, Contribution, and durable Admission Link across their Assessment, Subject, Role, Attempt generation and fence, invocation, usage, count, revision, and digest lineage. Every Source Anchor must match a caller-supplied frozen-Subject slice whose raw bytes are reverified and its byte span must remain in bounds; every Candidate Evidence ID must be present in the caller-confirmed durable object set. The Candidate batch is all-or-nothing, and each success receives independent deeply frozen Candidate and admission digests; failures expose only fixed-code protected diagnostics. Schema v6 further commits one caller-identified admission attempt as a single Assessment transaction: success writes the digest-bound batch and per-Candidate rows, while failure writes only the fixed code, a safely parsed Candidate ID when available, and a request digest, never source or failure text. Exact success and rejection replay remains revision-neutral after Store reopen; conflicting attempts, stale revisions, cancellation, and non-running Attempts fail closed, while a new attempt can retry an earlier rejection after missing durable input becomes available. Admission itself still creates no Finding, Coverage Resolution, cluster, Evidence merge, or ADR 0197 Evidence Link.
After durable admission, a new package-private pure validation boundary first freezes the one exact versioned Validation Contract Resolution from the Candidate weakness and affected control, exact Assessment Policy digest and Mode, ecosystem, execution boundary, and qualification validity across the complete supplied catalog. No applicable Contract or multiple equally applicable Contracts remain explicitly unresolved, and observed proof cannot influence selection. The three-state Validation Outcome is then derived only from exact caller-confirmed durable Evidence identities, purpose-specific Evidence Eligibility Decisions, Contract conditions, required negative controls, and independence decisions bound to the complete provenance graph: only proof of the claim can produce VALIDATED; only eligible Counter-Evidence satisfying an explicit rejection condition can produce REJECTED; missing proof, shared provenance, missing controls, or any qualifying claim proof facing qualifying Counter-Evidence stays UNRESOLVED, however many lineages either side has. Schema v7 first appends the validation attempt's Contract Resolution in its own Assessment revision; only a later transaction can append the Outcome in the next revision, preventing post-result Contract selection. Exact replay of either stage is revision-neutral, current reads choose the latest Outcome for the exact Contribution and Candidate identity, and reopen re-derives and verifies the complete Candidate Admission, Contract, Outcome, and Revision Journal lineage. This boundary still calls no Provider, creates no Finding or Coverage Resolution, merges no Evidence, emits no ADR 0197 Evidence Link, and widens no public API.
If the original Role output fails strict JSON and schema validation, a package-private format-repair boundary now accepts only one separately predeclared, digest-bound invocation. Its plan fixes the Context Grant, Role Definition, Attempt generation and fence, original and repair invocation identities, Provider/model, deterministic parameters, one-request/token budget, and package-owned authority-free semantic payload schema and syntax instruction. Schema v5 commits that plan in the same transaction that starts the Role Attempt, so a running or recovered Attempt cannot gain or replace repair authority. The protected request body sent to the repair Provider may contain only the original response, target schema, and syntax instruction, and its exact digest must match the repair Model Invocation Record. Repair Evidence can be linked only after the exact original invocation Evidence; the text-free repair result is admitted at most once only after both links are durable, and any later Contribution must match its exact digest. A repaired result may be composed only when it passes the strict payload schema and its ordered JSON scalar sequence exactly matches the original; the Service supplies Contribution identity, both invocation lineage entries, and exact usage rather than accepting those fields from the model. Exact replay survives Store reopen, while already-valid output, Markdown fences or heuristic extraction, scalar addition/removal/change/reordering, a second repair identity, authority fields, and raw-byte, Prompt, Provider, time, budget, or replay drift all fail closed. No protected response body is stored in the plan or repair-result rows. This package-private boundary does not yet call a Provider, retry automatically, or change a public contract.
Schema v5 extends the separately backed-up, exclusively leased, digest-journaled migration chain with the durable Format Repair plan and result tables. Existing Role Attempts migrate as having no repair plan, so migration cannot infer or add repair authority.
Schema v6 extends the same fail-closed migration chain with Candidate Admission batches, individually readable Candidate records, and protected rejection diagnostics. Every migration step retains its own verified pre-migration backup and digest-bound history; existing Contributions migrate with no inferred Candidate admission or rejection.
Schema v7 extends that chain with append-only Role Candidate Validation Contract Resolution and three-state Outcome records. The v6-to-v7 step owns its own verified backup and digest-bound migration history; existing Candidate Admissions migrate with no inferred Contract, Evidence eligibility, independence, or Outcome.
A package-private vertical material-review operation re-reads the exact Request from the content-addressed Subject, performs the inspection, redaction, sensitivity classification, and egress review itself, and returns only an immutable, text-free record. In fixed order, the record covers all seven material checks and binds the complete digest chain for the Grant, Request, Subject, raw source, inspection, redacted text, redaction record, sensitivity classification, secret review, Broker/Destination authorization, and egress review. Containment, raw-source integrity, and conservative sensitivity classification can be marked SATISFIED locally. SECRET_REDACTION may additionally advance through a Kernel-eligible Analyzer Portfolio and Contribution dedicated to this scope, but only complete CLEAR Evidence that exactly binds the redacted Slice, remains within qualification validity, and references Host-attested independence Evidence can satisfy it and remove the corresponding egress gap. A residual secret rejects both the secret and egress checks; missing, indeterminate, expired, scope-mismatched, or digest-drifted Evidence fails closed. The existing Gitleaks qualification covers frozen-report normalization only and cannot impersonate this clearance. Even complete Broker and destination Evidence only requires a later Broker invocation; measured tokens and Role need remain REVIEW_REQUIRED, so the operation still has no aggregate approved state, issues no Grant, and calls no Provider.
TARGETED still freezes and digest-binds the complete Subject, then exposes only verified relevant slices inside the explicit Target: package.json for the Node lifecycle policy and .github/workflows/*.yml|yaml for the GitHub Actions policy. Every Target path must name an existing entry or directory prefix. A nonexistent path is rejected before Assessment creation. The npm publish surface, npm audit, Gitleaks, and pnpm lockfile policies do not yet claim TARGETED support because their root or external inputs cannot independently prove an exact Target scan scope.
The Harness support window is an explicit, verified set: a daily Harness Compatibility workflow discovers official repository tags, then runs the dual-plugin joint E2E (Mission → Developer workspace change → CHANGE Assessment → sealed submission → Quality Gate) and a packed fresh-profile installation with a live Web probe — on Ubuntu, macOS, and Windows for the primary target, and on Ubuntu for the remaining versions. New tags enter verification automatically but are not claimed as supported until the matrix passes (ADR 0310).
Exact-commit CHANGE mode freezes the resolved base and head identities, raw diff digest, and complete head tree. The bundled policies evaluate their complete relevant input sets in that tree, which is a conservative superset of the Policy impact cone.
The standalone tool and Workbench catalog remains backward compatible and exposes only exact-commit change to models. After a Control Plane Developer run publishes Implementation Evidence, its Provider receives a Host-only workspace_change from the unforgeable execution context. Security Assurance independently matches branch, baseline HEAD, Git-status fingerprint, byte-exact produced-change fingerprint, and the complete resulting tree before creating an Assessment; any drift fails closed.
Three-minute install in Harness Web
Compatible with DeepSeek Harness 0.1.2-alpha.1 through 0.1.2-rc.1, 0.1.3-alpha.1, 0.1.3-alpha.2, 0.1.5-alpha.1, 0.1.5-alpha.2, 0.1.5-rc.1, 0.1.5-rc.2, 0.1.5-rc.3, 0.1.7-alpha.2, 0.1.7-rc.1, 0.1.7-rc.2, and 0.2.0-rc.1 (an explicit, verified set; see the support matrix above). Requires Node.js ^22.19.0 || >=24.0.0 and the Harness CLI. Install the prebuilt GitHub Release package directly:
- Download the tarball from the matching Release.
- Install it from the repository you want to assess and inspect the composed profile.
- Start Harness Web and run an explicit
/securityassessment.
dsh plugin --profile web add https://github.com/bailong-Hakuryu/dsh-security-assurance/releases/download/v0.1.0-rc.17/dsh-security-assurance-0.1.0-rc.17.tgz
dsh --profile web --dump-config
dsh web
Alternatively, download dsh-security-assurance-0.1.0-rc.17.tgz from the Release page and pass its absolute local path to the same command.
When both plugins are installed, install Engineering Control Plane first because it supplies the shared invariant registry. The launcher working directory is registered as current-workspace.
Invocation
Natural-language requests are routed through the catalog-first workflow. Users can also run:
/security Assess the current repository and report the final verdict and findings.
/security Assess only packages/api and packages/web for package installation lifecycle risks.
The eight tools are security_repositories, security_catalog, security_assessment_start, security_assessment_status, security_assessment_findings, security_assessment_resume, security_assessment_cancel, and security_assessment_export. The normal order is repositories, catalog, start, status, and findings. Mutations require the exact Service revision and a fresh idempotency key.
In Harness Web, calls to these eight tools render as purpose-built Security cards instead of generic tool rows: one line of title and summary with state, verdict, and severity chips, expandable into details and the raw input and output. The cards read only the tool-call records already in the conversation; they call no Service and hold no authority (ADR 0322). A card that concerns an Assessment offers 「在工作台中打开」 (Open in Workbench) at the end of its row, which opens that Assessment in the Workbench in one step (ADR 0323).
Security Assurance Workbench: select 「安全保障」 (Security Assurance) at the foot of the Harness Web sidebar to browse visible Assessments, follow their progress, and inspect Findings, Evidence metadata, and Bundles, or to start a new Assessment on a registered Repository after a Catalog preflight. The Workbench has exactly the reach of the model tools: read, start, resume, and cancel Assessments, and request and read exports. Risk Decisions, break-glass, sensitive Evidence disclosure, and export download remain grants only a deployment's authenticated resolver can make (ADR 0321).
npm audit report adapter
The Host, CI job, or operator runs npm audit outside the Assessment. The plugin never starts npm, contacts the Registry, or reads live network state from its PURE Analyzer boundary. Generate a UTF-8 report and make sure it is part of the selected Subject before the Assessment starts:
npm audit --json | Set-Content -Encoding utf8 npm-audit.json
Bind the Repository to security/npm-dependency-audit. The adapter reads the exact frozen report bytes and digest. A complete clean report yields SATISFIED; independently validated vulnerabilities yield blocking Findings and FAILED; a missing or unsupported report, incomplete Coverage, or tampered Evidence yields INDETERMINATE. Report freshness remains the responsibility of the Host or CI job that produced it.
Gitleaks report adapter
The Host, CI job, or operator also runs Gitleaks outside the Assessment. Enable full redaction and freeze the UTF-8 JSON report into the selected Subject:
gitleaks dir . --redact=100 --report-format=json --report-path=gitleaks-report.json
Bind the Repository to security/secret-leak-audit. The PURE adapter retains only the rule ID, affected relative path, and location. It never projects Secret, Match, source lines, secret hashes, author email, or commit messages into Candidates, Findings, Evidence, Seals, or exports. A complete empty report yields SATISFIED; any independently re-derived report entry yields a HIGH blocking Finding and FAILED; missing, malformed, tampered, or incomplete input yields INDETERMINATE. The Host or CI owns scan configuration, report freshness, Git history breadth, and allowlist correctness.
GitHub Actions supply-chain policy
Bind the Repository to security/github-actions-supply-chain to evaluate only .github/workflows/.yml and .yaml files selected from the frozen Subject and current Target. The PURE Analyzer does not execute workflows or contact GitHub. It requires an explicit read-only or empty top-level permissions boundary, rejects job-level write permissions, requires a full 40-hex commit SHA for external Actions and reusable workflows, and requires a sha256 image digest for container Actions. Local ./ Actions are accepted.
The complete parse is repeated by an independent Validation Contract. A safe or empty selected workflow set yields SATISFIED; verified violations yield blocking Findings and FAILED; duplicate keys, aliases, malformed or unsupported YAML, and tampered Contributions yield INDETERMINATE. This strict Policy does not decide whether write authority is operationally justified. A release workflow that needs write permission requires another reviewed Policy rather than a silent exception in this one.
npm publish surface policy
Bind the Repository to security/npm-publish-surface to verify the frozen root package.json publish declaration entirely offline: public package identity, public access, an explicit files allowlist, and exports, main, types, and bin targets contained by that allowlist. It never runs npm pack, enumerates the filesystem, contacts the Registry, or claims that files exist, provenance is trusted, or dependencies are safe.
A consistent manifest yields SATISFIED. Private packages, restricted access, missing or broad allowlists, and uncontained entry points yield independently re-derived blocking Findings and FAILED; malformed, duplicate-key, invalid-target, or tampered input yields INDETERMINATE. Version 1 supports only REPOSITORY and CHANGE and proves manifest consistency rather than the contents of a real packed artifact.
pnpm lockfile integrity policy
Bind the Repository to security/pnpm-lockfile-integrity to compare the root package.json and pnpm-lock.yaml from the frozen Subject entirely offline. The PURE Analyzer requires packageManager to pin one exact pnpm semantic version, requires the pnpm v9 root importer to match all three dependency sections exactly, and requires valid SRI on every external package resolution. It never runs pnpm, installs dependencies, contacts the Registry, or claims that dependencies are vulnerability-free.
Consistent input yields SATISFIED. A missing lockfile, importer drift, unpinned package manager, or missing SRI yields independently re-derived blocking Findings and FAILED. Duplicate JSON keys, YAML aliases, malformed input, an unknown lockfile version, a non-pnpm manager, or a tampered Contribution yields INDETERMINATE. Version 1 covers only the root importer and supports REPOSITORY and CHANGE; it does not misrepresent workspace child packages as covered.
Results and safety
All public operations return a typed SecurityResult<T> envelope. Commands return immutable versioned Receipts; queries return identity- and revision-bound Snapshots. Host authority resolves identity and permissions; model arguments never carry credentials, paths, database handles, or executable objects. Missing authorization, conflicts, timeouts, cancellation, and external failures fail closed.
Run workspace_snapshot only for repositories the user explicitly authorizes. Ancestor links are rejected, Subject symlinks are inventoried without dereference, and Git runs through the Harness-managed subprocess boundary. See SECURITY-REVIEW.md.
Control Plane integration
Engineering Control Plane owns the Mission, engineering Evidence, and final Quality Gate. Security Assurance owns the external security obligation and its evidence. An unavailable, failed, or indeterminate security result blocks the Gate; it is never converted into approval. The two plugins do not share SQLite files, writable Evidence paths, transactions, or Kernel objects.
Development
pnpm install
pnpm lint
pnpm build
pnpm typecheck
pnpm test
pnpm pack:dry-run
pnpm pack:profile-smoke
pnpm pack:browser-e2e
pnpm release:check
Stable candidates must first derive deterministic bindings from the real tarball, clean source revision, and lock files, then verify the complete release-evidence request against those bindings:
pnpm release:bind -- --input .\release-files.json --output .\release-file-bindings.json
pnpm release:collect -- --input .\release-proof-input.json --output .\release-proof-index.json
pnpm release:assemble -- --input .\release-qualification-draft.json --output .\release-qualification-input.json
pnpm release:qualify -- --input .\release-qualification-input.json --output .\release-qualification
pnpm release:handoff -- --input .\release-handoff-input.json --output .\release-promotion-handoff.json
The first command records verified file facts but manufactures no test or
security proof. Packed smoke commands can emit strict records for that same
tarball through DSH_RELEASE_PROOF_OUTPUT; the second command validates and
raw-byte hashes those records into a deterministically ordered proof index. The
third re-verifies the index, binding, and referenced record bytes, then copies
their unchanged statuses into the strict qualification input. The fourth
rereads the bound files and exits 0 only when the
Release Constitution says PROMOTE and the assembled Manifest is VERIFIED,
atomically emitting the Manifest, public Scorecard, and qualification verdict.
The fifth binds those three files and the retained RC tarball, compares every
entry in the proposed stable tarball, permits only the same-base stable version
transition plus README/CHANGELOG release metadata, and emits a receipt whose
authorization is explicitly NOT_GRANTED.
The release-grade real-browser E2E drives the candidate's own local Workbench
through real controls in a freshly installed Harness (ADR 0324). It records
WORKBENCH only when the tarball itself enables the local authority and
otherwise honestly reports INCONCLUSIVE; a generic Web shell is never
relabelled as Workbench proof.
Valid blocked or incomplete evidence exits 2 with auditable output; byte,
Git HEAD, tracked-source, portfolio, or package-behavior mismatches exit 1
without output. None of the CLIs or proof emitters tag, sign, upload, or publish
a package. See the
v0.1 release checklist for the input contracts.
The manually triggered Release Candidate Evidence workflow requires an
exact 40-character Control Plane commit SHA, packs and binds one candidate, and
reuses those tarballs for Linux, macOS, and Windows proof runs. Its final job
installs the public collector from the candidate and uploads a deterministic
release-evidence-index; it does not qualify, tag, release, or publish.
The current development tree contains 89 test files and 480 tests; the release gate runs those tests together with linting, typecheck, build, packaging, and Harness profile smoke. Public CI rebuilds a fresh Profile from both tarballs and probes Web on Ubuntu, macOS, and Windows; the daily compatibility matrix additionally runs the dual-plugin joint E2E and the packed-installation probe across every declared Harness version.