Update .gitea/workflows/security.yml

This commit is contained in:
2025-08-12 17:29:41 +07:00
parent 4ed5f2ccad
commit 985f9754c4

View File

@@ -28,9 +28,6 @@ jobs:
with: with:
token: ${{ secrets.CI_BOT_TOKEN }} token: ${{ secrets.CI_BOT_TOKEN }}
- name: Install jq (for parsing JSON)
run: sudo apt-get update && sudo apt-get install -y jq
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v4 uses: actions/setup-python@v4
with: with:
@@ -39,41 +36,24 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: | run: |
python -m pip install --upgrade pip --root-user-action=ignore python -m pip install --upgrade pip --root-user-action=ignore
# Pin safety to a v2 line where `check --json` is stable pip install --root-user-action=ignore safety bandit semgrep
pip install --root-user-action=ignore "safety>=2,<3" bandit semgrep
- name: Run Safety check - name: Run Safety check
run: | run: |
if [ -f requirements.txt ]; then safety check -r requirements.txt --json --output safety-report.json || true
safety check -r requirements.txt --json --output safety-report.json || true safety check -r requirements-dev.txt --json --output safety-dev-report.json || true
else
echo "[]" > safety-report.json
fi
if [ -f requirements-dev.txt ]; then
safety check -r requirements-dev.txt --json --output safety-dev-report.json || true
else
echo "[]" > safety-dev-report.json
fi
- name: Run Bandit security scan - name: Run Bandit security scan
run: | run: |
if [ -d src ]; then bandit -r src/ -f json -o bandit-report.json || true
bandit -r src/ -f json -o bandit-report.json || true
else
echo '{"results":[]}' > bandit-report.json
fi
- name: Run Semgrep security scan - name: Run Semgrep security scan
run: | run: |
if [ -d src ]; then semgrep --config=auto src/ --json --output=semgrep-report.json || true
semgrep --config=auto src/ --json --output=semgrep-report.json || true
else
echo '{"results":[]}' > semgrep-report.json
fi
- name: Upload security reports - name: Upload security reports
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: security-reports-${{ github.run_number }} name: security-reports-${{ github.run_number }}
path: | path: |
safety-report.json safety-report.json
@@ -85,43 +65,28 @@ jobs:
run: | run: |
echo "🔍 Checking for critical vulnerabilities..." echo "🔍 Checking for critical vulnerabilities..."
# --- Safety results (robust to array/object formats) --- # Check Safety results
summarize_safety () { if [ -f safety-report.json ]; then
f="$1" critical_count=$(jq '.vulnerabilities | length' safety-report.json 2>/dev/null || echo "0")
if [ -f "$f" ]; then if [ "$critical_count" -gt 0 ]; then
count=$(jq -r ' echo "⚠️ Found $critical_count dependency vulnerabilities"
if type=="array" then length jq '.vulnerabilities[] | "- \(.package_name) \(.installed_version): \(.vulnerability_id)"' safety-report.json
else ((.vulnerabilities // []) | length) else
end echo "✅ No dependency vulnerabilities found"
' "$f" 2>/dev/null || echo "0")
if [ "${count:-0}" -gt 0 ]; then
echo "⚠️ Found $count dependency vulnerabilities in $f"
jq -r '
if type=="array" then
.[] | "- \(.package_name // .name) \(.installed_version // ""): \(.vulnerability_id // .advisory // "N/A")"
else
(.vulnerabilities // [])[] | "- \(.package_name) \(.installed_version): \(.vulnerability_id)"
end
' "$f" || true
else
echo "✅ No dependency vulnerabilities found in $f"
fi
fi fi
} fi
summarize_safety safety-report.json
summarize_safety safety-dev-report.json
# --- Bandit results (count HIGH severity properly) --- # Check Bandit results
if [ -f bandit-report.json ]; then if [ -f bandit-report.json ]; then
high_severity=$(jq '[.results[]? | select(.issue_severity=="HIGH")] | length' bandit-report.json 2>/dev/null || echo "0") high_severity=$(jq '.results[] | select(.issue_severity == "HIGH") | length' bandit-report.json 2>/dev/null | wc -l)
if [ "${high_severity:-0}" -gt 0 ]; then if [ "$high_severity" -gt 0 ]; then
echo "⚠️ Found $high_severity high-severity security issues" echo "⚠️ Found $high_severity high-severity security issues"
else else
echo "✅ No high-severity security issues found" echo "✅ No high-severity security issues found"
fi fi
fi fi
# License compliance check # License compliance check
license-check: license-check:
name: License Compliance name: License Compliance
@@ -133,9 +98,6 @@ jobs:
with: with:
token: ${{ secrets.CI_BOT_TOKEN }} token: ${{ secrets.CI_BOT_TOKEN }}
- name: Install jq (for parsing JSON)
run: sudo apt-get update && sudo apt-get install -y jq
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v4 uses: actions/setup-python@v4
with: with:
@@ -145,9 +107,7 @@ jobs:
run: | run: |
python -m pip install --upgrade pip --root-user-action=ignore python -m pip install --upgrade pip --root-user-action=ignore
pip install --root-user-action=ignore pip-licenses pip install --root-user-action=ignore pip-licenses
if [ -f requirements.txt ]; then pip install --root-user-action=ignore -r requirements.txt
pip install --root-user-action=ignore -r requirements.txt
fi
- name: Check licenses - name: Check licenses
run: | run: |
@@ -155,10 +115,11 @@ jobs:
pip-licenses --format=json --output-file=licenses.json pip-licenses --format=json --output-file=licenses.json
pip-licenses --format=markdown --output-file=licenses.md pip-licenses --format=markdown --output-file=licenses.md
# Check for potentially problematic licenses # Check for problematic licenses
problematic_licenses=("GPL" "AGPL" "LGPL") problematic_licenses=("GPL" "AGPL" "LGPL")
for license in "${problematic_licenses[@]}"; do for license in "${problematic_licenses[@]}"; do
if grep -iq "$license" licenses.json; then if grep -i "$license" licenses.json; then
echo "⚠️ Found potentially problematic license: $license" echo "⚠️ Found potentially problematic license: $license"
fi fi
done done
@@ -167,7 +128,7 @@ jobs:
- name: Upload license report - name: Upload license report
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: license-report-${{ github.run_number }} name: license-report-${{ github.run_number }}
path: | path: |
licenses.json licenses.json
@@ -184,26 +145,25 @@ jobs:
with: with:
token: ${{ secrets.CI_BOT_TOKEN }} token: ${{ secrets.CI_BOT_TOKEN }}
- name: Install jq (for parsing JSON)
run: sudo apt-get update && sudo apt-get install -y jq
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v4 uses: actions/setup-python@v4
with: with:
python-version: ${{ env.PYTHON_VERSION }} python-version: ${{ env.PYTHON_VERSION }}
- name: Install pip-check-updates equivalent
run: |
python -m pip install --upgrade pip --root-user-action=ignore
pip install --root-user-action=ignore pip-review
- name: Check for outdated packages - name: Check for outdated packages
run: | run: |
echo "📦 Checking for outdated packages..." echo "📦 Checking for outdated packages..."
if [ -f requirements.txt ]; then pip install --root-user-action=ignore -r requirements.txt
python -m pip install --upgrade pip --root-user-action=ignore
pip install --root-user-action=ignore -r requirements.txt
fi
pip list --outdated --format=json > outdated-packages.json || true pip list --outdated --format=json > outdated-packages.json || true
if [ -s outdated-packages.json ] && [ "$(cat outdated-packages.json)" != "[]" ]; then if [ -s outdated-packages.json ]; then
echo "📋 Outdated packages found:" echo "📋 Outdated packages found:"
jq -r '.[] | "- \(.name): \(.version) -> \(.latest_version)"' outdated-packages.json cat outdated-packages.json | jq -r '.[] | "- \(.name): \(.version) -> \(.latest_version)"'
else else
echo "✅ All packages are up to date" echo "✅ All packages are up to date"
fi fi
@@ -213,39 +173,45 @@ jobs:
run: | run: |
if [ -s outdated-packages.json ] && [ "$(cat outdated-packages.json)" != "[]" ]; then if [ -s outdated-packages.json ] && [ "$(cat outdated-packages.json)" != "[]" ]; then
echo "📝 Creating dependency update issue..." echo "📝 Creating dependency update issue..."
cat > issue-body.md << 'EOF'
## 📦 Dependency Updates Available
The following packages have updates available: # Create issue body
EOF cat > issue-body.md << 'EOF'
jq -r '.[] | "- **\(.name)**: \(.version) → \(.latest_version)"' outdated-packages.json >> issue-body.md ## 📦 Dependency Updates Available
The following packages have updates available:
EOF
cat outdated-packages.json | jq -r '.[] | "- **\(.name)**: \(.version) → \(.latest_version)"' >> issue-body.md
cat >> issue-body.md << 'EOF' cat >> issue-body.md << 'EOF'
## 🔍 Security Impact ## 🔍 Security Impact
Please review each update for: Please review each update for:
- Security fixes - Security fixes
- Breaking changes - Breaking changes
- Compatibility issues - Compatibility issues
## ✅ Action Items ## ✅ Action Items
- [ ] Review changelog for each package - [ ] Review changelog for each package
- [ ] Test updates in development environment - [ ] Test updates in development environment
- [ ] Update requirements.txt - [ ] Update requirements.txt
- [ ] Run full test suite - [ ] Run full test suite
- [ ] Deploy to staging for validation - [ ] Deploy to staging for validation
---
*This issue was automatically created by the security workflow.*
EOF
---
*This issue was automatically created by the security workflow.*
EOF
echo "Issue body created. In a real implementation, you would create a Gitea issue here." echo "Issue body created. In a real implementation, you would create a Gitea issue here."
cat issue-body.md cat issue-body.md
fi fi
- name: Upload dependency reports - name: Upload dependency reports
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: dependency-reports-${{ github.run_number }} name: dependency-reports-${{ github.run_number }}
path: | path: |
outdated-packages.json outdated-packages.json
@@ -271,47 +237,33 @@ EOF
run: | run: |
python -m pip install --upgrade pip --root-user-action=ignore python -m pip install --upgrade pip --root-user-action=ignore
pip install --root-user-action=ignore radon xenon vulture pip install --root-user-action=ignore radon xenon vulture
if [ -f requirements.txt ]; then pip install --root-user-action=ignore -r requirements.txt
pip install --root-user-action=ignore -r requirements.txt
fi
- name: Calculate code complexity - name: Calculate code complexity
run: | run: |
echo "📊 Calculating code complexity..." echo "📊 Calculating code complexity..."
if [ -d src ]; then radon cc src/ --json > complexity-report.json
radon cc src/ --json > complexity-report.json radon mi src/ --json > maintainability-report.json
radon mi src/ --json > maintainability-report.json
echo "🔍 Complexity Summary:" echo "🔍 Complexity Summary:"
radon cc src/ --average radon cc src/ --average
echo "🔧 Maintainability Summary:"
radon mi src/ echo "🔧 Maintainability Summary:"
else radon mi src/
echo "{}" > complexity-report.json
echo "{}" > maintainability-report.json
echo "No src/ directory found; skipping detailed radon output."
fi
- name: Find dead code - name: Find dead code
run: | run: |
echo "🧹 Checking for dead code..." echo "🧹 Checking for dead code..."
if [ -d src ]; then vulture src/ --json > dead-code-report.json || true
vulture src/ --json > dead-code-report.json || true
else
echo "[]" > dead-code-report.json
fi
- name: Check for code smells - name: Check for code smells
run: | run: |
echo "👃 Checking for code smells..." echo "👃 Checking for code smells..."
if [ -d src ]; then xenon --max-absolute B --max-modules A --max-average A src/ || true
xenon --max-absolute B --max-modules A --max-average A src/ || true
else
echo "No src/ directory found; skipping xenon."
fi
- name: Upload quality reports - name: Upload quality reports
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: code-quality-reports-${{ github.run_number }} name: code-quality-reports-${{ github.run_number }}
path: | path: |
complexity-report.json complexity-report.json
@@ -322,13 +274,10 @@ EOF
security-summary: security-summary:
name: Security Summary name: Security Summary
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [dependency-scan, license-check, code-quality] needs: [dependency-scan, docker-security-scan, license-check, code-quality]
if: always() if: always()
steps: steps:
- name: Install jq (for parsing JSON)
run: sudo apt-get update && sudo apt-get install -y jq
- name: Download all artifacts - name: Download all artifacts
uses: actions/download-artifact@v3 uses: actions/download-artifact@v3
@@ -344,36 +293,30 @@ EOF
echo "## 📊 Results" >> security-summary.md echo "## 📊 Results" >> security-summary.md
echo "" >> security-summary.md echo "" >> security-summary.md
# Dependency scan results (support array/object formats) # Dependency scan results
if ls security-reports-*/safety-report.json >/dev/null 2>&1; then if [ -f security-reports-*/safety-report.json ]; then
vuln_count=$(jq -s ' vuln_count=$(jq '.vulnerabilities | length' security-reports-*/safety-report.json 2>/dev/null || echo "0")
def countfile: if [ "$vuln_count" -eq 0 ]; then
if type=="array" then length
else ((.vulnerabilities // []) | length)
end;
add | (if type=="number" then . else 0 end)
' security-reports-*/safety-report.json 2>/dev/null || echo "0")
if [ "${vuln_count:-0}" -eq 0 ]; then
echo "- ✅ **Dependency Scan**: No vulnerabilities found" >> security-summary.md echo "- ✅ **Dependency Scan**: No vulnerabilities found" >> security-summary.md
else else
echo "- ⚠️ **Dependency Scan**: ${vuln_count} vulnerabilities found" >> security-summary.md echo "- ⚠️ **Dependency Scan**: $vuln_count vulnerabilities found" >> security-summary.md
fi fi
else else
echo "- ❓ **Dependency Scan**: Results not available" >> security-summary.md echo "- ❓ **Dependency Scan**: Results not available" >> security-summary.md
fi fi
# Docker scan results (Trivy removed) # Docker scan results (removed Trivy)
echo "- ⏭️ **Docker Scan**: Skipped (Trivy removed)" >> security-summary.md echo "- ⏭️ **Docker Scan**: Skipped (Trivy removed)" >> security-summary.md
# License check results # License check results
if ls license-report-*/licenses.json >/dev/null 2>&1; then if [ -f license-report-*/licenses.json ]; then
echo "- ✅ **License Check**: Completed" >> security-summary.md echo "- ✅ **License Check**: Completed" >> security-summary.md
else else
echo "- ❓ **License Check**: Results not available" >> security-summary.md echo "- ❓ **License Check**: Results not available" >> security-summary.md
fi fi
# Code quality results # Code quality results
if ls code-quality-reports-*/complexity-report.json >/dev/null 2>&1; then if [ -f code-quality-reports-*/complexity-report.json ]; then
echo "- ✅ **Code Quality**: Analyzed" >> security-summary.md echo "- ✅ **Code Quality**: Analyzed" >> security-summary.md
else else
echo "- ❓ **Code Quality**: Results not available" >> security-summary.md echo "- ❓ **Code Quality**: Results not available" >> security-summary.md
@@ -388,6 +331,6 @@ EOF
- name: Upload security summary - name: Upload security summary
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: security-summary-${{ github.run_number }} name: security-summary-${{ github.run_number }}
path: security-summary.md path: security-summary.md