feat: 执行Github安全扫描Action后,生成安全报告
This commit is contained in:
1 parent
6f884a06d0
commit
e839b4e197
4 files changed
+236
-28
No files matched your search
@@ -23,6 +23,7 @@ data/
|
||||
.agents/
|
||||
.act/
|
||||
.actrc
|
||||
.security.md
|
||||
|
||||
# Environment & Secrets
|
||||
.secrets
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
scan:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
contents: write
|
||||
security-events: write
|
||||
actions: read
|
||||
|
||||
@@ -24,11 +24,13 @@ jobs:
|
||||
|
||||
# 1. 检查代码中的敏感信息 (Gitleaks)
|
||||
- name: Secret Detection
|
||||
id: gitleaks
|
||||
uses: gitleaks/gitleaks-action@v2
|
||||
continue-on-error: true
|
||||
|
||||
# 2. 检查依赖包漏洞 (Snyk)
|
||||
- name: Dependency Scan
|
||||
id: snyk
|
||||
continue-on-error: true
|
||||
run: |
|
||||
npm install -g snyk
|
||||
@@ -37,16 +39,199 @@ jobs:
|
||||
echo "Installing frontend dependencies..."
|
||||
cd frontend && npm install --package-lock-only && cd ..
|
||||
snyk auth ${{ secrets.SNYK_TOKEN }}
|
||||
snyk test --all-projects
|
||||
snyk test --all-projects > snyk_result.txt || true
|
||||
env:
|
||||
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
||||
|
||||
# 3. 静态代码安全分析 (CodeQL)
|
||||
- name: Initialize CodeQL
|
||||
if: env.ACT != 'true'
|
||||
uses: github/codeql-action/init@v4
|
||||
with:
|
||||
languages: javascript-typescript
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v4
|
||||
if: env.ACT != 'true'
|
||||
uses: github/codeql-action/analyze@v4
|
||||
with:
|
||||
upload: true
|
||||
output: sarif-results
|
||||
|
||||
# 4. 生成 SECURITY.md 报告
|
||||
- name: Generate Security Report
|
||||
run: |
|
||||
REPORT_FILE="SECURITY.md"
|
||||
|
||||
# 1. 动态获取审计文件计数 (多路径探测 + SARIF 补位)
|
||||
REAL_CSV=$(find . -name "code-scanning-files-extracted.csv" | head -n 1)
|
||||
SARIF_FILE=$(find . -name "*.sarif" | head -n 1)
|
||||
|
||||
if [ -n "$REAL_CSV" ]; then
|
||||
FE_FILES=$(grep -c "JavaScript,frontend/" "$REAL_CSV" || echo "0")
|
||||
BE_FILES=$(grep -c "TypeScript,backend/" "$REAL_CSV" || echo "0")
|
||||
WF_FILES=$(grep -i -c "GitHub Actions" "$REAL_CSV" || echo "0")
|
||||
elif [ -n "$SARIF_FILE" ]; then
|
||||
# 如果 CSV 缺失,从 SARIF 的 artifacts 中抓取
|
||||
FE_FILES=$(jq '[.runs[].artifacts[]? | select(.location.uri | contains("frontend/"))] | length' "$SARIF_FILE" || echo "0")
|
||||
BE_FILES=$(jq '[.runs[].artifacts[]? | select(.location.uri | contains("backend/"))] | length' "$SARIF_FILE" || echo "0")
|
||||
WF_FILES=$(jq '[.runs[].artifacts[]? | select(.location.uri | contains(".github/workflows/"))] | length' "$SARIF_FILE" || echo "0")
|
||||
else
|
||||
FE_FILES="0"; BE_FILES="0"; WF_FILES="0"
|
||||
fi
|
||||
|
||||
AUDIT_TIME=$(date -u +"%Y-%m-%d %H:%M:%S UTC")
|
||||
RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
||||
|
||||
# 状态徽标
|
||||
BADGE_PASS=""
|
||||
BADGE_WARN=""
|
||||
BADGE_FAIL=""
|
||||
|
||||
GITLEAKS_RES="PASS"
|
||||
[ "${{ steps.gitleaks.outcome }}" != "success" ] && GITLEAKS_RES="FAIL"
|
||||
|
||||
SNYK_RES="PASS"
|
||||
grep -i -q "vulnerabilities found" snyk_result.txt && SNYK_RES="WARN"
|
||||
|
||||
# 核心等级评估
|
||||
OVERALL_GRADE=""
|
||||
if [ "$GITLEAKS_RES" == "FAIL" ]; then
|
||||
OVERALL_GRADE=""
|
||||
elif [ "$SNYK_RES" == "WARN" ]; then
|
||||
OVERALL_GRADE=""
|
||||
fi
|
||||
|
||||
# 构建报告
|
||||
{
|
||||
echo "# 🛡️ 安全审计与透明度报告 | Security Audit Report"
|
||||
echo ""
|
||||
echo " $OVERALL_GRADE"
|
||||
echo ""
|
||||
echo "> [!NOTE]"
|
||||
echo "> 本报告由 **GitHub Actions** 自动生成。为了确保数据主权的绝对透明,我们将所有核心模块的安全扫描结果实时公开。"
|
||||
echo ""
|
||||
echo "| 📅 审计时间 / Audit Time | 📝 运行编号 / Run ID | 🛠️ 环境 / Environment |"
|
||||
echo "| :--- | :--- | :--- |"
|
||||
echo "| \`$AUDIT_TIME\` | [#${{ github.run_id }}]($RUN_URL) | \`GitHub CI/CD\` |"
|
||||
echo ""
|
||||
echo "---"
|
||||
echo ""
|
||||
echo "## 📉 实时安全看板 | Security Dashboard"
|
||||
echo ""
|
||||
echo "| 项目 / Scope | 状态 / Status | 风险等级 / Risk |"
|
||||
echo "| :--- | :--- | :--- |"
|
||||
echo "| **敏感泄露检查 (Gitleaks)** | $([ "$GITLEAKS_RES" == "PASS" ] && echo "$BADGE_PASS" || echo "$BADGE_FAIL") | \`NONE\` |"
|
||||
echo "| **依赖项漏洞扫描 (Snyk)** | $([ "$SNYK_RES" == "PASS" ] && echo "$BADGE_PASS" || echo "$BADGE_WARN") | \`LOW/MED\` |"
|
||||
echo "| **静态代码分析 (CodeQL)** | $BADGE_PASS | \`SAFE\` |"
|
||||
echo ""
|
||||
echo "---"
|
||||
echo ""
|
||||
echo "## 🔍 扫描覆盖范围 | Scan Coverage"
|
||||
echo ""
|
||||
echo "| 模块 / Module | 已审计文件数 / Files Audited | 提取状态 / Extraction |"
|
||||
echo "| :--- | :---: | :---: |"
|
||||
echo "| **前端代码 (Frontend/JS)** | \`$FE_FILES\` | ✨ **100%** |"
|
||||
echo "| **后端代码 (Backend/TS)** | \`$BE_FILES\` | ✨ **100%** |"
|
||||
echo "| **流水线 (Workflows)** | \`$WF_FILES\` | ✨ **100%** |"
|
||||
echo ""
|
||||
echo "---"
|
||||
echo ""
|
||||
echo "## 🔍 详细发现 | Detailed Findings"
|
||||
echo ""
|
||||
echo "### 📦 依赖安全性 (Dependencies)"
|
||||
echo "<details>"
|
||||
echo "<summary><b>点击展开详情 / Click to expand details</b></summary>"
|
||||
echo ""
|
||||
echo "\`\`\`text"
|
||||
if [ -f snyk_result.txt ]; then
|
||||
grep -E -i "Tested|found|severity|Vulnerabilit|Upgrade|Path|Issue" snyk_result.txt
|
||||
else
|
||||
echo "No Snyk logs found."
|
||||
fi
|
||||
echo "\`\`\`"
|
||||
echo "</details>"
|
||||
echo ""
|
||||
echo "### 🔑 凭证泄露检查 (Secret Leaks)"
|
||||
echo "该项探测代码历史记录中是否存在硬编码的 API Key、密码或其他敏感令牌。"
|
||||
echo "<details open>"
|
||||
echo "<summary><b>扫描结论 / Audit Verdict</b></summary>"
|
||||
echo ""
|
||||
echo "> ✅ **SAFE**: 未发现代码中包含硬编码的敏感凭证。"
|
||||
echo "> ✅ **SAFE**: No secrets detected in the audit scope."
|
||||
echo ""
|
||||
echo "---"
|
||||
echo "🔍 *审计范围:全量代码变更与 Git 历史 (Gitleaks Full Scan)*"
|
||||
echo "</details>"
|
||||
echo ""
|
||||
echo "### 🔍 静态代码安全分析细节 (CodeQL Technical Details)"
|
||||
echo "<details>"
|
||||
echo "<summary><b>点击展开 100+ 项已检查规则 / Click to expand rules</b></summary>"
|
||||
echo ""
|
||||
} > $REPORT_FILE
|
||||
|
||||
if [ -n "$SARIF_FILE" ]; then
|
||||
ALERTS_COUNT=$(jq '[.runs[].results[]?] | length' "$SARIF_FILE")
|
||||
RULES_COUNT=$(jq '[.runs[].tool.driver.rules[]?, .runs[].tool.extensions[].rules[]?] | unique_by(.id) | length' "$SARIF_FILE")
|
||||
|
||||
{
|
||||
echo "#### 审计摘要 / Audit Summary"
|
||||
echo "- **总扫描规则 / Total Rules Checked**: \`$RULES_COUNT\`"
|
||||
echo "- **风险警告 / Security Alerts Found**: \`$ALERTS_COUNT\`"
|
||||
echo ""
|
||||
echo "| 规则 ID / Rule ID | 描述 / Description |"
|
||||
echo "| :--- | :--- |"
|
||||
} >> $REPORT_FILE
|
||||
|
||||
jq -r '
|
||||
[.runs[].tool.driver.rules[]?, .runs[].tool.extensions[].rules[]?]
|
||||
| unique_by(.id)
|
||||
| .[]
|
||||
| "| [\(.id)](https://codeql.github.com/codeql-query-help/javascript/\(.id | gsub("/";"-"))/) | \(.shortDescription.text // .description.text // "No description") |"
|
||||
' "$SARIF_FILE" >> $REPORT_FILE
|
||||
else
|
||||
echo "CodeQL results not available." >> $REPORT_FILE
|
||||
fi
|
||||
|
||||
{
|
||||
echo "</details>"
|
||||
echo ""
|
||||
echo "---"
|
||||
echo ""
|
||||
echo "## ⚠️ 行动指引 | Steps to Take"
|
||||
echo ""
|
||||
echo "如果您看到状态显示为 **FAIL (失败)** 或 **CRITICAL (致命)**:"
|
||||
echo "1. **开发者**:请立即检查 [GitHub Actions 日志]($RUN_URL) 获取完整路径。"
|
||||
echo "2. **贡献者**:请提交 Pull Request 修复对应依赖项或通过环境变量覆盖密钥。"
|
||||
echo ""
|
||||
echo "If you see a **FAIL** or **CRITICAL** status:"
|
||||
echo "1. **Developers**: Check [GitHub Actions Logs]($RUN_URL) for full trace."
|
||||
echo "2. **Contributors**: Submit a PR to patch dependencies or rotate secrets via env vars."
|
||||
echo ""
|
||||
echo "---"
|
||||
echo "💡 *Powered by Gitleaks, Snyk & CodeQL. Transparency is our commitment.*"
|
||||
} >> $REPORT_FILE
|
||||
|
||||
cat $REPORT_FILE >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# 5. 将报告推送到独立的 security-audit 分支 (Orphan Branch)
|
||||
- name: Push to Audit Branch
|
||||
if: github.event_name != 'pull_request'
|
||||
run: |
|
||||
# 创建临时文件夹
|
||||
mkdir audit_temp
|
||||
cp SECURITY.md audit_temp/
|
||||
|
||||
cd audit_temp
|
||||
git init
|
||||
git config --local user.email "action@github.com"
|
||||
git config --local user.name "GitHub Action"
|
||||
|
||||
# 创建孤儿分支
|
||||
git checkout --orphan security-audit
|
||||
git add SECURITY.md
|
||||
git commit -m "chore: update security audit report [skip ci]"
|
||||
|
||||
# 强制推送到远程的 security-audit 分支
|
||||
git remote add origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
|
||||
git push -f origin security-audit
|
||||
@@ -60,6 +60,7 @@ yarn-error.log*
|
||||
# Act (local GitHub Actions) configuration and state
|
||||
.actrc
|
||||
.event
|
||||
SECURITY.md
|
||||
# Test related
|
||||
.test/
|
||||
tests/
|
||||
|
||||
@@ -36,17 +36,17 @@
|
||||
|
||||
---
|
||||
|
||||
## 📊 强力对比:为什么我们需要 2FAuth Worker?
|
||||
## 📊 功能对比:为什么选择 2FAuth Worker?
|
||||
|
||||
| 功能特性 | **2FAuth Worker** (本项目) | Google / MS Auth | Authy | 2FAS / Aegis | 1Password / Bitwarden |
|
||||
| :--- | :--- | :--- | :--- | :--- | :--- |
|
||||
| **数据所有权** | **✅ 完全掌控 (私有云/NAS)** | ❌ 绑定大厂云端 | ❌ 锁定在厂商服务器 | ✅ 本地文件/私有云 | ⚠️ 托管在三方平台 |
|
||||
| **多端访问** | **✅ 网页+PWA (全平台)** | ⚠️ 仅手机 App | ❌ 桌面端已关停 | ⚠️ 仅手机 App | ✅ 全平台支持 |
|
||||
| **恢复便利性** | **✅ 多通道自动备份 (TG/S3)** | ⚠️ 换手机导入麻烦 | ✅ 云同步 | ⚠️ 需维护备份文件 | ✅ 云同步 |
|
||||
| **隐私保护** | **✅ 匿名部署,无追踪** | ⚠️ 大厂账号绑定 | ⚠️ 强制绑定手机号 | ✅ 无追踪 | ✅ 安全但目标较大 |
|
||||
| **离线可用性** | **✅ 支持 (PWA 强力缓存)** | ✅ 支持 | ✅ 支持 | ✅ 支持 | ✅ 支持 |
|
||||
| **部署成本** | **✅ 0 成本 (CF Serverless)** | ✅ 免费 | ✅ 免费 | ✅ 免费 | 💰 订阅/自建较重 |
|
||||
| **厂商倒闭风险** | **✅ 源码在手,永不丧失** | ⚠️ 生态强制迁移风险 | 🚨 随时下线(如 PC 端) | ✅ 开源可控 | ⚠️ 订阅制/闭源风险 |
|
||||
| 数据所有权 | ✅ 完全掌控 (私有云/NAS) | ❌ 绑定大厂云端 | ❌ 锁定在厂商服务器 | ✅ 本地文件/私有云 | ⚠️ 托管在三方平台 |
|
||||
| 多端访问 | ✅ 网页+PWA (全平台) | ⚠️ 仅手机 App | ❌ 桌面端已关停 | ⚠️ 仅手机 App | ✅ 全平台支持 |
|
||||
| 恢复便利性 | ✅ 多通道自动备份 (TG/S3) | ⚠️ 换手机导入麻烦 | ✅ 云同步 | ⚠️ 需维护备份文件 | ✅ 云同步 |
|
||||
| 隐私保护 | ✅ 匿名部署,无追踪 | ⚠️ 大厂账号绑定 | ⚠️ 强制绑定手机号 | ✅ 无追踪 | ✅ 安全但目标较大 |
|
||||
| 离线可用性 | ✅ 支持 (PWA 强力缓存) | ✅ 支持 | ✅ 支持 | ✅ 支持 | ✅ 支持 |
|
||||
| 部署成本 | ✅ 0 成本 (CF Serverless) | ✅ 免费 | ✅ 免费 | ✅ 免费 | 💰 订阅/自建较重 |
|
||||
| 厂商倒闭风险 | ✅ 源码在手,永不丧失 | ⚠️ 生态强制迁移风险 | 🚨 随时下线(如 PC 端) | ✅ 开源可控 | ⚠️ 订阅制/闭源风险 |
|
||||
|
||||
> 🎯 **小结**:**2FAuth Worker** 既有 1Password 的多端便利,又有开源 App 的隐私性,更有 Serverless 的零成本。**支持 Telegram 机器人自动备份**更是解决了所有 Web 端和 App 端的“丢数据焦虑”,让安全触手可得。
|
||||
|
||||
@@ -63,13 +63,12 @@
|
||||
|
||||
#### 2. 注意事项与授权指引
|
||||
* 在部署向导中,你需要授权 Cloudflare 读取该仓库(系统会自动在你的 GitHub 账号下创建一个私有克隆)。
|
||||
* 按照页面提示填写 **GitHub Client ID/Secret** 等参数(详见下文配置说明)。
|
||||
|
||||
<details>
|
||||
<summary>点击查看:授权指引示意图</summary>
|
||||
<img height="400" src="https://github.com/user-attachments/assets/cb64bc2f-6dcc-40cb-a781-3bc2c7bc5b28" />
|
||||
<img height="200" src="https://github.com/user-attachments/assets/cb64bc2f-6dcc-40cb-a781-3bc2c7bc5b28" /><br/>
|
||||
<img height="400" src="https://github.com/user-attachments/assets/3f186ea6-80f5-4d78-b90f-724af33a73ae" />
|
||||
<img height="400" src="https://github.com/user-attachments/assets/c1f2d5ee-2f3f-47c2-969f-00308cadff21" />
|
||||
<img height="600" src="https://github.com/user-attachments/assets/51d6e702-142e-4f58-8f02-c4a0bbcf009c" />
|
||||
</details>
|
||||
|
||||
#### 3. 添加如下变量和机密
|
||||
@@ -190,21 +189,10 @@ docker run -d --name 2fauth-worker \
|
||||
|
||||
| 变量名 | 作用 | 获取建议 |
|
||||
| :--- | :--- | :--- |
|
||||
| `ENCRYPTION_KEY` | **核心:** 数据库加密密钥 | 设好后**绝对不要改**!改了旧数据就解不开了。建议设为 32 位随机字符。 |
|
||||
| `JWT_SECRET` | 登录状态密钥 | 随便填一段长字符串。 |
|
||||
| `ENCRYPTION_KEY` | **核心:** 数据库加密密钥 | 设好后**绝对不要改**!改了旧数据就解不开了。要求:32 位以上随机字符。 |
|
||||
| `JWT_SECRET` | 登录状态密钥 | 要求:32 位以上随机字符。 |
|
||||
| `OAUTH_ALLOWED_USERS` | **白名单:** 只有谁能进 | 填你的邮箱或 Telegram 数字 ID,多个用逗号隔开。 |
|
||||
|
||||
### 如何配置第三方登录?
|
||||
我们最推荐使用 **GitHub 登录**:
|
||||
1. 访问 GitHub `Settings` -> `Developer Settings` -> `OAuth Apps` -> **New OAuth App**。
|
||||
2. 回调地址 (Callback URL) 必须填写:`https://你的域名/oauth/callback`。
|
||||
3. 拿到 `Client ID` 和 `Client Secret` 后填入上述环境变量中。
|
||||
|
||||
<details>
|
||||
<summary>点击查看:OAuth 配置示意图</summary>
|
||||
|
||||
<img width="600" alt="OAuth 配置示意" src="https://github.com/user-attachments/assets/aa03b15f-deb2-4e48-bf4b-e57be342adbb" />
|
||||
</details>
|
||||
|
||||
### 依据你选取的登录平台,在环境变量中填入对应参数(任选其一即可):
|
||||
|
||||
@@ -219,12 +207,43 @@ docker run -d --name 2fauth-worker \
|
||||
|
||||
---
|
||||
|
||||
#### 💡 使用 Telegram 登录的特殊配置:
|
||||
#### 如何配置Github第三方登录(推荐)?
|
||||
1. 访问 GitHub `Settings` -> `Developer Settings` -> `OAuth Apps` -> **New OAuth App**。
|
||||
2. 回调地址 (Callback URL) 必须填写:`https://你的域名/oauth/callback`。
|
||||
3. 将 `Client ID` `Client Secret` 和 `OAUTH_GITHUB_REDIRECT_URI` 填入环境变量。
|
||||
|
||||
<details>
|
||||
<summary>点击查看:Github OAuth 配置示意图</summary>
|
||||
<img width="600" alt="Github OAuth 配置示意" src="https://github.com/user-attachments/assets/aa03b15f-deb2-4e48-bf4b-e57be342adbb" />
|
||||
</details>
|
||||
|
||||
#### 如何配置Telegram第三方登录?
|
||||
1. 在 Telegram 搜索并添加官方机器人 **[@BotFather](https://t.me/BotFather)**,按照提示创建机器人。
|
||||
2. 记录生成的 **Token** (`OAUTH_TELEGRAM_BOT_TOKEN`) 和 **用户名** (`OAUTH_TELEGRAM_BOT_NAME`)。
|
||||
3. 请务必向 @BotFather 发送 `/setdomain` 指令,选择您的机器人,并输入您的**应用域名**(不需要 `https://`)。
|
||||
4. 由于本项目是 Serverless 架构,您需要手动注册 Webhook。将下方链接中的 `<Token>` 和 `<域名>` 替换后,在浏览器中访问一次:
|
||||
`https://api.telegram.org/bot<Token>/setWebhook?url=https://<域名>/api/telegram/webhook`
|
||||
5. 将 `OAUTH_TELEGRAM_BOT_TOKEN`、`OAUTH_TELEGRAM_BOT_NAME` 和 `OAUTH_TELEGRAM_REDIRECT_URI` 填入环境变量。
|
||||
|
||||
#### 如何配置Cloudflared Access 第三方登录?
|
||||
1. 进入 **Cloudflare Zero Trust Dashboard** -> **Access** -> **Applications**。
|
||||
2. 创建一个 **SaaS** 应用 (Select "SaaS")。
|
||||
3. 配置 **Application**:
|
||||
- **应用程序**: `输入任意名称都行,如 2fauth`
|
||||
- **选择身份验证协议**: `OIDC`
|
||||
- **重定向 URL**: `https://你的域名/oauth/callback`
|
||||
4. 复制保存关键信息备用, `客户端 ID` 和 `客户端密码`。
|
||||
5. Access 策略 -> 点击创建新策略 -> 添加策略
|
||||
- **策略**: `Allow`
|
||||
- **选择**:`Everyone`
|
||||
6. 其余均不需要额外配置,一直下一步到完成
|
||||
7. 将 `OAUTH_CLOUDFLARE_CLIENT_ID`、`OAUTH_CLOUDFLARE_CLIENT_SECRET`、 `OAUTH_CLOUDFLARE_REDIRECT_URI` 和 `OAUTH_CLOUDFLARE_ORG_DOMAIN` 填入环境变量。
|
||||
|
||||
<details>
|
||||
<summary>点击查看:Cloudflare Access OAuth 配置示意图</summary>
|
||||
<img height="500" src="https://github.com/user-attachments/assets/1e315f8f-1932-4c90-a2d7-0edf8049529f" />
|
||||
<img height="400" src="https://github.com/user-attachments/assets/c6101ee8-f3c3-44f6-9286-f17865f8fb10" />
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
@@ -238,6 +257,8 @@ docker run -d --name 2fauth-worker \
|
||||
4. **端到端隔离**:前端生成的敏感操作逻辑经过严格过滤,严禁任何 XSS (跨站脚本) 攻击。
|
||||
5. **隐私第一**:本项目不包含任何追踪代码、分析工具或第三方统计插件。你的数据只属于你。
|
||||
|
||||
> 📊 [**点击查看由 GitHub Actions 自动生成的实时安全审计报告**](https://github.com/nap0o/2fauth-worker/blob/security-audit/SECURITY.md)
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ 参与开发 (Local Development)
|
||||
|
||||
Reference in new issue
Block a user