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.