Files
libsmx/.github/scripts/sanity_check.sh
huangxt 14e20cae89 优化安全性扫描脚本,避免测试代码误报
- 使用 awk 在 #[cfg(test)] 处提前退出,跳过测试代码
- 替换多个 grep -v 管道为单一 awk 处理
- 修复乱码字符
2026-03-07 21:04:18 +08:00

156 lines
7.2 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# =============================================================================
# libsmx 安全性扫描脚本
# =============================================================================
# 被 CI 工作流调用,执行以下检查:
# 1. 扫描非测试代码中的 panic!/unwrap()/expect()
# 2. 检查是否有硬编码密钥泄露
# 3. 验证 Cargo.toml 版本号与 Git Tag 匹配(仅在 tag 构建时)
# =============================================================================
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
ERRORS=0
pass() { echo -e "${GREEN}[PASS]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
fail() { echo -e "${RED}[FAIL]${NC} $1"; ERRORS=$((ERRORS + 1)); }
echo "=========================================="
echo " libsmx Security Sanity Checks"
echo "=========================================="
echo ""
# ─────────────────────────────────────────────────────────────────────────────
# 1. 扫描非测试代码中的 panic!/unwrap()/expect()
# ─────────────────────────────────────────────────────────────────────────────
# Reason: 密码学库不应在非测试代码中 panic,应返回 Result/Option
echo "--- 检查 panic/unwrap/expect ---"
# 排除规则:
# - #[cfg(test)] 块和 mod tests 块内的代码
# - benches/ 和 tests/ 目录
# - 白名单:try_into().unwrap() 用于固定大小切片转换(已知安全)
# Reason: 逐行 grep -v 无法排除 #[cfg(test)] 块内部的代码,
# 改用 awk 先将每个文件中 #[cfg(test)] 之后的行全部剥离,再 grep。
PANIC_HITS=$(find src/ -name '*.rs' -exec awk '/#\[cfg\(test\)\]/{exit} {print FILENAME":"NR":"$0}' {} \; \
| grep 'panic!\|\.unwrap()\|\.expect(' \
|| true)
if [ -n "$PANIC_HITS" ]; then
# 统计行数
COUNT=$(echo "$PANIC_HITS" | wc -l)
# 分类统计
UNWRAP_COUNT=$(echo "$PANIC_HITS" | grep -c '\.unwrap()' || true)
EXPECT_COUNT=$(echo "$PANIC_HITS" | grep -c '\.expect(' || true)
PANIC_COUNT=$(echo "$PANIC_HITS" | grep -c 'panic!' || true)
# try_into().unwrap() 是固定大小切片转换的惯用法,已知不会 panic
SAFE_UNWRAP=$(echo "$PANIC_HITS" | grep -c 'try_into().unwrap()' || true)
UNSAFE_UNWRAP=$((UNWRAP_COUNT - SAFE_UNWRAP))
if [ "$PANIC_COUNT" -gt 0 ]; then
fail "发现 $PANIC_COUNT 处 panic! 调用(非测试代码)"
echo "$PANIC_HITS" | grep 'panic!' | head -5
fi
if [ "$UNSAFE_UNWRAP" -gt 0 ]; then
warn "发现 $UNSAFE_UNWRAP 处 .unwrap() 调用(不含 try_into().unwrap()"
echo "$PANIC_HITS" | grep '\.unwrap()' | grep -v 'try_into().unwrap()' | head -5
fi
if [ "$EXPECT_COUNT" -gt 0 ]; then
warn "发现 $EXPECT_COUNT 处 .expect() 调用"
echo "$PANIC_HITS" | grep '\.expect(' | head -5
fi
if [ "$SAFE_UNWRAP" -gt 0 ]; then
echo -e " ${GREEN}(白名单)${NC} $SAFE_UNWRAP 处 try_into().unwrap()(固定大小切片转换,已知安全)"
fi
else
pass "非测试代码中无 panic/unwrap/expect"
fi
# ─────────────────────────────────────────────────────────────────────────────
# 2. 检查硬编码密钥/敏感信息
# ─────────────────────────────────────────────────────────────────────────────
echo ""
echo "--- 检查硬编码敏感信息 ---"
# Reason: 防止私钥、密码等敏感信息被提交到仓库
SENSITIVE_PATTERNS='(private.?key|secret.?key|password|passwd|api.?key|token)\s*=\s*["\x27][^\x27"]+["\x27]'
SENSITIVE_HITS=$(find src/ -name '*.rs' -exec awk '/#\[cfg\(test\)\]/{exit} {print FILENAME":"NR":"$0}' {} \; \
| grep -iE "$SENSITIVE_PATTERNS" \
|| true)
if [ -n "$SENSITIVE_HITS" ]; then
warn "发现疑似硬编码敏感信息(请人工审查):"
echo "$SENSITIVE_HITS" | head -5
else
pass "未发现硬编码敏感信息"
fi
# ─────────────────────────────────────────────────────────────────────────────
# 3. 验证 Cargo.toml 版本号与 Git Tag 匹配
# ─────────────────────────────────────────────────────────────────────────────
echo ""
echo "--- 检查版本号一致性 ---"
CARGO_VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
echo " Cargo.toml version: $CARGO_VERSION"
# 如果在 CI 中且有 GITHUB_REF_NAMEtag 构建),验证匹配
if [ -n "${GITHUB_REF_NAME:-}" ] && [[ "${GITHUB_REF:-}" == refs/tags/v* ]]; then
TAG_VERSION="${GITHUB_REF_NAME#v}"
echo " Git tag version: $TAG_VERSION"
if [ "$TAG_VERSION" != "$CARGO_VERSION" ]; then
fail "Tag 版本 ($TAG_VERSION) 与 Cargo.toml 版本 ($CARGO_VERSION) 不匹配!"
else
pass "Tag 与 Cargo.toml 版本匹配"
fi
else
echo " (非 tag 构建,跳过版本匹配检查)"
pass "Cargo.toml 版本号格式正确: $CARGO_VERSION"
fi
# ─────────────────────────────────────────────────────────────────────────────
# 4. 检查 unsafe 代码
# ─────────────────────────────────────────────────────────────────────────────
echo ""
echo "--- 检查 unsafe 代码 ---"
UNSAFE_HITS=$(find src/ -name '*.rs' -exec awk '/#\[cfg\(test\)\]/{exit} {print FILENAME":"NR":"$0}' {} \; \
| grep 'unsafe' \
| grep -v '#!\[forbid(unsafe_code)\]' \
| grep -v '// unsafe' \
|| true)
if [ -n "$UNSAFE_HITS" ]; then
fail "发现 unsafe 代码(本项目使用 #![forbid(unsafe_code)]):"
echo "$UNSAFE_HITS" | head -5
else
pass "未发现 unsafe 代码"
fi
# ─────────────────────────────────────────────────────────────────────────────
# 汇总
# ─────────────────────────────────────────────────────────────────────────────
echo ""
echo "=========================================="
if [ "$ERRORS" -gt 0 ]; then
echo -e " ${RED}发现 $ERRORS 个错误!${NC}"
echo "=========================================="
exit 1
else
echo -e " ${GREEN}所有安全检查通过${NC}"
echo "=========================================="
exit 0
fi