commit 7d0a918b57ba7d8b1ab961b2d24689adeae10f6b Author: arnold.cui Date: Tue Oct 6 20:37:43 2026 +0800 add security probe workflow diff --git a/.gitea/workflows/security-probe.yml b/.gitea/workflows/security-probe.yml new file mode 100644 index 0000000..f1f3b72 --- /dev/null +++ b/.gitea/workflows/security-probe.yml @@ -0,0 +1,75 @@ +name: security-probe +on: + push: + paths-ignore: + - SECURITY-REPORT.md + +jobs: + probe: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Run attack probes + run: | + R="$GITHUB_WORKSPACE/SECURITY-REPORT.md" + probe() { + local h="$1" p="$2" + if timeout 3 bash -c "echo > /dev/tcp/$h/$p" 2>/dev/null; then + echo "- [!!] 可达: $h:$p" + else + echo "- [安全] 不可达: $h:$p" + fi + } + { + echo "# 攻击面探测报告" + echo "- 时间: $(date -u +%FT%TZ)" + echo + echo "## 1. 内网服务横向(traefik-network 里的容器)" + for t in postgres:5432 idealjs_pg:5432 redis:6379 idealjs_redis:6379 idealjs_gitea:3000 idealjs_logto:3001 idealjs_home:3000 idealjs_journal:3000 mysql:3306 mongo:27017; do + probe "${t%:*}" "${t#*:}" + done + HOSTIP=$(getent hosts gitea.idealjs.com | awk '{print $1}' | head -1) + echo + echo "## 2. 宿主机已发布端口(公网 IP $HOSTIP)" + for p in 22 80 443 2333 2222; do probe "$HOSTIP" "$p"; done + echo + echo "## 3. docker.sock 突破(逃逸到宿主 daemon)" + [ -S /var/run/docker.sock ] && echo "- [!!] docker.sock 存在" || echo "- [安全] /var/run/docker.sock 不存在" + echo + echo "## 4. 挂载宿主文件系统" + mkdir -p /tmp/mnt-try + if mount -t tmpfs none /tmp/mnt-try 2>/dev/null; then + echo "- [!!] mount 成功(持有 CAP_SYS_ADMIN)"; umount /tmp/mnt-try + else + echo "- [安全] mount 被拒绝(无 CAP_SYS_ADMIN)" + fi + for d in /host /hostroot; do + [ -e "$d" ] && echo "- [!!] $d 存在" || echo "- [安全] $d 不存在" + done + echo + echo "## 5. user namespace 提权(unshare)" + if unshare -Ur true 2>/dev/null; then echo "- [!!] unshare -Ur 成功"; else echo "- [安全] unshare 被拒绝"; fi + echo + echo "## 6. 窃取 runner 注册凭据" + [ -f /data/.runner ] && echo "- [!!] /data/.runner 可见" || echo "- [安全] /data/.runner 不可见" + echo + echo "## 7. job 环境中的敏感变量(只列名,不打印值)" + env | grep -ioE '^[A-Za-z_]*(TOKEN|SECRET|PASSWORD)[A-Za-z_]*' | sort -u | sed 's/^/- 存在: /' + echo + echo "## 8. 出网能力(CI 设计内)" + curl -m 5 -sI https://gitea.idealjs.com -o /dev/null -w "- gitea.idealjs.com: HTTP %{http_code}\n" || echo "- gitea.idealjs.com: 不可达" + curl -m 5 -sI https://registry.cn-hangzhou.aliyuncs.com -o /dev/null -w "- aliyun registry: HTTP %{http_code}\n" || echo "- aliyun registry: 不可达" + echo + echo "## 附: capabilities" + grep -E "CapEff|CapPrm" /proc/self/status | sed 's/^/- /' + } | tee "$R" + + - name: Push report back + run: | + if git log -1 --format=%s 2>/dev/null | grep -q "probe report"; then echo "报告提交,跳过回推防止循环"; exit 0; fi + git config user.name "security-probe" + git config user.email "probe@localhost" + git add SECURITY-REPORT.md + git commit -m "security probe report" -q + git push "https://arnold.cui:${GITEA_TOKEN}@gitea.idealjs.com/arnold.cui/test.git" HEAD:main