10404dbb36
同步工作区剩余变更,主要包括: - 营销页面组件与布局持续优化(about/news/services/solutions/team 等) - 详情页四层叙事组件、布局组件、UI 组件调整 - CMS 数据模型、API 路由、权限、工作流、站内通知、媒体管理扩展 - 新增/补充单元测试与 E2E 测试(cms-workflow.spec.ts 等) - ESLint 9 迁移、jest/tsconfig 配置更新、依赖调整 - 新增 ADR、CMS 评估文档、Release Review / Acceptance 报告 - 移除水墨装饰组件与大体积未使用字体文件
81 lines
3.3 KiB
Bash
Executable File
81 lines
3.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# 封版验收安全扫描手动清单脚本
|
|
# 运行环境:本地生产预览服务 http://localhost:3000
|
|
# 前置条件:npm run start 已启动在 3000 端口
|
|
|
|
set -euo pipefail
|
|
|
|
BASE_URL="${BASE_URL:-http://localhost:3000}"
|
|
REPORT_DIR="${REPORT_DIR:-release-acceptance-reports/$(date +%Y%m%d-%H%M%S)}"
|
|
mkdir -p "$REPORT_DIR"
|
|
|
|
echo "======================================"
|
|
echo "安全扫描手动清单"
|
|
echo "目标: $BASE_URL"
|
|
echo "报告目录: $REPORT_DIR"
|
|
echo "======================================"
|
|
|
|
# SEC-01 / SEC-06: 依赖漏洞扫描
|
|
echo "[SEC-01] 运行 npm audit --production..."
|
|
npm audit --audit-level moderate --registry=https://registry.npmjs.org/ > "$REPORT_DIR/50-npm-audit-final.log" 2>&1 || true
|
|
|
|
# SEC-02: 安全响应头检查
|
|
echo "[SEC-02] 检查安全响应头..."
|
|
curl -sI "$BASE_URL/" | grep -iE 'X-Content-Type-Options|X-Frame-Options|X-XSS-Protection|Strict-Transport-Security|Content-Security-Policy' > "$REPORT_DIR/51-security-headers.log" 2>&1 || true
|
|
if [ ! -s "$REPORT_DIR/51-security-headers.log" ]; then
|
|
echo "未检测到安全响应头" > "$REPORT_DIR/51-security-headers.log"
|
|
fi
|
|
|
|
# SEC-03: 认证绕过测试
|
|
echo "[SEC-03] 测试未授权访问 /admin 与 /api/admin/models..."
|
|
{
|
|
echo "GET $BASE_URL/admin"
|
|
curl -s -o /dev/null -w "%{http_code}\n" "$BASE_URL/admin"
|
|
echo "GET $BASE_URL/api/admin/models"
|
|
curl -s -o /dev/null -w "%{http_code}\n" "$BASE_URL/api/admin/models"
|
|
} > "$REPORT_DIR/52-auth-bypass.log" 2>&1
|
|
|
|
# SEC-04: XSS 过滤测试
|
|
echo "[SEC-04] 测试联系表单 XSS 过滤..."
|
|
curl -s -X POST "$BASE_URL/api/contact" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"name":"XSS Test","email":"xss@test.com","phone":"13800138000","subject":"XSS","message":"<script>alert(1)</script>"}' \
|
|
> "$REPORT_DIR/53-xss-test.log" 2>&1
|
|
|
|
# SEC-05: SQLi 过滤测试
|
|
echo "[SEC-05] 测试联系表单 SQLi 过滤..."
|
|
curl -s -X POST "$BASE_URL/api/contact" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"name":"SQLi Test","email":"sqli@test.com","phone":"13800138000","subject":"SQLi","message":"1\x27 OR \x271\x27=\x271"}' \
|
|
> "$REPORT_DIR/54-sqli-test.log" 2>&1
|
|
|
|
# SEC-06: JWT 校验测试
|
|
echo "[SEC-06] 测试 JWT 校验..."
|
|
{
|
|
echo "空 token:"
|
|
curl -s -o /dev/null -w "%{http_code}\n" "$BASE_URL/api/admin/models"
|
|
echo "无效 token:"
|
|
curl -s -o /dev/null -w "%{http_code}\n" -H "Authorization: Bearer invalid-token" "$BASE_URL/api/admin/models"
|
|
echo "过期 token (expired signature):"
|
|
curl -s -o /dev/null -w "%{http_code}\n" -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1MTYyMzkwMjJ9.4AdcjS3X_FSn0FxL5XfKX5qJ6tE4ZfG8h0e8_xW3V7o" "$BASE_URL/api/admin/models"
|
|
} > "$REPORT_DIR/55-jwt-test.log" 2>&1
|
|
|
|
# SEC-07: 敏感信息泄露扫描
|
|
echo "[SEC-07] 扫描源码中的硬编码敏感信息..."
|
|
grep -R -n -E "password|secret|token|api[_-]?key" \
|
|
--include="*.ts" --include="*.tsx" \
|
|
src/ \
|
|
| grep -v "\.env" \
|
|
| grep -v "process\.env" \
|
|
| grep -v "// " \
|
|
| head -100 \
|
|
> "$REPORT_DIR/56-secrets-scan.log" 2>&1 || true
|
|
|
|
if [ ! -s "$REPORT_DIR/56-secrets-scan.log" ]; then
|
|
echo "未发现明显硬编码敏感信息" > "$REPORT_DIR/56-secrets-scan.log"
|
|
fi
|
|
|
|
echo "======================================"
|
|
echo "安全扫描完成,产物保存在 $REPORT_DIR"
|
|
echo "======================================"
|