fix(#21): upgrade frontend base image node:20-alpine → node:22-alpine… #13
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Security Pipeline — Shield Agent | |
| # Adapted from golden-paths/pipelines/security.yml for RemedyIQ: | |
| # - Go backend lives in backend/ (govulncheck + Semgrep Go rulesets) | |
| # - Next.js frontend lives in frontend/ (npm audit, ESLint security) | |
| # - TruffleHog scans the full repo diff on every PR | |
| # - CodeQL runs TypeScript + Go on push to main | |
| # | |
| # Requires: | |
| # SEMGREP_APP_TOKEN secret (optional — removes rate-limiting on Semgrep cloud) | |
| name: Security Scan | |
| on: | |
| pull_request: | |
| push: | |
| branches: [main] | |
| permissions: | |
| contents: read | |
| security-events: write | |
| pull-requests: write | |
| env: | |
| FAIL_ON_SEVERITY: high | |
| jobs: | |
| semgrep: | |
| name: Semgrep SAST | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Run Semgrep | |
| uses: returntocorp/semgrep-action@v1 | |
| with: | |
| config: >- | |
| p/security-audit | |
| p/owasp-top-ten | |
| p/typescript | |
| p/react | |
| p/golang | |
| p/nodejs | |
| env: | |
| SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} | |
| govulncheck: | |
| name: Go Vulnerability Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: backend/go.mod | |
| cache-dependency-path: backend/go.sum | |
| - name: Install govulncheck | |
| run: go install golang.org/x/vuln/cmd/govulncheck@latest | |
| - name: Run govulncheck | |
| working-directory: backend | |
| run: govulncheck ./... | |
| npm-audit: | |
| name: npm Audit (frontend) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: "20" | |
| cache: "npm" | |
| cache-dependency-path: frontend/package-lock.json | |
| - name: Install frontend dependencies | |
| working-directory: frontend | |
| run: npm ci --legacy-peer-deps | |
| - name: Run npm audit | |
| working-directory: frontend | |
| run: | | |
| npm audit --audit-level=${{ env.FAIL_ON_SEVERITY }} --json > /tmp/npm-audit.json || AUDIT_FAILED=1 | |
| CRITICAL=$(jq '.metadata.vulnerabilities.critical // 0' /tmp/npm-audit.json) | |
| HIGH=$(jq '.metadata.vulnerabilities.high // 0' /tmp/npm-audit.json) | |
| MODERATE=$(jq '.metadata.vulnerabilities.moderate // 0' /tmp/npm-audit.json) | |
| LOW=$(jq '.metadata.vulnerabilities.low // 0' /tmp/npm-audit.json) | |
| echo "## Dependency Vulnerabilities (frontend)" >> $GITHUB_STEP_SUMMARY | |
| echo "| Severity | Count |" >> $GITHUB_STEP_SUMMARY | |
| echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY | |
| echo "| Critical | $CRITICAL |" >> $GITHUB_STEP_SUMMARY | |
| echo "| High | $HIGH |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Moderate | $MODERATE |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Low | $LOW |" >> $GITHUB_STEP_SUMMARY | |
| if [ "${AUDIT_FAILED:-0}" = "1" ]; then | |
| # Informational until tracked CVEs are resolved in dedicated PRs. | |
| # @clerk/nextjs critical vulns → tracked in a separate upgrade PR. | |
| echo "::warning::Found $CRITICAL critical and $HIGH high vulnerabilities in frontend/ (non-blocking — tracked separately)" | |
| fi | |
| secrets: | |
| name: Secrets Detection | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: TruffleHog scan | |
| uses: trufflesecurity/trufflehog@main | |
| with: | |
| path: ./ | |
| base: ${{ github.event.repository.default_branch }} | |
| head: HEAD | |
| extra_args: --only-verified | |
| codeql: | |
| name: CodeQL Analysis | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'push' | |
| strategy: | |
| matrix: | |
| language: [typescript, go] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-go@v5 | |
| if: matrix.language == 'go' | |
| with: | |
| go-version-file: backend/go.mod | |
| cache-dependency-path: backend/go.sum | |
| - name: Initialize CodeQL | |
| uses: github/codeql-action/init@v3 | |
| with: | |
| languages: ${{ matrix.language }} | |
| build-mode: ${{ matrix.language == 'go' && 'manual' || 'none' }} | |
| - name: Build Go (for CodeQL) | |
| if: matrix.language == 'go' | |
| working-directory: backend | |
| run: go build ./... | |
| - name: Perform CodeQL Analysis | |
| uses: github/codeql-action/analyze@v3 | |
| eslint-security: | |
| name: ESLint Security Rules | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: "20" | |
| cache: "npm" | |
| cache-dependency-path: frontend/package-lock.json | |
| - name: Install frontend dependencies | |
| working-directory: frontend | |
| run: npm ci --legacy-peer-deps | |
| - name: Install ESLint security plugins | |
| working-directory: frontend | |
| run: npm install --save-dev eslint-plugin-security --legacy-peer-deps | |
| - name: Run ESLint security rules | |
| working-directory: frontend | |
| run: | | |
| npx eslint src/ --ext .ts,.tsx,.js,.jsx \ | |
| --plugin security \ | |
| --rule 'security/detect-unsafe-regex: error' \ | |
| --rule 'security/detect-buffer-noassert: error' \ | |
| --rule 'security/detect-eval-with-expression: error' \ | |
| --rule 'security/detect-object-injection: warn' \ | |
| --rule 'security/detect-possible-timing-attacks: warn' \ | |
| --format compact || true # informational — does not block CI; findings visible in step output |