222 lines
7.2 KiB
YAML
222 lines
7.2 KiB
YAML
name: Security & Dependency Updates
|
|
|
|
on:
|
|
schedule:
|
|
# Run security scans daily at 3 AM UTC
|
|
- cron: "0 3 * * *"
|
|
workflow_dispatch:
|
|
push:
|
|
paths:
|
|
- "requirements*.txt"
|
|
- "Dockerfile"
|
|
- ".gitea/workflows/security.yml"
|
|
|
|
env:
|
|
PYTHON_VERSION: "3.11"
|
|
# GitHub token for better rate limits and authentication
|
|
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
|
|
|
jobs:
|
|
# Dependency vulnerability scan
|
|
dependency-scan:
|
|
name: Dependency Security Scan
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
with:
|
|
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
|
|
uses: actions/setup-python@v4
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
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>=2,<3" bandit semgrep
|
|
|
|
- name: Run Safety check
|
|
run: |
|
|
if [ -f requirements.txt ]; then
|
|
safety check -r requirements.txt --json --output safety-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
|
|
run: |
|
|
if [ -d src ]; then
|
|
bandit -r src/ -f json -o bandit-report.json || true
|
|
else
|
|
echo '{"results":[]}' > bandit-report.json
|
|
fi
|
|
|
|
- name: Run Semgrep security scan
|
|
run: |
|
|
if [ -d src ]; then
|
|
semgrep --config=auto src/ --json --output=semgrep-report.json || true
|
|
else
|
|
echo '{"results":[]}' > semgrep-report.json
|
|
fi
|
|
|
|
- name: Upload security reports
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: security-reports-${{ github.run_number }}
|
|
path: |
|
|
safety-report.json
|
|
safety-dev-report.json
|
|
bandit-report.json
|
|
semgrep-report.json
|
|
|
|
- name: Check for critical vulnerabilities
|
|
run: |
|
|
echo "🔍 Checking for critical vulnerabilities..."
|
|
|
|
# --- Safety results (robust to array/object formats) ---
|
|
summarize_safety () {
|
|
f="$1"
|
|
if [ -f "$f" ]; then
|
|
count=$(jq -r '
|
|
if type=="array" then length
|
|
else ((.vulnerabilities // []) | length)
|
|
end
|
|
' "$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
|
|
}
|
|
summarize_safety safety-report.json
|
|
summarize_safety safety-dev-report.json
|
|
|
|
# --- Bandit results (count HIGH severity properly) ---
|
|
if [ -f bandit-report.json ]; then
|
|
high_severity=$(jq '[.results[]? | select(.issue_severity=="HIGH")] | length' bandit-report.json 2>/dev/null || echo "0")
|
|
if [ "${high_severity:-0}" -gt 0 ]; then
|
|
echo "⚠️ Found $high_severity high-severity security issues"
|
|
else
|
|
echo "✅ No high-severity security issues found"
|
|
fi
|
|
fi
|
|
|
|
# License compliance check
|
|
license-check:
|
|
name: License Compliance
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
with:
|
|
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
|
|
uses: actions/setup-python@v4
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
|
|
- name: Install pip-licenses
|
|
run: |
|
|
python -m pip install --upgrade pip --root-user-action=ignore
|
|
pip install --root-user-action=ignore pip-licenses
|
|
if [ -f requirements.txt ]; then
|
|
pip install --root-user-action=ignore -r requirements.txt
|
|
fi
|
|
|
|
- name: Check licenses
|
|
run: |
|
|
echo "📄 Checking dependency licenses..."
|
|
pip-licenses --format=json --output-file=licenses.json
|
|
pip-licenses --format=markdown --output-file=licenses.md
|
|
|
|
# Check for potentially problematic licenses
|
|
problematic_licenses=("GPL" "AGPL" "LGPL")
|
|
for license in "${problematic_licenses[@]}"; do
|
|
if grep -iq "$license" licenses.json; then
|
|
echo "⚠️ Found potentially problematic license: $license"
|
|
fi
|
|
done
|
|
|
|
echo "✅ License check completed"
|
|
|
|
- name: Upload license report
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: license-report-${{ github.run_number }}
|
|
path: |
|
|
licenses.json
|
|
licenses.md
|
|
|
|
# Dependency update check
|
|
dependency-update:
|
|
name: Check for Dependency Updates
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
with:
|
|
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
|
|
uses: actions/setup-python@v4
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
|
|
- name: Check for outdated packages
|
|
run: |
|
|
echo "📦 Checking for outdated packages..."
|
|
if [ -f requirements.txt ]; then
|
|
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
|
|
|
|
if [ -s outdated-packages.json ] && [ "$(cat outdated-packages.json)" != "[]" ]; then
|
|
echo "📋 Outdated packages found:"
|
|
jq -r '.[] | "- \(.name): \(.version) -> \(.latest_version)"' outdated-packages.json
|
|
else
|
|
echo "✅ All packages are up to date"
|
|
fi
|
|
|
|
- name: Create dependency update issue
|
|
if: github.event_name == 'schedule'
|
|
run: |
|
|
if [ -s outdated-packages.json ] && [ "$(cat outdated-packages.json)" != "[]" ]; then
|
|
echo "📝 Creating dependency update issue..."
|
|
cat > issue-body.md << 'EOF'
|
|
## 📦 Dependency Updates Available
|
|
|
|
The following packages have updates available:
|
|
EOF
|
|
jq -r '.[] | "- **\(.name)**: \(.version) →
|