chrisgillham/oss-trust-framework
GitHub: chrisgillham/oss-trust-framework
一个多重关卡的开源供应链信任验证框架,用于在依赖更新进入应用前进行安全审查并拦截恶意包,同时为零日漏洞补丁提供受控快速通道。
Stars: 1 | Forks: 0
# OSS 信任框架
[](https://pypi.org/project/oss-trust-framework/)
[](https://pypi.org/project/oss-trust-framework/)
[](LICENSE)
**开源供应链信任验证流水线**
一个多重关卡的安全框架,用于在开源依赖项更新到达您的应用程序之前对其进行验证——针对 CI/CD 流水线入侵(Miasma、Shai-Hulud、TanStack、Bitwarden、IronWorm)提供坚固的防御,并为零日漏洞 CVE 补丁提供严格控制的快速通道。
## 目录
- [安装](#installation)
- [使用指南](#usage-guide)
- [检查项目中的所有依赖](#1-check-all-deps-in-a-project-the-most-common-task)
- [检查单个包](#2-check-a-single-package)
- [Windows 用户](#3-windows-users)
- [CI/CD 集成](#4-cicd-integration)
- [零日快速通道](#5-zero-day-expedited-lane)
- [填充可信发布者白名单](#6-populate-the-trusted-publishers-allowlist)
- [支持的生态系统](#supported-ecosystems)
- [配置](#configuration)
- [为何开发此框架](#why-this-exists)
- [架构](#architecture)
- [关卡参考](#gate-reference)
- [攻击覆盖范围](#attack-coverage)
- [运行测试](#running-tests)
- [贡献](#contributing)
## 安装
```
pip install oss-trust-framework
# 验证
oss-trust --version
# oss-trust, 版本 0.6.1
```
## 使用指南
### 1. 检查项目中的所有依赖(最常见任务)
**npm 项目:**
```
oss-trust check-all --manifest package.json
```
**Python 项目(自动检测 `requirements.txt`):**
```
oss-trust check-all
```
**Rust:**
```
oss-trust check-all --manifest Cargo.toml
```
**Ruby:**
```
oss-trust check-all --manifest Gemfile.lock
```
**.NET:**
```
oss-trust check-all --manifest packages.config
```
**一次性检查多个清单(混合技术栈项目):**
```
oss-trust check-all --manifest package.json --manifest requirements.txt
```
**跳过开发依赖(仅检查生产环境):**
```
oss-trust check-all --prod-only
```
**非交互模式 — 用于 CI 流水线:**
```
oss-trust check-all --manifest package.json --no-interactive
```
**JSON 输出 — 用于 CI 流水线和报告:**
```
# Linux/Mac
oss-trust check-all --manifest package.json --no-interactive --output json > trust-report.json
# Windows PowerShell (重定向需要 UTF-8 编码)
$env:PYTHONUTF8 = "1"
oss-trust check-all --manifest package.json --no-interactive --output json 2>$null > trust-report.json
```
**如果任何包处于 HOLD(挂起)状态则使构建失败:**
```
oss-trust check-all --manifest package.json --no-interactive --fail-on-hold
```
**输出效果如下:**
```
OSS Trust Framework - check-all
config: ./config/trusted_publishers.yaml
package.json -> 9 packages
Running Gate 1 age checks on 9 packages...
All packages are in the trusted_publishers allowlist.
Ecosystem Package Version Allowlist Age (h) Gate 1 Outcome
npm express 4.18.2 check 32261.3 pass PASS
npm jsonwebtoken 9.0.2 check 24445.0 pass PASS
npm uuid 14.0.0 check 168.2 pass PASS
...
Summary: 9 packages -- 9 passed 0 on hold 0 blocked 0 errors
```
**JSON 输出(`trust-report.json`)效果如下:**
```
[
{
"ecosystem": "npm",
"package": "express",
"version": "4.18.2",
"source": "package.json",
"in_allowlist": true,
"attestation_required": false,
"age_hours": 32261.3,
"gate1_decision": "pass",
"gate1_message": "express@4.18.2 is 32261.3h old -- age gate cleared.",
"outcome": "PASS"
}
]
```
### 2. 检查单个包
当您想在升级前验证某个特定的包版本时使用此命令——尤其是在执行 `npm audit fix --force` 或处理 Dependabot PR 之后非常有用。
```
# 基本检查 — 仅 Gate 1 (age)
oss-trust check --package express --version 5.0.0 --ecosystem npm
# 完整 pipeline 检查 — 所有 gates,包括 provenance 和 OOB trust
oss-trust check \
--package requests \
--version 2.33.0 \
--ecosystem PyPI \
--github-repo psf/requests
# 带有 GitHub repo 的 npm package 以实现完整的 gate 覆盖
oss-trust check \
--package jsonwebtoken \
--version 9.0.2 \
--ecosystem npm \
--github-repo auth0/node-jsonwebtoken
# Cargo crate
oss-trust check --package serde --version 1.0.200 --ecosystem Cargo
# Maven artifact (使用 groupId:artifactId 格式)
oss-trust check \
--package "org.apache.commons:commons-lang3" \
--version 3.14.0 \
--ecosystem Maven
```
**支持的 `--ecosystem` 取值:**
`PyPI` `npm` `Cargo` `Go` `Maven` `NuGet` `RubyGems`
**PASS(通过)效果如下:**
```
Gate 1 (Age): PASS — requests@2.33.0 is 1847.2h old
Gate 2 (Provenance): PASS — published from psf/requests (expected)
Gate 3 (OOB Trust): PASS — score 82.5/100, 0 active CVEs
Outcome: APPROVED
```
**BLOCK(阻断)效果如下(新发布版本):**
```
Gate 1 (Age): BLOCK — express@5.0.1 is 4.2h old
Hard block threshold is 24h.
File a CVE reference to route through the zero-day expedited lane.
Outcome: BLOCKED
```
**HOLD(暂扣)效果如下(24-72小时时间窗口):**
```
Gate 1 (Age): HOLD — cryptography@44.0.1 is 31.5h old
Within the 72h hold window. Human approval required.
Outcome: HOLD
```
### 3. Windows 用户
PowerShell 重定向(`>`)默认使用 cp1252 编码,该编码无法处理 Rich 终端输出中的某些 Unicode 字符。请先设置 UTF-8 模式:
```
# 对于当前 session
$env:PYTHONUTF8 = "1"
# 使其永久生效 (运行一次)
New-Item -ItemType Directory -Force -Path (Split-Path $PROFILE)
Add-Content $PROFILE "`n`$env:PYTHONUTF8 = '1'"
```
**在将输出保存到文件时,请将 stderr 从 JSON 输出中重定向出去**(Rich 表格输出到 stderr,JSON 输出到 stdout):
```
# 仅保存 JSON,隐藏表格显示
oss-trust check-all --manifest package.json --output json 2>$null > trust-report.json
# 查看 JSON 报告
Get-Content trust-report.json | ConvertFrom-Json | Format-Table ecosystem, package, version, outcome
```
### 4. CI/CD 集成
**GitHub Actions — 在 lock 文件发生任何更改时自动运行:**
将 `.github/workflows/dep-trust-check.yml` 添加到您的仓库中:
```
name: Dependency trust check
on:
pull_request:
paths:
- '**/package.json'
- '**/package-lock.json'
- '**/requirements.txt'
- '**/Cargo.toml'
- '**/Cargo.lock'
- '**/Gemfile.lock'
jobs:
trust-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install OSS Trust Framework
run: pip install oss-trust-framework
- name: Run trust check
run: |
oss-trust check-all \
--manifest package.json \
--no-interactive \
--fail-on-hold \
--output json > trust-report.json
- name: Upload trust report
uses: actions/upload-artifact@v4
with:
name: trust-report
path: trust-report.json
```
**退出码:**
| 代码 | 含义 |
|------|---------|
| `0` | 所有包均已通过 |
| `1` | 一个或多个包被 BLOCKED(阻断)或(使用 `--fail-on-hold` 时)被 HELD(暂扣) |
| `2` | 未找到任何需要检查的包 |
### 5. 零日快速通道
当您依赖的包发布了合法的零日漏洞补丁时,72 小时的发布时间暂扣规则就会产生时间差。快速通道**仅**绕过年限关卡(Age Gate)——所有其他关卡依然是强制性的。
**第 1 步 — 请求例外:**
```
oss-trust zeroday request \
--cve CVE-2024-12345 \
--package cryptography \
--version 44.0.1 \
--ecosystem PyPI \
--requester security@yourorg.com
```
输出:
```
CVE-2024-12345 validated against NVD + OSV + GHSA (2-of-3 sources required)
Quorum request created: request-id abc123def456
Notify approvers: approver_001, approver_002, approver_003
Token TTL: 6 hours
```
**第 2 步 — 每位审批者单独审批(需要 MFA):**
```
oss-trust zeroday approve \
--request-id abc123def456 \
--approver-id approver_001 \
--mfa-token 123456
```
**第 3 步 — 检查状态:**
```
oss-trust zeroday status --request-id abc123def456
```
**规则:**
- 请求者不能批准自己的请求(职责分离)
- 需要 3 名指定审批者中的 2 名同意
- Token 在 6 小时后过期 — 不予延期
- 24 小时内超过 3 次例外请求将暂停快速通道,等待 CISO 审查
### 6. 填充可信发布者白名单
白名单将包名映射到其标准的 GitHub 源代码仓库。关卡 2 使用此信息来验证包的来源出处证明是否指向正确的仓库——而不是被入侵的分支或员工账户(Miasma 攻击模式)。
**交互式填充 — 任何项目推荐的第一步:**
```
# 从您的项目目录运行
oss-trust check-all --manifest package.json
```
对于不在白名单中的任何包,系统会提示您:
```
express@4.18.2 is not in trusted_publishers.yaml
Looking up canonical repo... found: expressjs/express
[1] Add to allowlist only
[2] Add to allowlist + require_attestation (block if no Sigstore attestation)
[s] Skip
[q] Quit interactive mode
Choice [1/2/s/q]: 1
Added npm/express: expressjs/express
config/trusted_publishers.yaml saved.
```
**无提示自动填充(脚本/自动化):**
```
# 在 scripts/check_all.py 中 — 为 manifest 中的所有 deps 输出 YAML 条目
python scripts/check_all.py --populate-allowlist npm package.json
```
输出:
```
# npm trusted_publishers 条目
# 从 package.json 生成
"express": "expressjs/express"
"jsonwebtoken": "auth0/node-jsonwebtoken"
"helmet": "helmetjs/helmet"
# "acme-client": "FIXME/repo" <-- couldn't auto-resolve, fill in manually
```
粘贴到 `config/trusted_publishers.yaml` 的 `npm:` 部分下。
**手动编辑 `config/trusted_publishers.yaml`:**
```
npm:
"express": "expressjs/express"
"jsonwebtoken": "auth0/node-jsonwebtoken"
"uuid": "uuidjs/uuid"
PyPI:
"cryptography": "pyca/cryptography"
"requests": "psf/requests"
Cargo:
"serde": "serde-rs/serde"
"tokio": "tokio-rs/tokio"
require_attestation: # These packages BLOCK if no Sigstore attestation found
PyPI:
- "cryptography"
- "requests"
npm:
- "jsonwebtoken"
```
## 支持的生态系统
### 全关卡覆盖
| 生态系统 | Registry | 包格式 | 示例 | 清单 |
|-----------|----------|----------------|---------|----------|
| `PyPI` ✅ | pypi.org | `package==version` | `requests==2.33.0` | `requirements.txt` |
| `npm` ✅ | npmjs.com | `package@version` | `express@4.18.2` | `package.json` |
### 部分覆盖(关卡 0、1、2.5、3、4 — 关卡 2 来源出处证明待定)
| 生态系统 | Registry | 包格式 | 示例 | 清单 | 关卡 2 状态 |
|-----------|----------|----------------|---------|----------|--------------|
| `Cargo` | crates.io | `crate@version` | `serde@1.0.200` | `Cargo.toml` | ⚠️ 占位符 — 计划集成 `cargo-vet` |
| `RubyGems` | rubygems.org | `gem` | `rails` | `Gemfile.lock` | ❌ 尚未实现 |
| `NuGet` | nuget.org | `PackageId` | `Newtonsoft.Json` | `packages.config` | ❌ 尚未实现 |
### 仅清单解析器和年限检查(关卡 0、1、3 — 无 lockfile 解析器或关卡 2)
| 生态系统 | Registry | 包格式 | 示例 | 清单 | 缺失功能 |
|-----------|----------|----------------|---------|----------|----------------|
| `Go` | proxy.golang.org | module path | `github.com/gin-gonic/gin` | ❌ 需要解析 `go.sum` | Manifest 解析器、关卡 2(GOPROXY 校验和数据库) |
| `Maven` | search.maven.org | `groupId:artifactId` | `org.apache.commons:commons-lang3` | ❌ 需要解析 `pom.xml` / `build.gradle` | Manifest 解析器、关卡 2(通过 Maven Central 的 GPG) |
对于通过 `--manifest` 或通过 `framework_deps.txt` 前缀格式(`Go:github.com/gin-gonic/gin@v1.9.0`)明确指定的 Go 和 Maven 包,仍然可以运行关卡 0、1、3 和 4。
| 文件 | 生态系统 | 是否支持? |
|------|-----------|-----------|
| `requirements.txt` | PyPI | ✅ 自动检测 |
| `framework_deps.txt` | Multi | ✅ 自动检测 |
| `package.json` | npm | ✅ 传递 `--manifest package.json` |
| `Cargo.toml` | Cargo | ✅ 传递 `--manifest Cargo.toml` |
| `Gemfile.lock` | RubyGems | ✅ 传递 `--manifest Gemfile.lock` |
| `packages.config` | NuGet | ✅ 传递 `--manifest packages.config` |
| `go.sum` / `go.mod` | Go | ❌ 尚不支持 |
| `pom.xml` / `build.gradle` | Maven | ❌ 尚不支持 |
**尚不支持**(路线图请参阅 [BACKLOG.md](BACKLOG.md)):
`poetry.lock` · `pyproject.toml` · `uv.lock` · `Pipfile.lock` · `Cargo.lock` · `packages.lock.json` · `*.csproj` · `pub.yaml` (Dart) · `Package.swift` · `composer.lock` (PHP)
## 配置
### `config/pipeline.yaml` — 关卡阈值
```
age_gate:
hard_block_hours: 24 # Releases younger than this: auto-blocked
hold_hours: 72 # 24-72h: human approval required before proceeding
trust_scoring:
min_scorecard_score: 6.0 # OpenSSF Scorecard minimum (0-10 scale)
require_zero_active_vulns: true
cicd_audit:
orphan_commits:
enabled: true
action_on_orphan: block
workflow_permissions:
enabled: true
action_on_finding: quarantine
pr_provenance:
min_pr_reviewers: 1
action_on_direct_push: block
sandbox:
runtime: gvisor # gvisor | strace | audit
network: none
behavioral_patterns:
block_on_critical: true
zero_day:
required_approvers: 2
token_ttl_hours: 6
circuit_breakers:
max_exceptions_per_24h: 3
```
### `config/trusted_publishers.yaml` — 基于包的白名单
请参阅上方的 [填充可信发布者白名单](#6-populate-the-trusted-publishers-allowlist)。涵盖所有 7 个生态系统中 100 多个高价值包的完整预填充白名单随框架一起提供,位于 `config/trusted_publishers.yaml`。
## 为何开发此框架
目前有三种截然不同的供应链攻击模式正在突破传统的防御手段:
**模式 2 — CI/CD 流水线入侵(Miasma 类)。** 攻击者入侵合法员工的 GitHub 账户,推送绕过 PR 审查的孤立提交(orphan commits),并利用 `id-token: write` CI/CD 权限通过 OIDC 受信任发布机制进行发布。这些包被*正确签名*——签名是真实的。传统的签名验证完全通过。
### 活跃攻击
| 攻击 | 日期 | 包 | 攻击向量 | 状态 |
|---|---|---|---|---|
| **Miasma / Red Hat Insights** | 2026 | 32 npm | 被入侵的员工账户 + OIDC 受信任发布 | 活跃攻击活动 |
| **IronWorm** | 2026-06-03 | 36 npm | Rust ELF preinstall hook + eBPF rootkit + Tor C2 | 活跃攻击活动 |
| **TanStack** | 2026 | 170 npm | 相同的 OIDC 受信任发布模式 | 活跃攻击活动 |
| **Bitwarden CLI** | 2026 | npm | Checkmarx 活动 — OIDC 受信任发布 | 活跃攻击活动 |
| **XZ Utils** | 2024 | tarball | 2年期的社会工程学 -> 构建脚本后门 | CVSS 10.0 |
## 架构
```
Dependency update request
|
v
+----------------------+ Name >= 92% similar to trusted pkg --> BLOCKED <-- postmark-mcp-evil
| Gate 0: Name | Name >= 80% similar --> WARN (manual review)
| Similarity Check | Exact allowlist match --> pass immediately
| (local, no network) | 3 algorithms: Levenshtein, prefix, char-swap
+----------+-----------+
|
v
+----------------------+ < 24 h, no CVE --> BLOCKED
| Gate 1: Age Hold |
| 24 h hard block | Zero-day CVE filed? --> Expedited Lane ----------+
| 72 h soft hold | |
+----------+-----------+ |
| >= 24 h |
v |
+----------------------+ Repo mismatch --> BLOCKED <-- Miasma/IronWorm |
| Gate 2: Provenance | No attestation --> QUARANTINE |
| Attestation + | (sourceRepositoryURI vs trusted_publishers.yaml) |
| Publisher Allowlist | |
+----------+-----------+ |
| |
v |
+----------------------+ Orphan commit --> BLOCKED <-- Miasma/IronWorm |
| Gate 2.5: CI/CD | id-token:write --> QUARANTINE |
| Pipeline Audit | No PR review --> BLOCKED |
+----------+-----------+ <-- Rejoins here --------+
|
v
+----------------------+ Score < threshold --> QUARANTINE
| Gate 3: Out-of-Band | Active CVE --> QUARANTINE
| Trust Aggregation | (OpenSSF, OSV, deps.dev, GHSA)
+----------+-----------+
|
v
+----------------------+ New transitive dep --> QUARANTINE
| Gate 4: SBOM Delta | Hash mismatch --> QUARANTINE
+----------+-----------+
|
v
+----------------------+ Tor C2 --> BLOCKED <-- IronWorm: exfil
| Gate 5: Behavioral | eBPF rootkit --> BLOCKED <-- IronWorm: rootkit
| Sandbox | AI API key harvest --> BLOCKED
| 34 patterns active | Cloud cred harvest --> BLOCKED
+----------+-----------+
|
v
+--------------+
| Staged Rollout| --> APPROVED
| 72 h canary |
+--------------+
```
## 关卡参考
| 关卡 | 控制内容 | 失败动作 | 可绕过? |
|---|---|---|---|
| **0 — 名称相似度** | 包名对比可信白名单 — Levenshtein、前缀添加、字符交换检测 | 警告 (>=80%) · 阻断 (>=92%) | 否 |
| **1 — 年限(Age)** | 发布时间戳对比 24 小时 / 72 小时阈值 | 阻断 / 暂扣 | 仅年限关卡 — 需 CVE + MFA 法定人数 |
| **2 — 来源出处(Provenance)** | 存在 Sigstore 证明;`sourceRepositoryURI` 匹配白名单 | 阻断(不匹配) · 隔离(缺失) | 否 |
| **2.5a — 孤立提交** | 通过 BFS 图遍历,发布标签提交可从默认分支到达 | 阻断 | 否 |
| **2.5b — 工作流权限** | 在发布工作流中具有 `id-token: write` 且无补偿性控制 | 隔离 | 否 |
| **2.5c — PR 来源** | 版本发布由 >= 1 名审查者批准合并的 PR 支撑 | 阻断(无 PR) · 隔离(无审查) | 否 |
| **3 — OOB 信任** | OpenSSF Scorecard >= 阈值;通过 OSV + deps.dev + GHSA 发现零活跃 CVE | 隔离 | 否 |
| **4 — SBOM 增量** | 无意外的传递依赖;lock 文件哈希未更改 | 隔离 | 否 |
| **5 — 行为沙箱** | gVisor/strace 安装时执行;34 种命名的行为模式(18 种 Miasma + 16 种 IronWorm) | 阻断 | 否 |
## 攻击覆盖范围
### Mma / Shai-Hulud — Red Hat Insights (2026)
| 攻击步骤 | 关卡 | 机制 |
|---|---|---|
| 推送孤立提交,绕过 PR | **2.5a** | BFS 遍历;标签提交无法从 main 到达 -> BLOCK |
| 恶意提交未进行代码审查 | **2.5c** | 无已合并的 PR -> DIRECT_PUSH -> BLOCK |
| `id-token: write` 被利用于 OIDC 发布 | **2.5b** | 危险权限 + 无环境保护 -> QUARANTINE |
| 从员工分支发布,而非标准组织 | **2** | `sourceRepositoryURI` 不匹配 -> BLOCK |
| 云凭证收集 (GCP/Azure IMDS) | **5** | MIASMA-001/002: IMDS 网络事件 -> BLOCK |
| 从安装上下文请求 OIDC token | **5** | MIASMA-010: `token.actions.githubusercontent.com` -> BLOCK |
| 从安装脚本重新发布到 npm | **5** | PUBLISH-001: PUT 请求到 `registry.npmjs.org` -> BLOCK |
### IronWorm — asteroiddao / Arweave 生态系统 (JFrog, 2026-06-03)
| 攻击步骤 | 关卡 | 机制 |
|---|---|---|
| 从被入侵的 `asteroiddao` 账户发布 | **2** | `sourceRepositoryURI` 不匹配 -> BLOCK |
| 具有倒签时间戳的孤立提交 | **2.5a** | 图可达性 — 时间戳无关 -> BLOCK |
| 通过 `preinstall` hook 投递 Rust ELF 二进制文件 | **5** | IRONWORM-002b: `tools/setup` 进程事件 -> BLOCK |
| eBPF 内核 rootkit 加载 | **5** | IRONWORM-002: `BPF_PROG_LOAD` 系统调用 -> BLOCK |
| AI API 密钥收集 (OpenAI、Anthropic、Gemini) | **5** | IRONWORM-003: `OPENAI_API_KEY`、`ANTHROPIC_API_KEY` -> BLOCK |
| AWS / GCP / Azure / Vault 凭证窃取 | **5** | CRED-003/004 + IRONWORM-004 -> BLOCK |
| Tor 隐藏服务 C2 信标 | **5** | IRONWORM-001: `.onion` 网络事件 -> BLOCK |
| 窃取 npm token 用于自我传播 | **5** | IRONWORM-006/006b: 读取 `.npmrc` + `NPM_AUTH_TOKEN` -> BLOCK |
## 零日通道断路器
| 条件 | 动作 |
|---|---|
| 24小时内超过 3 次例外请求 | 暂停通道,等待 CISO 审查 |
| 同一请求者在 48 小时内提出两次例外 | 第二次请求升级为 CISO 签字批准 |
| 任何通过例外部署的包在 30 天内收到新的 CVE | 暂停通道;触发回顾性审查 |
例外 Token 在 6 小时后过期。需要重新批准 — 不予延期。
## 运行测试
```
# 完整套件 — 131 项测试,全部离线 (无需网络)
pytest
# 按 gate
pytest tests/test_gate1_age.py # 11 tests — age threshold boundaries
pytest tests/test_gate3_trust.py # 6 tests — OOB trust aggregation
pytest tests/test_gate5_behavioral.py # 50 tests — all 34 named patterns
pytest tests/test_zeroday_lane.py # 23 tests — full quorum lifecycle
pytest tests/test_integration.py # 10 tests — cross-gate scenarios
# 带覆盖
pytest --cov=oss_trust_framework --cov-report=term-missing
```
所有外部 API 调用(PyPI、OSV、OpenSSF、GitHub)均已被模拟(mocked)— 测试完全在离线状态下运行。
## OWASP Top 10 CI/CD 安全风险覆盖
| 风险 | 框架覆盖范围 | 关卡 |
|---|---|---|
| **CICD-SEC-1** 流控制不足 | 年限关卡强制执行暂扣。零日通道需要 CVE + 2/3 的 MFA 法定人数。任何个人都无法单方面加速。 | 关卡 1, ZD 通道 |
| **CICD-SEC-2** IAM 不当 | 关卡 2.5b 审计 `id-token: write`。关卡 2.5c 强制执行审查人数。ZD 法定人数强制执行职责分离。 | 关卡 2.5b, 2.5c, ZD 通道 |
| **CICD-SEC-3** 依赖链滥用 | 核心任务。关卡 1-5 验证每一个依赖更新。 | 关卡 1-5 |
| **CICD-SEC-4** 中毒的流水线执行 | 关卡 2.5a 检测孤立提交。关卡 2.5c 确认 PR 审查。关卡 2.5b 标记危险权限。 | 关卡 2.5a, 2.5b, 2.5c |
| **CICD-SEC-5** PBAC 不足 | 关卡 2.5b 对发布工作流强制执行基于流水线的访问控制。 | 关卡 2.5b |
| **CICD-SEC-6** 凭证卫生不足 | 关卡 5 在安装时检测凭证收集(AWS/GCP/Azure、Vault、npm、AI API 密钥)。 | 关卡 2, 5 |
| **CICD-SEC-7** 不安全的系统配置 | 关卡 2.5b 检查是否缺失分支保护、CODEOWNERS、环境保护规则。 | 关卡 2.5b |
| **CICD-SEC-8** 不受管控的第三方服务 | 关卡 3 独立查询 OpenSSF、OSV、deps.dev、GHSA。关卡 4 SBOM 增量捕获意外的传递依赖。 | 关卡 3, 4 |
| **CICD-SEC-9** 制品完整性不当 | 关卡 2 验证 Sigstore/GPG 签名和 `sourceRepositoryURI`。关卡 4 锁定哈希。关卡 2.5a 验证标签可达性。 | 关卡 2, 2.5a, 4 |
| **CICD-SEC-10** 日志记录不足 | 每个关卡决策都会发出结构化的 SIEM 事件。零日例外需要关联工单。完整的不可否认审计跟踪。 | 所有关卡, ZD 通道 |
## 项目结构
```
oss-trust-framework/
+-- oss_trust_framework/ # Installable Python package (pip install oss-trust-framework)
| +-- check_all.py # oss-trust check-all command
| +-- name_similarity/checker.py # Gate 0 -- typosquat detection
| +-- age_check/checker.py # Gate 1 -- multi-ecosystem age check
| +-- signature/provenance.py # Gate 2 -- Sigstore attestation + allowlist
| +-- cicd_audit/ # Gate 2.5 -- CI/CD pipeline audit
| +-- trust/aggregator.py # Gate 3 -- OpenSSF/OSV/deps.dev/GHSA
| +-- sbom/differ.py # Gate 4 -- SBOM delta + hash pin
| +-- sandbox/ # Gate 5 -- behavioral sandbox (34 patterns)
| +-- zeroday/validator.py # CVE validation + quorum approval
| +-- pipeline/orchestrator.py # Full pipeline runner
| +-- cli.py # oss-trust CLI entry point
+-- scripts/check_all.py # Multi-ecosystem batch checker (all 7 registries)
+-- check_all.py # Repo-root shim (python check_all.py)
+-- config/
| +-- pipeline.yaml # Gate thresholds and circuit breakers
| +-- trusted_publishers.yaml # Publisher allowlist (100+ packages, 7 ecosystems)
+-- requirements.txt # Framework runtime deps (pinned, Dependabot-clean)
+-- framework_deps.txt # Self-validation dep declarations
+-- tests/ # 131 tests, all offline
+-- docs/index.html # Full documentation site
+-- .github/workflows/
+-- dep-trust-check.yml # PR gate: auto-runs on lock file changes
+-- publish.yml # PyPI publish on GitHub Release
```
## 供应链完整性对比运行时监控
该框架在依赖项**进入您的环境之前**对其进行验证。它不是一个运行时安全监控器。
| 威胁 | 是否覆盖? | 如未覆盖,请使用 |
|---|---|---|
| 恶意安装脚本 (IronWorm preinstall hook) | 关卡 5 | — |
| 被入侵的发布者账户 | 关卡 2, 2.5, 5 | — |
| Typosquat(域名拼写错误)/ 冒充 | 关卡 0 | — |
| 依赖项中已知的 CVE | 关卡 3 | — |
| 运行时数据渗出 (MCP server 密送电子邮件) | 否 | Falco, Tetragon |
| 延迟激活(满足条件后发送信标) | 否 | 运行时监控 |
| 语义冒充(字符串相似度低) | 否 | 人工白名单审查 |
## 许可证
MIT — 参见 [LICENSE](LICENSE)。
## 参考
- [IronWorm: Shai-Hulud 的 Rust 近亲 — JFrog 安全研究](https://research.jfrog.com/post/iron-worm-shai-hulud-rustier-cousin/)
- [IronWorm 恶意软件攻击 36 个 npm 包 — BleepingComputer](https://www.bleepingcomputer.com/news/security/new-ironworm-malware-hits-36-packages-in-npm-supply-chain-attack/)
- [Miasma 入侵 32 个 Red Hat npm 包 — devops.com](https://devops.com/shai-hulud-clone-miasma-compromises-32-red-hat-npm-packages/)
- [TanStack npm 供应链攻击 — Security Boulevard](https://securityboulevard.com/2026/05/the-tanstack-npm-supply-chain-attack-that-hit-170-packages-and-punishes-you-for-revoking-your-token/)
- [Bitwarden CLI 入侵 — Security Boulevard](https://securityboulevard.com/2026/04/bitwarden-cli-compromise-linked-to-ongoing-checkmarx-supply-chain-campaign/)
- [OpenSSF Scorecard](https://securityscorecards.dev)
- [Sigstore / cosign](https://docs.sigstore.dev)
- [OSV — 开源漏洞](https://osv.dev)
- [Google deps.dev](https://deps.dev)
- [SLSA 框架](https://slsa.dev)
- [npm 来源出处证明](https://docs.npmjs.com/generating-provenance-statements)
- [PyPI 可信发布者](https://docs.pypi.org/trusted-publishers/)
- [gVisor 容器沙箱](https://gvisor.dev)
标签:LNA, 逆向工具