Install
openclaw skills install @zhaoxinghua09-cell/skill-admission-gate技能上架安全闸门——一个技能/插件在安装或上架前,先跑确定性安全审查:查破坏性命令、远程执行、数据外泄、提示注入、隐蔽行为、混淆载荷与作用域越界,产出「分级发现 + 闸门判定 + 包指纹证据」。当需要审查第三方 skill、安装来源不明的技能、给自研技能做发布前安检、做供应链安全评估、或需要出具"该包未被篡改且已评估风险"的证据时调用。核心三件事:①按规则集扫全部文件并分级(BLOCK/WARN)②支持"已接受风险"声明(.admission-allow.json,须署名留痕)③输出包指纹与文件哈希作为"有证"产物。触发词:技能安全、审查 skill、安装前检查、恶意技能、skill 安全扫描、上架闸门、供应链安全、这个技能安全吗、第三方技能、能不能装、木马、后门、提示注入。
openclaw skills install @zhaoxinghua09-cell/skill-admission-gate凡自治之物 · LGD 治理学 · 创造术家族 | 评测协议:skill-quality-gate
Call this when you need to review a third-party skill, install a skill of unknown provenance, run pre-release security screening on an in-house skill, perform a supply-chain security assessment, or produce evidence that "this package is untampered and risk-assessed".
Entry script (run inside the skill directory): scan_skill.py.
Executable implementation of the LGD Three Laws: registered (package fingerprint) · evidenced (scan evidence on record) · gated (verdicts and accepted risks must be signed). Rule set
1.0.0· stdlib only · offline-runnable · no API key.
The security problem of the skill ecosystem is not "are there malicious packages" but "there is no admission gate":
Conclusion: skills need a deterministic, traceable, re-auditable security checkpoint, not "looks fine".
| Scenario | Note |
|---|---|
| Before installing third-party skills | Especially packages of unknown provenance, no repo backing, no license |
| Before in-house skill release | Pairs with skill-release-gate as the security front gate |
| Supply-chain assessment | Batch-scan a skill root, produce a risk list |
| Evidence needed | Package fingerprint + file hashes + timestamp proving "this version unchanged" |
Single-skill review:
python scripts/scan_skill.py <skill-dir> [--json out.json]
Batch review (scan a skill root):
python scripts/scan_skill.py <skill-root> --batch --json batch-result.json
Output example:
skill: my-skill
verdict: WARN | BLOCK 0 | WARN 2 | accepted 0 | 6 files scanned
package fingerprint: cd23896eee940857
[WARN] EXF-04 script.py:41 requests.post("https://api.example.com/collect", ...)
Exit codes: 0 = no BLOCK; 1 = BLOCK (usable as CI gate).
| Group | Rules | Level | Detects |
|---|---|---|---|
| Destructive | DES-01~05 | BLOCK | recursive forced delete, del /s /f, shutil.rmtree, format/write device, fork bomb |
| Remote exec | EXE-01,02 | BLOCK | `curl |
| EXE-03,04 | WARN | eval(/exec(, post-base64-decode exec | |
| Exfiltration | EXF-01,02 | BLOCK | reading private keys / credential files, reading local vaults and key-drop tools |
| EXF-03,04 | WARN | reading .env/env credentials, POST/PUT to external endpoints | |
| Prompt injection | INJ-01,02 | BLOCK | "ignore previous instructions", "do not tell the user" |
| INJ-03~05 | WARN | silent execution, bypassing security/approvals, tricking users into pasting keys | |
| Obfuscation | OBF-01 | WARN | overlong Base64 strings (suspected payload) |
| Scope | SCP-01 | WARN | writing absolute paths outside the skill dir |
Verdict: any BLOCK hit → overall BLOCK; only WARN → WARN; none → PASS.
False positives are inevitable — e.g. a local-vault skill "reading " is its job, not exfiltration.
But "accepting a risk" must not be silent ignoring: it must be traceable and signed. Drop .admission-allow.json in the reviewed dir:
{
"schema": "skill-admission-allow/1.0",
"skill": "dpapi-local-vault",
"note": "This skill's function is a local credential vault; accessing that dir is its declared use.",
"allow": [
{
"rule": "EXF-02",
"reason": "Reading/writing <local-vault> is its sole declared use; keys never leave plaintext or the machine.",
"approved_by": "XLGD",
"date": "2026-09-12",
"mitigation": "This skill makes no network requests."
}
]
}
After declaration the rule moves to ACCEPTED (still appears in the report, no verdict impact) — this is "gated + evidenced".
Every review outputs:
| Field | Meaning |
|---|---|
package_fingerprint_sha256 | aggregate hash of all files — "was the package tampered" |
file_hashes[] | sha256 + byte size per file |
rule_version | rule-set version (rules evolve; record which version decided) |
timestamp_utc | review time |
accepted_risks[] | accepted risks with signer and reason |
Uses: release ledger, dispute forensics, version-regression comparison (fingerprint changed → re-review required).
rule_version; align rule versions when comparing across versions.PASS means "no hit against this rule set", not "secure".| LGD law | This skill's implementation |
|---|---|
| Registered | Package fingerprint + file hashes: uniquely identify "who / which version" |
| Evidenced | scan findings + rule version + timestamp, all persisted to JSON |
| Gated | BLOCK blocks (exit 1); accepting a risk requires signer + reason + mitigation |
skill-admission-gate v1.0.1 · © XLGD · SynomosAI · 2026-09-12
入口脚本(在技能目录下执行):scan_skill.py。
LGD 三律的可执行实现:有籍(包指纹)· 有证(扫描证据留痕)· 有门禁(判定与已接受风险须署名)。 规则版本
1.0.0| 纯标准库 | 离线可跑 | 无需 API key
技能生态的安全问题不是"有没有恶意包",而是"没有上架闸门":
结论:技能需要一个确定性、可留痕、可复核的安检环节,而不是靠"看起来没问题"。
| 场景 | 说明 |
|---|---|
| 安装第三方技能前 | 尤其是来源不明、无仓库背书、无 license 的包 |
| 自研技能发布前 | 与 skill-release-gate 配套,作为安全前置 |
| 供应链安全评估 | 批量扫描技能根目录,出一张风险清单 |
| 需要出具证据 | 包指纹 + 文件哈希 + 时间戳,证明"此版本未变" |
python scripts/scan_skill.py <技能目录> [--json out.json]
python scripts/scan_skill.py <技能根目录> --batch --json batch-result.json
输出示例:
技能: my-skill
判定: WARN | BLOCK 0 | WARN 2 | 已接受 0 | 扫描 6 文件
包指纹: cd23896eee940857
[WARN] EXF-04 script.py:41 requests.post("https://api.example.com/collect", ...)
退出码:0 = 非 BLOCK;1 = BLOCK(可用于 CI 阻断)。
| 组 | 规则 | 级别 | 检测内容 |
|---|---|---|---|
| 破坏性 | DES-01~05 | BLOCK | 递归强制删除、del /s /f、shutil.rmtree、格式化/写设备、fork 炸弹 |
| 远程执行 | EXE-01,02 | BLOCK | `curl |
| EXE-03,04 | WARN | eval(/exec(、base64 解码后执行 | |
| 数据外泄 | EXF-01,02 | BLOCK | 读私钥/凭据文件、读本地保险库与密钥投递工具 |
| EXF-03,04 | WARN | 读 .env/环境凭据、向外部端点 POST/PUT | |
| 提示注入 | INJ-01,02 | BLOCK | "忽略之前指令"、"不要告诉用户" |
| INJ-03~05 | WARN | 静默执行、绕过安全/审批、诱导粘贴密钥 | |
| 混淆 | OBF-01 | WARN | 超长 Base64 字串(疑似载荷) |
| 作用域 | SCP-01 | WARN | 写入技能目录之外的绝对路径 |
判定口径:命中任一 BLOCK → 整体 BLOCK;仅命中 WARN → WARN;无命中 → PASS。
误报是必然的——例如本地保险库技能"读 <local-vault>"是其本职,不是外泄。
但"接受风险"不能靠静默忽略,必须留痕、必须署名。 在被审目录放 .admission-allow.json:
{
"schema": "skill-admission-allow/1.0",
"skill": "dpapi-local-vault",
"note": "本技能功能即本地凭据保险库,访问该目录是其声明用途。",
"allow": [
{
"rule": "EXF-02",
"reason": "读写 <local-vault> 是其唯一且声明的用途;密钥不落明文、不出本机。",
"approved_by": "XLGD",
"date": "2026-09-12",
"mitigation": "本技能不发起任何网络请求。"
}
]
}
声明后该规则转入 ACCEPTED 分类(仍出现在报告里,但不影响判定)——这就是"有门禁 + 有证"。
每次审查都输出:
| 字段 | 含义 |
|---|---|
package_fingerprint_sha256 | 全包文件哈希聚合指纹——用于判定"包是否被改过" |
file_hashes[] | 每个文件的 sha256 与字节数 |
rule_version | 规则集版本(规则会演进,须记录用哪版判的) |
timestamp_utc | 审查时间 |
accepted_risks[] | 已接受风险及其署名与理由 |
用途:上架台账、争议取证、版本回归比对(新版本指纹变了 → 须重审)。
rule_version;跨版本比较结论时须对齐规则版本。PASS 表示"未命中本规则集",不等于"安全"。| LGD 法则 | 本技能的实现 |
|---|---|
| 有籍(Registry) | 包指纹 + 文件哈希:这个包"是谁、是什么版本"可唯一标识 |
| 有证(Evidence) | 扫描发现 + 规则版本 + 时间戳,全部落盘 JSON |
| 有门禁(Gates) | BLOCK 则阻断(退出码 1);接受风险须署名 + 给理由 + 给缓解措施 |