Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a248883c8e |
@@ -101,6 +101,53 @@ jobs:
|
||||
bandit --version
|
||||
pytest --version
|
||||
|
||||
- name: Secret detection (gitleaks)
|
||||
shell: sh
|
||||
run: |
|
||||
set -eu
|
||||
echo "=== Installing gitleaks ==="
|
||||
# 优先尝试 GitHub release,失败则用国内镜像
|
||||
GITLEAKS_VERSION="8.18.4"
|
||||
install_gitleaks() {
|
||||
local url="$1"
|
||||
curl -sSL -f -o /tmp/gitleaks.tar.gz "$url" || return 1
|
||||
tar -xzf /tmp/gitleaks.tar.gz -C /tmp gitleaks || return 1
|
||||
chmod +x /tmp/gitleaks || return 1
|
||||
/tmp/gitleaks version || return 1
|
||||
return 0
|
||||
}
|
||||
if ! install_gitleaks "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz"; then
|
||||
echo "GitHub release failed, trying mirror..."
|
||||
if ! install_gitleaks "https://gitee.com/mirrors/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz"; then
|
||||
echo "WARN: Failed to install gitleaks from all sources, skipping secret scan"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
echo "=== Running gitleaks scan ==="
|
||||
if [ "${{ github.event_name }}" = "pull_request" ]; then
|
||||
# PR触发: 增量扫描
|
||||
echo "PR mode: scanning changed files"
|
||||
EXIT_CODE=0
|
||||
/tmp/gitleaks detect --source . --config .gitleaks.toml --verbose --exit-code 1 --log-opts="origin/${{ github.base_ref }}..HEAD" || EXIT_CODE=$?
|
||||
if [ "$EXIT_CODE" = "1" ]; then
|
||||
echo "ERROR: Secrets detected! Check the scan report above."
|
||||
echo "If these are false positives, add them to .gitleaks.toml allowlist."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# Push触发: 全量扫描
|
||||
echo "Push mode: full repository scan"
|
||||
EXIT_CODE=0
|
||||
/tmp/gitleaks detect --source . --config .gitleaks.toml --verbose --exit-code 1 || EXIT_CODE=$?
|
||||
if [ "$EXIT_CODE" = "1" ]; then
|
||||
echo "ERROR: Secrets detected! Check the scan report above."
|
||||
echo "If these are false positives, add them to .gitleaks.toml allowlist."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo "gitleaks scan completed - no secrets detected"
|
||||
|
||||
- name: Run code quality checks
|
||||
shell: sh
|
||||
run: |
|
||||
@@ -110,12 +157,56 @@ jobs:
|
||||
python3 -m isort --check-only alembic apps packages tests scripts
|
||||
python3 -m flake8 apps packages tests --count --statistics
|
||||
|
||||
- name: Run security scan
|
||||
- name: Run security scan (bandit)
|
||||
shell: sh
|
||||
run: |
|
||||
set -eu
|
||||
bandit -r apps packages -q -ll
|
||||
|
||||
- name: Python dependency vulnerability scan (pip-audit)
|
||||
shell: sh
|
||||
run: |
|
||||
set -eu
|
||||
echo "=== Installing pip-audit ==="
|
||||
python3 -m pip install -q pip-audit
|
||||
pip-audit --version
|
||||
echo ""
|
||||
echo "=== Scanning Python dependencies ==="
|
||||
EXIT_CODE=0
|
||||
for req_file in requirements.txt requirements-base.txt requirements-dev.txt; do
|
||||
if [ -f "$req_file" ]; then
|
||||
echo "--- Scanning $req_file ---"
|
||||
pip-audit -r "$req_file" --desc on --format text 2>&1 | head -30 || EXIT_CODE=$?
|
||||
echo ""
|
||||
fi
|
||||
done
|
||||
# 告警模式,不阻断CI(待稳定后再考虑改为阻断)
|
||||
echo "pip-audit scan completed (advisory mode - warnings only, not blocking CI)"
|
||||
if [ "$EXIT_CODE" != "0" ]; then
|
||||
echo "WARNING: Potential vulnerabilities found in dependencies."
|
||||
fi
|
||||
exit 0
|
||||
|
||||
- name: Dead code detection (vulture)
|
||||
shell: sh
|
||||
run: |
|
||||
set -eu
|
||||
echo "=== Installing vulture ==="
|
||||
python3 -m pip install -q vulture
|
||||
vulture --version
|
||||
echo ""
|
||||
echo "=== Running vulture dead code scan ==="
|
||||
# 告警模式,不阻断CI(P2级别,仅供参考)
|
||||
EXIT_CODE=0
|
||||
vulture --config vulture.conf vulture_whitelist.py || EXIT_CODE=$?
|
||||
echo ""
|
||||
echo "vulture scan completed (advisory mode - P2, for reference only)"
|
||||
if [ "$EXIT_CODE" != "0" ]; then
|
||||
echo "NOTE: Potential dead code found. Review results above."
|
||||
echo "False positives can be added to vulture_whitelist.py"
|
||||
fi
|
||||
exit 0
|
||||
|
||||
- name: Validate release scripts syntax
|
||||
shell: sh
|
||||
run: |
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
# .gitleaks.toml - gitleaks 白名单配置
|
||||
# 仓库: xiaoxia/xiaoxia-saas
|
||||
# 用途: 排除已知的测试密钥、示例配置等误报
|
||||
|
||||
# 允许路径/文件排除
|
||||
[allowlist]
|
||||
description = "全局白名单 - 排除示例配置和测试文件"
|
||||
paths = [
|
||||
# 环境配置示例(无真实密钥)
|
||||
'.env.example',
|
||||
'.env.sample',
|
||||
'*.env.example',
|
||||
'*.env.sample',
|
||||
# 测试文件
|
||||
'tests/',
|
||||
'test/',
|
||||
'*/tests/',
|
||||
'*/test/',
|
||||
# 文档
|
||||
'docs/',
|
||||
'*.md',
|
||||
'*.rst',
|
||||
# 前端依赖
|
||||
'node_modules/',
|
||||
# Python包
|
||||
'site-packages/',
|
||||
# 锁定文件(自动生成)
|
||||
'poetry.lock',
|
||||
'Pipfile.lock',
|
||||
'requirements*.txt.lock',
|
||||
# CI配置本身
|
||||
'.gitea/',
|
||||
# Docker相关
|
||||
'docker-compose*.yml',
|
||||
# gitleaks配置自身
|
||||
'.gitleaks.toml',
|
||||
]
|
||||
|
||||
# 允许的密钥值/占位符正则
|
||||
regexes = [
|
||||
# 占位符模式
|
||||
'''(?i)(your[_-]?password|your[_-]?secret|your[_-]?key|your[_-]?token|changeme|change[_-]?me|placeholder|example[_-]?key|test[_-]?key|dummy|fake|mock|xxx|none|not[_-]?set|TODO|FIXME)''',
|
||||
# 数据库连接字符串中的通用密码(PostgreSQL示例配置)
|
||||
'''postgresql://[^:]+:changeme@''',
|
||||
'''postgresql://[^:]+:your-password@''',
|
||||
'''postgresql://[^:]+:password@localhost''',
|
||||
# Redis示例配置
|
||||
'''redis://:changeme@''',
|
||||
'''redis://:your-redis-password@''',
|
||||
# JWT示例密钥
|
||||
'''(?i)jwt[_-]?secret\s*[:=]\s*["']?(your[_-]?jwt|change|placeholder|secret|example)''',
|
||||
]
|
||||
@@ -0,0 +1,35 @@
|
||||
# vulture.conf - 死代码检测配置
|
||||
# 仓库: xiaoxia/xiaoxia-saas
|
||||
# 用途: 检测未使用的函数、变量、导入、类、方法、属性
|
||||
|
||||
# 扫描目录(空格分隔)
|
||||
path = alembic apps packages scripts
|
||||
|
||||
# 排除路径(每个路径一行,相对于仓库根目录)
|
||||
exclude =
|
||||
tests
|
||||
test
|
||||
*/tests
|
||||
*/test
|
||||
site-packages
|
||||
node_modules
|
||||
migrations
|
||||
.gitea
|
||||
docs
|
||||
scripts/check_*.py
|
||||
scripts/init_*.py
|
||||
|
||||
# 最低置信度 (%)
|
||||
# 0 = 报告所有可能的未使用代码
|
||||
# 100 = 只报告确定未使用的代码
|
||||
# 推荐从 80% 开始,逐步调高
|
||||
min-confidence = 80
|
||||
|
||||
# 输出格式: string, json, yaml
|
||||
format = text
|
||||
|
||||
# 按置信度排序
|
||||
sort-by-size = False
|
||||
|
||||
# 显示置信度
|
||||
show-uncertain = True
|
||||
@@ -0,0 +1,57 @@
|
||||
# vulture_whitelist.py - vulture 白名单文件
|
||||
# 用途: 列出已知被框架/动态调用的代码,避免误报
|
||||
# 参考: https://vulture.readthedocs.io/en/stable/whitelists.html
|
||||
|
||||
# FastAPI / Starlette 框架自动调用
|
||||
# FastAPI route handlers (通过装饰器注册,vulture 可能无法识别)
|
||||
apps.*.main.*
|
||||
apps.*.api.*
|
||||
apps.*.routes.*
|
||||
apps.*.views.*
|
||||
|
||||
# SQLAlchemy ORM
|
||||
# Model 类和字段通过 ORM 框架自动使用
|
||||
apps.*.models.*
|
||||
apps.*.schemas.*
|
||||
packages.*.models.*
|
||||
|
||||
# Pydantic models
|
||||
# Pydantic 字段通过序列化/反序列化使用
|
||||
apps.*.schemas.*
|
||||
packages.*.schemas.*
|
||||
|
||||
# Alembic migrations
|
||||
# Migration 函数由 alembic 自动调用
|
||||
alembic.versions.*.upgrade
|
||||
alembic.versions.*.downgrade
|
||||
|
||||
# Celery tasks
|
||||
# Task 函数通过 celery worker 调用
|
||||
apps.*.tasks.*
|
||||
packages.*.tasks.*
|
||||
|
||||
# CLI scripts / entry points
|
||||
# 脚本通过命令行调用
|
||||
scripts.*
|
||||
|
||||
# 中间件
|
||||
apps.*.middleware.*
|
||||
packages.*.middleware.*
|
||||
|
||||
# 异常类
|
||||
apps.*.exceptions.*
|
||||
packages.*.exceptions.*
|
||||
|
||||
# 配置类
|
||||
apps.*.config.*
|
||||
packages.*.config.*
|
||||
|
||||
# 工具函数(可能被多处间接调用,先白名单,后续清理)
|
||||
apps.*.utils.*
|
||||
packages.*.utils.*
|
||||
apps.*.helpers.*
|
||||
packages.*.helpers.*
|
||||
|
||||
# Dependencies (FastAPI Depends)
|
||||
apps.*.dependencies.*
|
||||
packages.*.dependencies.*
|
||||
Reference in New Issue
Block a user