name: Security Analysis on: push: branches: [main, stable] pull_request: branches: [main] schedule: # Run weekly security scan on Sundays at 2 AM - cron: '0 2 * * 0' permissions: actions: read contents: read security-events: read jobs: codeql: name: CodeQL Analysis runs-on: ubuntu-latest timeout-minutes: 360 strategy: fail-fast: false matrix: language: ['javascript', 'typescript'] steps: - name: Checkout repository uses: actions/checkout@v4 - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} queries: security-extended,security-and-quality - name: Setup and Build uses: ./.github/actions/setup-and-build - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 with: category: "/language:${{matrix.language}}" upload: false - name: Upload CodeQL results as artifact uses: actions/upload-artifact@v4 if: always() with: name: codeql-results-${{ matrix.language }} path: | **/results/**/*.sarif **/results/**/*.sarif.json dependency-scan: name: Dependency Vulnerability Scan runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20.18.0' - name: Install pnpm uses: pnpm/action-setup@v4 with: version: '9.14.4' - name: Install dependencies run: pnpm install --frozen-lockfile - name: Run npm audit run: pnpm audit --audit-level moderate continue-on-error: true - name: Generate SBOM uses: anchore/sbom-action@v0 with: path: ./ format: spdx-json artifact-name: sbom.spdx.json - name: Upload SBOM as artifact uses: actions/upload-artifact@v4 if: always() with: name: sbom-results path: sbom.spdx.json secrets-scan: name: Secrets Detection runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 0 - name: Run Trivy secrets scan uses: aquasecurity/trivy-action@master with: scan-type: 'fs' scan-ref: '.' format: 'sarif' output: 'trivy-secrets-results.sarif' scanners: 'secret' - name: Upload Trivy secrets results as artifact uses: actions/upload-artifact@v4 if: always() with: name: trivy-secrets-results path: trivy-secrets-results.sarif