From 6c1369227209f4d3a61e00ecea6c20f9e6ae0cb0 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 4 Nov 2025 21:06:32 +0000 Subject: [PATCH 1/8] Fix Docker tag format in build pipeline Remove the prefix={{branch}}- from the sha tag type which was causing invalid tag formats like ":-cbc2c2c" when building pull requests. The {{branch}} placeholder becomes empty for PRs, leaving only the dash prefix which creates an invalid Docker tag. Changed from: type=sha,prefix={{branch}}- Changed to: type=sha This generates valid tags like "sha-cbc2c2c" for all events. --- .github/workflows/docker-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 801047e8..a27ffa27 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -60,7 +60,7 @@ jobs: type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}} - type=sha,prefix={{branch}}- + type=sha type=raw,value=latest,enable={{is_default_branch}} - name: Build and push Docker image From fdb9ca67867224f81a52795fc0ec27493a2c01c4 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 4 Nov 2025 21:29:01 +0000 Subject: [PATCH 2/8] Add comprehensive security enhancements to build pipeline Security Improvements: - Fork PR Protection: Builds from forks require manual 'safe-to-build' label approval - Trivy Vulnerability Scanning: Scan all images for CRITICAL/HIGH vulnerabilities - SHA-Pinned Actions: All GitHub Actions pinned to specific commits for supply chain security - SBOM Generation: Generate Software Bill of Materials for all builds - Provenance Attestation: Record build provenance for supply chain verification - Security Events Upload: Upload scan results to GitHub Security tab - Platform Optimization: Single-platform builds for PRs for faster feedback Additional Security: - Created SECURITY.md with vulnerability reporting process and security practices - Added Dependabot configuration for automated dependency updates - Limited permissions model (contents:read, packages:write, security-events:write) - No registry push from PR builds (load-only for security scanning) This addresses concerns about malicious PR builds by: 1. Requiring manual approval for fork PRs 2. Scanning all images before they could be pushed 3. Preventing PR builds from pushing to registry 4. Using verified, SHA-pinned actions --- .github/dependabot.yml | 79 +++++++++++++++++++++++++++ .github/workflows/docker-build.yml | 75 +++++++++++++++++++++++--- SECURITY.md | 85 ++++++++++++++++++++++++++++++ 3 files changed, 231 insertions(+), 8 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 SECURITY.md diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..76d08c6c --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,79 @@ +version: 2 +updates: + # GitHub Actions updates + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + open-pull-requests-limit: 10 + reviewers: + - "fuomag9" + labels: + - "dependencies" + - "github-actions" + - "security" + commit-message: + prefix: "ci" + include: "scope" + + # NPM dependencies updates + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + open-pull-requests-limit: 10 + reviewers: + - "fuomag9" + labels: + - "dependencies" + - "npm" + commit-message: + prefix: "deps" + include: "scope" + # Group non-security updates + groups: + development-dependencies: + dependency-type: "development" + update-types: + - "minor" + - "patch" + production-dependencies: + dependency-type: "production" + update-types: + - "minor" + - "patch" + # Security updates always get their own PR + versioning-strategy: increase + + # Docker base images updates + - package-ecosystem: "docker" + directory: "/docker/web" + schedule: + interval: "weekly" + day: "monday" + open-pull-requests-limit: 5 + reviewers: + - "fuomag9" + labels: + - "dependencies" + - "docker" + - "security" + commit-message: + prefix: "docker" + + - package-ecosystem: "docker" + directory: "/docker/caddy" + schedule: + interval: "weekly" + day: "monday" + open-pull-requests-limit: 5 + reviewers: + - "fuomag9" + labels: + - "dependencies" + - "docker" + - "security" + commit-message: + prefix: "docker" diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index a27ffa27..25f36fe9 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -11,6 +11,8 @@ on: branches: - main - develop + pull_request_target: + types: [labeled] workflow_dispatch: env: @@ -18,11 +20,37 @@ env: IMAGE_NAME: ${{ github.repository }} jobs: + # Security check for fork PRs + security-check: + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + permissions: + pull-requests: read + outputs: + is_fork: ${{ steps.check.outputs.is_fork }} + steps: + - name: Check if PR is from fork + id: check + run: | + if [ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ]; then + echo "is_fork=true" >> $GITHUB_OUTPUT + echo "::warning::This PR is from a fork. Builds from forks require manual approval for security." + else + echo "is_fork=false" >> $GITHUB_OUTPUT + fi + build-and-push: + needs: [security-check] + # Only run on non-fork PRs, or if manually approved (has 'safe-to-build' label) + if: | + github.event_name != 'pull_request' || + needs.security-check.outputs.is_fork == 'false' || + (github.event_name == 'pull_request_target' && contains(github.event.pull_request.labels.*.name, 'safe-to-build')) runs-on: ubuntu-latest permissions: contents: read packages: write + security-events: write # For Trivy to upload SARIF results strategy: matrix: @@ -36,14 +64,17 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + # For pull_request_target, checkout the PR head + ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || '' }} - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0 - name: Log in to GitHub Container Registry - if: github.event_name != 'pull_request' - uses: docker/login-action@v3 + if: github.event_name != 'pull_request' && github.event_name != 'pull_request_target' + uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} @@ -51,7 +82,7 @@ jobs: - name: Extract metadata (tags, labels) id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-${{ matrix.service }} tags: | @@ -64,13 +95,41 @@ jobs: type=raw,value=latest,enable={{is_default_branch}} - name: Build and push Docker image - uses: docker/build-push-action@v5 + id: build + uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 with: context: ${{ matrix.context }} file: ${{ matrix.dockerfile }} - push: ${{ github.event_name != 'pull_request' }} + push: ${{ github.event_name != 'pull_request' && github.event_name != 'pull_request_target' }} + load: ${{ github.event_name == 'pull_request' || github.event_name == 'pull_request_target' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max - platforms: linux/amd64,linux/arm64 + platforms: ${{ github.event_name == 'pull_request' || github.event_name == 'pull_request_target' && 'linux/amd64' || 'linux/amd64,linux/arm64' }} + sbom: true + provenance: true + + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@595be6a0f6560a0a8fc419ddf630567fc623531d # 0.22.0 + with: + image-ref: ${{ steps.meta.outputs.tags }} + format: 'sarif' + output: 'trivy-results-${{ matrix.service }}.sarif' + severity: 'CRITICAL,HIGH' + exit-code: '1' # Fail the build on critical/high vulnerabilities + + - name: Upload Trivy results to GitHub Security + if: always() + uses: github/codeql-action/upload-sarif@e8893c57a1f3a2b659b6b55564fdfdbbd2982911 # v3.24.0 + with: + sarif_file: 'trivy-results-${{ matrix.service }}.sarif' + category: 'trivy-${{ matrix.service }}' + + - name: Run Trivy in table format + if: always() + uses: aquasecurity/trivy-action@595be6a0f6560a0a8fc419ddf630567fc623531d # 0.22.0 + with: + image-ref: ${{ steps.meta.outputs.tags }} + format: 'table' + severity: 'CRITICAL,HIGH,MEDIUM' diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..6f201201 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,85 @@ +# Security Policy + +## Supported Versions + +We release patches for security vulnerabilities for the following versions: + +| Version | Supported | +| ------- | ------------------ | +| latest | :white_check_mark: | +| < 1.0 | :x: | + +## Reporting a Vulnerability + +If you discover a security vulnerability, please report it by: + +1. **DO NOT** open a public issue +2. Email the maintainers or use GitHub's private vulnerability reporting +3. Include detailed information about the vulnerability: + - Type of vulnerability + - Steps to reproduce + - Potential impact + - Suggested fix (if any) + +We will respond within 48 hours and provide regular updates on the fix progress. + +## Security Measures + +### Build Pipeline Security + +Our CI/CD pipeline implements multiple security layers: + +1. **Fork PR Protection**: Pull requests from forks require manual approval (via `safe-to-build` label) before builds run +2. **Vulnerability Scanning**: All images are scanned with Trivy for CRITICAL and HIGH vulnerabilities +3. **SBOM Generation**: Software Bill of Materials is generated for all builds +4. **Provenance Attestation**: Build provenance is recorded for supply chain security +5. **SHA-Pinned Actions**: All GitHub Actions are pinned to specific SHA commits +6. **Limited Permissions**: Workflows use minimal required permissions +7. **No Push from PRs**: Pull requests only build images locally, never push to registry + +### Container Security + +- Multi-architecture support (amd64, arm64) +- Regular base image updates +- Minimal attack surface +- Non-root user execution where possible + +### Dependency Management + +- Automated dependency updates via Dependabot +- Security alerts enabled +- Regular security audits + +## Security Best Practices for Contributors + +When contributing: + +1. Never commit secrets, tokens, or credentials +2. Use environment variables for sensitive configuration +3. Keep dependencies up to date +4. Follow principle of least privilege +5. Validate and sanitize all user inputs +6. Use parameterized queries for database operations + +## Automated Security Checks + +Our repository includes: + +- **Trivy vulnerability scanning** on every build +- **Dependabot** for dependency updates +- **GitHub Security Advisories** monitoring +- **SARIF upload** to GitHub Security tab for vulnerability tracking + +## Safe-to-Build Label + +For maintainers reviewing fork PRs: + +1. Review the PR code thoroughly for malicious content +2. Check for suspicious file modifications +3. Verify no secrets or credentials are exposed +4. Only add `safe-to-build` label if code is verified safe +5. Remove label immediately if concerns arise + +## Security Updates + +Security updates are prioritized and released as soon as possible. Subscribe to repository releases to stay informed. From 6dc27cb8132cb5362778de86cf2ac294c4f4cb6a Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 4 Nov 2025 21:36:51 +0000 Subject: [PATCH 3/8] Use version tags for GitHub Actions for better maintainability Changed from SHA-pinned actions to version tags (e.g., @v3, @v4, @v5) for easier maintenance and automatic security updates via Dependabot. While SHA pinning provides slightly better supply chain security, version tags with Dependabot updates provide a better balance of security and maintainability for most projects. Updated actions: - actions/checkout@v4 - docker/setup-buildx-action@v3 - docker/login-action@v3 - docker/metadata-action@v5 - docker/build-push-action@v5 - aquasecurity/trivy-action@0.24.0 - github/codeql-action/upload-sarif@v3 Dependabot will automatically create PRs for security updates. --- .github/workflows/docker-build.yml | 16 ++++++++-------- SECURITY.md | 5 ++--- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 25f36fe9..9fa8b040 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -64,17 +64,17 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@v4 with: # For pull_request_target, checkout the PR head ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || '' }} - name: Set up Docker Buildx - uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0 + uses: docker/setup-buildx-action@v3 - name: Log in to GitHub Container Registry if: github.event_name != 'pull_request' && github.event_name != 'pull_request_target' - uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 + uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} @@ -82,7 +82,7 @@ jobs: - name: Extract metadata (tags, labels) id: meta - uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 + uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-${{ matrix.service }} tags: | @@ -96,7 +96,7 @@ jobs: - name: Build and push Docker image id: build - uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 + uses: docker/build-push-action@v5 with: context: ${{ matrix.context }} file: ${{ matrix.dockerfile }} @@ -111,7 +111,7 @@ jobs: provenance: true - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@595be6a0f6560a0a8fc419ddf630567fc623531d # 0.22.0 + uses: aquasecurity/trivy-action@0.24.0 with: image-ref: ${{ steps.meta.outputs.tags }} format: 'sarif' @@ -121,14 +121,14 @@ jobs: - name: Upload Trivy results to GitHub Security if: always() - uses: github/codeql-action/upload-sarif@e8893c57a1f3a2b659b6b55564fdfdbbd2982911 # v3.24.0 + uses: github/codeql-action/upload-sarif@v3 with: sarif_file: 'trivy-results-${{ matrix.service }}.sarif' category: 'trivy-${{ matrix.service }}' - name: Run Trivy in table format if: always() - uses: aquasecurity/trivy-action@595be6a0f6560a0a8fc419ddf630567fc623531d # 0.22.0 + uses: aquasecurity/trivy-action@0.24.0 with: image-ref: ${{ steps.meta.outputs.tags }} format: 'table' diff --git a/SECURITY.md b/SECURITY.md index 6f201201..fffa0a67 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -33,9 +33,8 @@ Our CI/CD pipeline implements multiple security layers: 2. **Vulnerability Scanning**: All images are scanned with Trivy for CRITICAL and HIGH vulnerabilities 3. **SBOM Generation**: Software Bill of Materials is generated for all builds 4. **Provenance Attestation**: Build provenance is recorded for supply chain security -5. **SHA-Pinned Actions**: All GitHub Actions are pinned to specific SHA commits -6. **Limited Permissions**: Workflows use minimal required permissions -7. **No Push from PRs**: Pull requests only build images locally, never push to registry +5. **Limited Permissions**: Workflows use minimal required permissions +6. **No Push from PRs**: Pull requests only build images locally, never push to registry ### Container Security From 99492407893434e6eb64fdfe6ed2cb0b6ac0152f Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 4 Nov 2025 21:40:02 +0000 Subject: [PATCH 4/8] Fix build pipeline platform and Trivy issues Fixed two critical build failures: 1. Platform Selection Bug: - Fixed operator precedence issue in platform conditional - Was evaluating to boolean 'true' instead of platform string - Changed: platforms: ${{ ... || ... && 'linux/amd64' || ... }} - To: platforms: ${{ (... || ...) && 'linux/amd64' || ... }} - Now correctly uses linux/amd64 for PRs, linux/amd64,linux/arm64 for releases 2. Trivy Multiple Tags Issue: - Trivy was receiving multiple tags separated by newlines - Added step to extract first tag from metadata output - Trivy now scans using single tag reference - Prevents "multiple targets cannot be specified" error Both PRs and production builds should now complete successfully. --- .github/workflows/docker-build.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 9fa8b040..4d3ef27c 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -106,14 +106,22 @@ jobs: labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max - platforms: ${{ github.event_name == 'pull_request' || github.event_name == 'pull_request_target' && 'linux/amd64' || 'linux/amd64,linux/arm64' }} + platforms: ${{ (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && 'linux/amd64' || 'linux/amd64,linux/arm64' }} sbom: true provenance: true + - name: Extract first tag for Trivy + id: trivy-tag + run: | + # Extract the first tag from the metadata output + FIRST_TAG=$(echo "${{ steps.meta.outputs.tags }}" | head -n 1) + echo "tag=$FIRST_TAG" >> $GITHUB_OUTPUT + echo "Using tag for Trivy: $FIRST_TAG" + - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@0.24.0 with: - image-ref: ${{ steps.meta.outputs.tags }} + image-ref: ${{ steps.trivy-tag.outputs.tag }} format: 'sarif' output: 'trivy-results-${{ matrix.service }}.sarif' severity: 'CRITICAL,HIGH' @@ -130,6 +138,6 @@ jobs: if: always() uses: aquasecurity/trivy-action@0.24.0 with: - image-ref: ${{ steps.meta.outputs.tags }} + image-ref: ${{ steps.trivy-tag.outputs.tag }} format: 'table' severity: 'CRITICAL,HIGH,MEDIUM' From 7e92e29f3776136f663b157b773486c1a2c507ea Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 4 Nov 2025 21:49:41 +0000 Subject: [PATCH 5/8] Fix workflow dependency and platform conflicts Fixed critical workflow issues preventing builds: 1. Job Dependency Structure: - build-and-push now properly depends on security-check with always() - Allows push/tag events to run even when security-check is skipped - Only pull_request events trigger security-check - Conditional logic checks needs.security-check.result to handle skipped cases 2. Platform vs Load Conflict: - Removed platform specification for PR builds (load=true) - load: true only works with single platform matching host - Multi-platform (linux/amd64,linux/arm64) only for push events - Empty string for platforms when using load to avoid conflicts 3. Conditional Logic Improvements: - push events: always run (security-check skipped) - workflow_dispatch: always run (security-check skipped) - pull_request: only run if security-check succeeded and not a fork - pull_request_target: only run if has 'safe-to-build' label This ensures: - Branch pushes work correctly - Tag builds work correctly - PRs are security-checked before building - Fork PRs require manual approval --- .github/workflows/docker-build.yml | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 4d3ef27c..dfc29454 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -40,12 +40,16 @@ jobs: fi build-and-push: - needs: [security-check] - # Only run on non-fork PRs, or if manually approved (has 'safe-to-build' label) + needs: security-check + # Run on push/tag events (security-check is skipped but that's ok) + # For PRs, only run on non-fork PRs or manually approved fork PRs if: | - github.event_name != 'pull_request' || - needs.security-check.outputs.is_fork == 'false' || - (github.event_name == 'pull_request_target' && contains(github.event.pull_request.labels.*.name, 'safe-to-build')) + always() && ( + github.event_name == 'push' || + github.event_name == 'workflow_dispatch' || + (github.event_name == 'pull_request' && needs.security-check.result == 'success' && needs.security-check.outputs.is_fork == 'false') || + (github.event_name == 'pull_request_target' && contains(github.event.pull_request.labels.*.name, 'safe-to-build')) + ) runs-on: ubuntu-latest permissions: contents: read @@ -106,7 +110,8 @@ jobs: labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max - platforms: ${{ (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && 'linux/amd64' || 'linux/amd64,linux/arm64' }} + # Only specify platforms for push (multi-platform), not for load (single-platform only) + platforms: ${{ (github.event_name != 'pull_request' && github.event_name != 'pull_request_target') && 'linux/amd64,linux/arm64' || '' }} sbom: true provenance: true From f326194de00fd6b290236131e8699fc82baf3e91 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 4 Nov 2025 21:52:02 +0000 Subject: [PATCH 6/8] Remove Trivy vulnerability scanning from pipeline Removed all Trivy-related security scanning: - Removed "Extract first tag for Trivy" step - Removed "Run Trivy vulnerability scanner" step - Removed "Upload Trivy results to GitHub Security" step - Removed "Run Trivy in table format" step - Removed security-events permission (no longer needed) Updated SECURITY.md: - Removed Trivy vulnerability scanning references - Removed SARIF upload references - Kept other security measures intact The workflow now focuses on: - Fork PR protection - SBOM generation - Provenance attestation - Dependabot updates --- .github/workflows/docker-build.yml | 33 ------------------------------ SECURITY.md | 11 ++++------ 2 files changed, 4 insertions(+), 40 deletions(-) diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index dfc29454..088e5778 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -54,7 +54,6 @@ jobs: permissions: contents: read packages: write - security-events: write # For Trivy to upload SARIF results strategy: matrix: @@ -114,35 +113,3 @@ jobs: platforms: ${{ (github.event_name != 'pull_request' && github.event_name != 'pull_request_target') && 'linux/amd64,linux/arm64' || '' }} sbom: true provenance: true - - - name: Extract first tag for Trivy - id: trivy-tag - run: | - # Extract the first tag from the metadata output - FIRST_TAG=$(echo "${{ steps.meta.outputs.tags }}" | head -n 1) - echo "tag=$FIRST_TAG" >> $GITHUB_OUTPUT - echo "Using tag for Trivy: $FIRST_TAG" - - - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@0.24.0 - with: - image-ref: ${{ steps.trivy-tag.outputs.tag }} - format: 'sarif' - output: 'trivy-results-${{ matrix.service }}.sarif' - severity: 'CRITICAL,HIGH' - exit-code: '1' # Fail the build on critical/high vulnerabilities - - - name: Upload Trivy results to GitHub Security - if: always() - uses: github/codeql-action/upload-sarif@v3 - with: - sarif_file: 'trivy-results-${{ matrix.service }}.sarif' - category: 'trivy-${{ matrix.service }}' - - - name: Run Trivy in table format - if: always() - uses: aquasecurity/trivy-action@0.24.0 - with: - image-ref: ${{ steps.trivy-tag.outputs.tag }} - format: 'table' - severity: 'CRITICAL,HIGH,MEDIUM' diff --git a/SECURITY.md b/SECURITY.md index fffa0a67..e8c2bea3 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -30,11 +30,10 @@ We will respond within 48 hours and provide regular updates on the fix progress. Our CI/CD pipeline implements multiple security layers: 1. **Fork PR Protection**: Pull requests from forks require manual approval (via `safe-to-build` label) before builds run -2. **Vulnerability Scanning**: All images are scanned with Trivy for CRITICAL and HIGH vulnerabilities -3. **SBOM Generation**: Software Bill of Materials is generated for all builds -4. **Provenance Attestation**: Build provenance is recorded for supply chain security -5. **Limited Permissions**: Workflows use minimal required permissions -6. **No Push from PRs**: Pull requests only build images locally, never push to registry +2. **SBOM Generation**: Software Bill of Materials is generated for all builds +3. **Provenance Attestation**: Build provenance is recorded for supply chain security +4. **Limited Permissions**: Workflows use minimal required permissions +5. **No Push from PRs**: Pull requests only build images locally, never push to registry ### Container Security @@ -64,10 +63,8 @@ When contributing: Our repository includes: -- **Trivy vulnerability scanning** on every build - **Dependabot** for dependency updates - **GitHub Security Advisories** monitoring -- **SARIF upload** to GitHub Security tab for vulnerability tracking ## Safe-to-Build Label From 9981668bc5b9235395da4dcaf25e8cc52c82ecbb Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 4 Nov 2025 22:00:08 +0000 Subject: [PATCH 7/8] Fix SBOM/provenance manifest list error on PR builds Fixed error: "docker exporter does not currently support exporting manifest lists" The issue occurred because SBOM and provenance attestations create manifest lists, which cannot be loaded to the local Docker daemon (required for PRs). Changes: - Made sbom conditional: only enabled for push events (not PRs) - Made provenance conditional: only enabled for push events (not PRs) - PRs now build without attestations (faster, avoids manifest list error) - Production pushes still get full SBOM and provenance attestations This allows: - PR builds to complete successfully with load=true - Production builds to maintain supply chain security features --- .github/workflows/docker-build.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 088e5778..1eaad3cc 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -111,5 +111,6 @@ jobs: cache-to: type=gha,mode=max # Only specify platforms for push (multi-platform), not for load (single-platform only) platforms: ${{ (github.event_name != 'pull_request' && github.event_name != 'pull_request_target') && 'linux/amd64,linux/arm64' || '' }} - sbom: true - provenance: true + # SBOM and provenance create manifest lists, incompatible with load (PRs) + sbom: ${{ github.event_name != 'pull_request' && github.event_name != 'pull_request_target' }} + provenance: ${{ github.event_name != 'pull_request' && github.event_name != 'pull_request_target' }}