Files
michaelschiemer/.gitea/workflows/security-scan.yml
Michael Schiemer a12188a7c1 fix: rename GITEA_TOKEN to CI_TOKEN in workflows
- Change secret name from GITEA_TOKEN to CI_TOKEN
- Gitea doesn't allow secrets starting with GITEA_
- Update all checkout steps to use CI_TOKEN instead
2025-10-31 03:50:04 +01:00

198 lines
7.6 KiB
YAML

name: Security Vulnerability Scan
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
schedule:
# Daily security scan at 2 AM UTC
- cron: '0 2 * * *'
workflow_dispatch:
jobs:
security-audit:
name: Composer Security Audit
runs-on: ubuntu-latest
steps:
- name: Checkout code
run: |
REF_NAME="${{ github.ref_name }}"
REPO="${{ github.repository }}"
if [ -z "$REF_NAME" ]; then
REF_NAME="main"
fi
# Use CI token if available, otherwise try public access
if [ -n "${{ secrets.CI_TOKEN }}" ]; then
git clone --depth 1 --branch "$REF_NAME" \
"https://${{ secrets.CI_TOKEN }}@git.michaelschiemer.de/${REPO}.git" \
/workspace/repo
else
# Try public HTTPS (works if repository is public)
git clone --depth 1 --branch "$REF_NAME" \
"https://git.michaelschiemer.de/${REPO}.git" \
/workspace/repo || \
# Fallback: Try to use Gitea's internal runner access
git clone --depth 1 \
"https://git.michaelschiemer.de/${REPO}.git" \
/workspace/repo
fi
cd /workspace/repo
- name: Setup PHP
run: |
apt-get update
apt-get install -y \
php8.4 \
php8.4-cli \
php8.4-dom \
php8.4-curl \
php8.4-xml \
php8.4-mbstring \
php8.4-zip \
php8.4-pcntl \
php8.4-pdo \
php8.4-pdo-sqlite \
php8.4-bcmath \
php8.4-soap \
php8.4-intl \
php8.4-gd \
php8.4-exif \
php8.4-iconv \
php8.4-sodium \
composer
- name: Validate composer.json and composer.lock
run: |
cd /workspace/repo
# Validate composer.json (less strict - lock file might be updated during install)
composer validate --no-check-lock || echo "⚠️ composer.lock might need update, but continuing..."
# Try to update lock file if needed
composer update --lock --no-interaction || echo "⚠️ Could not update lock file, but continuing..."
- name: Cache Composer packages (simple)
run: |
if [ -d "/tmp/composer-cache/vendor" ]; then
echo "📦 Restoring cached dependencies..."
cp -r /tmp/composer-cache/vendor /workspace/repo/vendor || true
fi
- name: Install dependencies
run: |
cd /workspace/repo
composer install --prefer-dist --no-progress --no-dev
- name: Save Composer cache
run: |
mkdir -p /tmp/composer-cache
cp -r /workspace/repo/vendor /tmp/composer-cache/vendor || true
- name: Run Composer Security Audit
id: security-audit
run: |
cd /workspace/repo
composer audit --format=json > audit-result.json || true
cat audit-result.json
- name: Parse audit results
id: parse-audit
run: |
cd /workspace/repo
if [ -f audit-result.json ]; then
# Check if jq is available, install if not
if ! command -v jq &> /dev/null; then
apt-get update && apt-get install -y jq
fi
ADVISORIES=$(jq -r '.advisories | length' audit-result.json 2>/dev/null || echo "0")
ABANDONED=$(jq -r '.abandoned | length' audit-result.json 2>/dev/null || echo "0")
echo "advisories_count=$ADVISORIES" >> $GITHUB_OUTPUT
echo "abandoned_count=$ABANDONED" >> $GITHUB_OUTPUT
echo "## Security Audit Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **Vulnerabilities Found:** $ADVISORIES" >> $GITHUB_STEP_SUMMARY
echo "- **Abandoned Packages:** $ABANDONED" >> $GITHUB_STEP_SUMMARY
if [ "$ADVISORIES" -gt 0 ]; then
echo "has_vulnerabilities=true" >> $GITHUB_OUTPUT
echo "- **Status:** ❌ Security vulnerabilities detected - review required" >> $GITHUB_STEP_SUMMARY
# Display vulnerability details
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Vulnerability Details" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo '```json' >> $GITHUB_STEP_SUMMARY
jq '.advisories' audit-result.json >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
exit 1
else
echo "has_vulnerabilities=false" >> $GITHUB_OUTPUT
echo "- **Status:** ✅ No security vulnerabilities detected" >> $GITHUB_STEP_SUMMARY
fi
if [ "$ABANDONED" -gt 0 ]; then
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Abandoned Packages" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
jq -r '.abandoned | to_entries[] | "- **\(.key)**: \(.value // "No replacement suggested")"' audit-result.json >> $GITHUB_STEP_SUMMARY
fi
fi
- name: Save audit results
if: always()
run: |
cd /workspace/repo
if [ -f audit-result.json ]; then
mkdir -p /tmp/artifacts
cp audit-result.json /tmp/artifacts/security-audit-results-${{ github.run_number }}.json || true
echo "✅ Audit results saved"
fi
- name: Create Gitea issue on vulnerability (scheduled runs only)
if: failure() && github.event_name == 'schedule'
run: |
# Prepare issue body
ISSUE_TITLE="🚨 Security Vulnerabilities Detected in Dependencies"
ISSUE_BODY="## Security Audit Report\n\n"
ISSUE_BODY="${ISSUE_BODY}**Date:** $(date -u +"%Y-%m-%d %H:%M:%S UTC")\n"
ISSUE_BODY="${ISSUE_BODY}**Workflow Run:** ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\n\n"
if [ -f audit-result.json ]; then
# Add vulnerability details
ISSUE_BODY="${ISSUE_BODY}### Vulnerabilities Found\n\n"
ISSUE_BODY="${ISSUE_BODY}\`\`\`json\n"
ISSUE_BODY="${ISSUE_BODY}$(cat audit-result.json)\n"
ISSUE_BODY="${ISSUE_BODY}\`\`\`\n\n"
fi
ISSUE_BODY="${ISSUE_BODY}### Action Required\n\n"
ISSUE_BODY="${ISSUE_BODY}1. Review the vulnerability details above\n"
ISSUE_BODY="${ISSUE_BODY}2. Update affected packages: \`composer update <package>\`\n"
ISSUE_BODY="${ISSUE_BODY}3. Run tests: \`make test\`\n"
ISSUE_BODY="${ISSUE_BODY}4. Verify with: \`make security-check\`\n"
# Create issue using Gitea API
# Note: Requires GITEA_TOKEN secret to be configured
if [ -n "${{ secrets.GITEA_TOKEN }}" ]; then
curl -X POST \
-H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \
-H "Content-Type: application/json" \
-d "{\"title\":\"${ISSUE_TITLE}\",\"body\":\"${ISSUE_BODY}\",\"labels\":[\"security\",\"dependencies\",\"automated\"]}" \
"${{ github.server_url }}/api/v1/repos/${{ github.repository }}/issues"
else
echo "⚠️ GITEA_TOKEN not configured - skipping issue creation"
echo "Please add GITEA_TOKEN as repository secret for automated issue creation"
fi
- name: Notify on failure
if: failure()
run: |
echo "::error::Security vulnerabilities detected! Check the audit results for details."
echo "Run 'make security-check' locally to review vulnerabilities."