name: Weekly Security Rebuild # Note: This workflow filename has remained consistent. The related docker-publish.yml # was replaced by docker-build.yml in commit f640524b (Dec 21, 2025). # GitHub Advanced Security may show warnings about the old filename until its tracking updates. on: schedule: - cron: '0 2 * * 0' # Sundays at 02:00 UTC workflow_dispatch: inputs: force_rebuild: description: 'Force rebuild without cache' required: false type: boolean default: true concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: false env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository_owner }}/charon jobs: security-rebuild: name: Security Rebuild & Scan runs-on: ubuntu-latest timeout-minutes: 60 permissions: contents: read packages: write security-events: write steps: - name: Checkout repository uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - name: Normalize image name run: | echo "IMAGE_NAME=$(echo "${{ env.IMAGE_NAME }}" | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV - name: Set up QEMU uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 - name: Set up Docker Buildx uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - name: Resolve Caddy base digest id: caddy run: | docker pull caddy:2-alpine DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' caddy:2-alpine) echo "image=$DIGEST" >> $GITHUB_OUTPUT - name: Log in to Container Registry uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Extract metadata id: meta uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | type=raw,value=security-scan-{{date 'YYYYMMDD'}} - name: Build Docker image (NO CACHE) id: build uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6 with: context: . platforms: linux/amd64 push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} no-cache: ${{ github.event_name == 'schedule' || inputs.force_rebuild }} pull: true # Always pull fresh base images to get latest security patches build-args: | VERSION=security-scan BUILD_DATE=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }} VCS_REF=${{ github.sha }} CADDY_IMAGE=${{ steps.caddy.outputs.image }} - name: Run Trivy vulnerability scanner (CRITICAL+HIGH) uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # 0.33.1 with: image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }} format: 'table' severity: 'CRITICAL,HIGH' exit-code: '1' # Fail workflow if vulnerabilities found continue-on-error: true - name: Run Trivy vulnerability scanner (SARIF) id: trivy-sarif uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # 0.33.1 with: image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }} format: 'sarif' output: 'trivy-weekly-results.sarif' severity: 'CRITICAL,HIGH,MEDIUM' - name: Upload Trivy results to GitHub Security uses: github/codeql-action/upload-sarif@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 with: sarif_file: 'trivy-weekly-results.sarif' - name: Run Trivy vulnerability scanner (JSON for artifact) uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # 0.33.1 with: image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }} format: 'json' output: 'trivy-weekly-results.json' severity: 'CRITICAL,HIGH,MEDIUM,LOW' - name: Upload Trivy JSON results uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 with: name: trivy-weekly-scan-${{ github.run_number }} path: trivy-weekly-results.json retention-days: 90 - name: Check Alpine package versions run: | echo "## 📦 Installed Package Versions" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "Checking key security packages:" >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY docker run --rm --entrypoint "" ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }} \ sh -c "apk update >/dev/null 2>&1 && apk info c-ares curl libcurl openssl" >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY - name: Create security scan summary if: always() run: | echo "## 🔒 Weekly Security Rebuild Complete" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "- **Build Date:** $(date -u +"%Y-%m-%d %H:%M:%S UTC")" >> $GITHUB_STEP_SUMMARY echo "- **Image:** ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}" >> $GITHUB_STEP_SUMMARY echo "- **Cache Used:** No (forced fresh build)" >> $GITHUB_STEP_SUMMARY echo "- **Trivy Scan:** Completed (see Security tab for details)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### Next Steps:" >> $GITHUB_STEP_SUMMARY echo "1. Review Security tab for new vulnerabilities" >> $GITHUB_STEP_SUMMARY echo "2. Check Trivy JSON artifact for detailed package info" >> $GITHUB_STEP_SUMMARY echo "3. If critical CVEs found, trigger production rebuild" >> $GITHUB_STEP_SUMMARY - name: Notify on security issues (optional) if: failure() run: | echo "::warning::Weekly security scan found HIGH or CRITICAL vulnerabilities. Review the Security tab."