名称: clawsec-suite
版本: 0.1.3
描述: ClawSec 套件管理器,包含内嵌的安全通告订阅监控、加密签名验证、需用户批准的恶意技能响应处理,以及为其他安全技能提供引导式设置。
主页: https://clawsec.prompt.security
clawdis:
emoji: "📦"
requires:
bins: [curl, jq, shasum, openssl]
clawsec-suite 具备以下核心功能:
- 监控 ClawSec 安全通告订阅源。
- 追踪自上次检查以来的新通告。
- 将通告与本地已安装的技能进行交叉比对。
- 针对恶意技能通告推荐移除,并首先要求用户明确批准。
- 同时作为其他 ClawSec 防护功能的设置与管理入口。
advisories/feed.jsonHEARTBEAT.mdhooks/clawsec-advisory-guardian/scripts/scripts/guarded_skill_install.mjsscripts/discover_skill_catalog.mjsclawsec-suite 不会在本文档中硬编码附加技能的名称。
请在运行时从权威索引(https://clawsec.prompt.security/skills/index.json)发现当前目录:
SUITE_DIR="${INSTALL_ROOT:-$HOME/.openclaw/skills}/clawsec-suite"
node "$SUITE_DIR/scripts/discover_skill_catalog.mjs"
备用行为:
- 如果远程目录索引可达且有效,套件将使用它。
- 如果远程索引不可用或格式错误,脚本将回退到套件本地的目录元数据 skill.json。
bash/zsh 中,保持路径变量可扩展(例如:INSTALL_ROOT="$HOME/.openclaw/skills")。'$HOME/.openclaw/skills')。$env:INSTALL_ROOT = Join-Path $HOME ".openclaw\\skills"\$HOME/...),套件脚本现在会快速失败并给出明确错误。npx clawhub@latest install clawsec-suite
set -euo pipefail
VERSION="${SKILL_VERSION:?请设置 SKILL_VERSION (例如 0.0.8)}"
INSTALL_ROOT="${INSTALL_ROOT:-$HOME/.openclaw/skills}"
DEST="$INSTALL_ROOT/clawsec-suite"
BASE="https://github.com/prompt-security/clawsec/releases/download/clawsec-suite-v${VERSION}"
TEMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TEMP_DIR"' EXIT
# 固定的发布签名公钥(首次使用时请通过带外方式验证指纹)
# 指纹 (SPKI DER 的 SHA-256):711424e4535f84093fefb024cd1ca4ec87439e53907b305b79a631d5befba9c8
RELEASE_PUBKEY_SHA256="711424e4535f84093fefb024cd1ca4ec87439e53907b305b79a631d5befba9c8"
cat > "$TEMP_DIR/release-signing-public.pem" <<'PEM'
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEAS7nijfMcUoOBCj4yOXJX+GYGv2pFl2Yaha1P4v5Cm6A=
-----END PUBLIC KEY-----
PEM
ACTUAL_KEY_SHA256="$(openssl pkey -pubin -in "$TEMP_DIR/release-signing-public.pem" -outform DER | shasum -a 256 | awk '{print $1}')"
if [ "$ACTUAL_KEY_SHA256" != "$RELEASE_PUBKEY_SHA256" ]; then
echo "错误:发布公钥指纹不匹配" >&2
exit 1
fi
ZIP_NAME="clawsec-suite-v${VERSION}.zip"
# 1) 下载发布包、已签名的校验和清单及签名公钥
curl -fsSL "$BASE/$ZIP_NAME" -o "$TEMP_DIR/$ZIP_NAME"
curl -fsSL "$BASE/checksums.json" -o "$TEMP_DIR/checksums.json"
curl -fsSL "$BASE/checksums.sig" -o "$TEMP_DIR/checksums.sig"
# 2) 在信任任何哈希值之前,先验证校验和清单的签名
openssl base64 -d -A -in "$TEMP_DIR/checksums.sig" -out "$TEMP_DIR/checksums.sig.bin"
if ! openssl pkeyutl -verify \
-pubin \
-inkey "$TEMP_DIR/release-signing-public.pem" \
-sigfile "$TEMP_DIR/checksums.sig.bin" \
-rawin \
-in "$TEMP_DIR/checksums.json" >/dev/null 2>&1; then
echo "错误:checksums.json 签名验证失败" >&2
exit 1
fi
EXPECTED_ZIP_SHA="$(jq -r '.archive.sha256 // empty' "$TEMP_DIR/checksums.json")"
if [ -z "$EXPECTED_ZIP_SHA" ]; then
echo "错误:checksums.json 缺少 archive.sha256 字段" >&2
exit 1
fi
if command -v shasum >/dev/null 2>&1; then
ACTUAL_ZIP_SHA="$(shasum -a 256 "$TEMP_DIR/$ZIP_NAME" | awk '{print $1}')"
else
ACTUAL_ZIP_SHA="$(sha256sum "$TEMP_DIR/$ZIP_NAME" | awk '{print $1}')"
fi
if [ "$EXPECTED_ZIP_SHA" != "$ACTUAL_ZIP_SHA" ]; then
echo "错误:$ZIP_NAME 的归档校验和不匹配" >&2
exit 1
fi
echo "校验和清单签名与归档哈希验证通过。"
# 3) 安装已验证的归档文件
mkdir -p "$INSTALL_ROOT"
rm -rf "$DEST"
unzip -q "$TEMP_DIR/$ZIP_NAME" -d "$INSTALL_ROOT"
chmod 600 "$DEST/skill.json"
find "$DEST" -type f ! -name "skill.json" -exec chmod 644 {} \;
echo "已将 clawsec-suite v${VERSION} 安装到:$DEST"
echo "下一步(OpenClaw):node \"\$DEST/scripts/setup_advisory_hook.mjs\""
安装套件后,启用通告守护钩子:
SUITE_DIR="${INSTALL_ROOT:-$HOME/.openclaw/skills}/clawsec-suite"
node "$SUITE_DIR/scripts/setup_advisory_hook.mjs"
可选:创建/更新一个定期触发的定时任务(默认每 6h),用于在主会话中触发通告扫描:
SUITE_DIR="${INSTALL_ROOT:-$HOME/.openclaw/skills}/clawsec-suite"
node "$SUITE_DIR/scripts/setup_advisory_cron.mjs"
此钩子功能包括:
- 在 agent:bootstrap 和 /new (command:new) 时进行扫描,
- 将通告的 affected 条目与已安装技能进行比对,
- 考虑 application: "openclaw" 的通告(以及为向后兼容而保留的无 application 字段的旧条目),
- 当出现新的匹配项时发出通知,
- 并在任何移除流程之前要求用户明确批准。
启用钩子后,请重启 OpenClaw 网关。然后运行一次 /new 以在下一个会话上下文中强制立即扫描。
当用户请求安装一个技能时,将其视为第一次请求,并运行防护式安装检查:
SUITE_DIR="${INSTALL_ROOT:-$HOME/.openclaw/skills}/clawsec-suite"
node "$SUITE_DIR/scripts/guarded_skill_install.mjs" --skill helper-plus --version 1.0.1
行为:
- 如果未找到匹配的通告,则继续安装。
- 如果省略 --version,匹配策略将更保守:任何提及该技能名称的通告都将被视为匹配。
- 如果找到匹配的通告,脚本将打印通告详情并以退出码 42 退出。
- 然后,需要用户明确的第二次确认,并使用 --confirm-advisory 重新运行:
node "$SUITE_DIR/scripts/guarded_skill_install.mjs" --skill helper-plus --version 1.0.1 --confirm-advisory
这强制执行:
1. 第一次确认:用户请求安装。
2. 第二次确认:用户在查看通告详情后明确批准安装。
内嵌的订阅源逻辑使用以下默认值:
https://clawsec.prompt.security/advisories/feed.json${CLAWSEC_FEED_URL}.sig(可通过 CLAWSEC_FEED_SIG_URL 覆盖)checksums.json(可通过 CLAWSEC_FEED_CHECKSUMS_URL 覆盖)~/.openclaw/skills/clawsec-suite/advisories/feed.json${CLAWSEC_LOCAL_FEED}.sig(可通过 CLAWSEC_LOCAL_FEED_SIG 覆盖)~/.openclaw/skills/clawsec-suite/advisories/checksums.json~/.openclaw/skills/clawsec-suite/advisories/feed-signing-public.pem(可通过 CLAWSEC_FEED_PUBLIC_KEY 覆盖)~/.openclaw/clawsec-suite-feed-state.jsonCLAWSEC_HOOK_INTERVAL_SECONDS(默认 300)故障关闭式验证: 默认需要订阅源签名。当存在配套的校验和文件时,会验证校验和清单。仅在采用此版本但上游尚未提供签名的订阅源文件时,才临时设置 CLAWSEC_ALLOW_UNSIGNED_FEED=1 作为迁移绕过。
FEED_URL="${CLAWSEC_FEED_URL:-https://clawsec.prompt.security/advisories/feed.json}"
STATE_FILE="${CLAWSEC_SUITE_STATE_FILE:-$HOME/.openclaw/clawsec-suite-feed-state.json}"
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
if ! curl -fsSLo "$TMP/feed.json" "$FEED_URL"; then
echo "错误:获取通告订阅源失败"
exit 1
fi
if ! jq -e '.version and (.advisories | type == "array")' "$TMP/feed.json" >/dev/null; then
echo "错误:通告订阅源格式无效"
exit 1
fi
mkdir -p "$(dirname "$STATE_FILE")"
if [ ! -f "$STATE_FILE" ]; then
echo '{"schema_version":"1.0","known_advisories":[],"last_feed_check":null,"last_feed_updated":null}' > "$STATE_FILE"
chmod 600 "$STATE_FILE"
fi
NEW_IDS_FILE="$TMP/new_ids.txt"
jq -r --argfile state "$STATE_FILE" '($state.known_advisories // []) as $known | [.advisories[]?.id | select(. != null and ($known | index(.) | not))] | .[]?' "$TMP/feed.json" > "$NEW_IDS_FILE"
if [ -s "$NEW_IDS_FILE" ]; then
echo "检测到新通告:"
while IFS= read -r id; do
[ -z "$id" ] && continue
jq -r --arg id "$id" '.advisories[] | select(.id == $id) | "- [\(.severity | ascii_upcase)] \(.id): \(.title)"' "$TMP/feed.json"
done < "$NEW_IDS_FILE"
else
echo "订阅源正常 - 无新通告"
fi
使用套件的心跳脚本作为单一的定期安全检查入口点:
skills/clawsec-suite/HEARTBEAT.md它负责处理:
- 套件更新检查,
- 订阅源轮询,
- 新通告检测,
- 受影响技能交叉比对,
- 针对恶意/移除通告的需批准响应指导,
- 以及持久化状态更新。
如果一条通告指出某个已安装技能是恶意的或建议移除:
套件钩子和心跳指导默认是非破坏性的。
通告守护管道支持对已由安全团队审查并接受的通告进行选择性抑制。这对于内部工具或不适用于您部署环境的通告非常有用。
通告抑制需要一个单一的门控:配置文件必须包含 "enabledFor" 数组,且数组中包含 "advisory"。不需要 CLI 标志——配置文件中的这个标记就是选择性加入的门控。
如果 enabledFor 数组缺失、为空或不包含 "advisory",则所有通告都将正常上报。
通告守护程序使用与审计管道相同的优先级顺序来解析抑制配置:
--config <路径> 参数OPENCLAW_AUDIT_CONFIG 环境变量~/.openclaw/security-audit.json.clawsec/allowlist.json{
"enabledFor": ["advisory"],
"suppressions": [
{
"checkId": "CVE-2026-25593",
"skill": "clawsec-suite",
"reason": "内部安全工具 — 已由安全团队审查",
"suppressedAt": "2026-02-15"
},
{
"checkId": "CLAW-2026-0001",
"skill": "example-skill",
"reason": "该通告不适用于我们的部署配置",
"suppressedAt": "2026-02-16"
}
]
}
"enabledFor": ["advisory"] -- 仅激活通告抑制"enabledFor": ["audit"] -- 仅激活审计抑制(对通告管道无影响)"enabledFor": ["audit", "advisory"] -- 两个管道都遵守抑制规则enabledFor -- 无抑制激活(安全默认值)CVE-2026-25593 或 CLAW-2026-0001)| 字段 | 描述 | 示例 |
|---|---|---|
checkId |
要抑制的通告 ID | CVE-2026-25593 |
skill |
受影响的技能名称 | clawsec-suite |
reason |
审计追踪的理由(必需) | 内部工具,已由安全团队审查 |
suppressedAt |
ISO 8601 日期 (YYYY-MM-DD) | 2026-02-15 |
通告和审计管道共享同一个配置文件。使用 enabledFor 数组来控制哪些管道遵守抑制列表:
{
"enabledFor": ["audit", "advisory"],
"suppressions": [
{
"checkId": "skills.code_safety",
"skill": "clawsec-suite",
"reason": "内部工具 — 审计发现已接受",
"suppressedAt": "2026-02-15"
},
{
"checkId": "CVE-2026-25593",
"skill": "clawsec-suite",
"reason": "内部工具 — 通告已审查",
"suppressedAt": "2026-02-15"
}
]
}
审计条目(带有如 skills.code_safety 的检查标识符)仅由审计管道匹配。通告条目(带有如 CVE-2026-25593 或 CLAW-2026-0001 的通告 ID)仅由通告管道匹配。每个管道都只过滤与其相关的条目。
动态发现