Skip to content

Security Scanning

Security Scanning #221

Workflow file for this run

name: Security Scanning
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
schedule:
- cron: '0 2 * * *' # Daily at 2 AM UTC
workflow_dispatch:
permissions:
contents: read
security-events: write
actions: read
jobs:
codeql:
name: CodeQL Analysis
runs-on: ubuntu-latest
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: Autobuild
uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{ matrix.language }}"
dependency-review:
name: Dependency Review
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Dependency Review
uses: actions/dependency-review-action@v4
with:
fail-on-severity: moderate
allow-licenses: MIT, Apache-2.0, BSD-3-Clause, BSD-2-Clause, ISC
secrets-scan:
name: Secret Scanning
runs-on: ubuntu-latest
steps:
- name: Checkout repository
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: --debug --only-verified
container-scan:
name: Container Security
runs-on: ubuntu-latest
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
strategy:
matrix:
framework: [core, remix, next]
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Build Docker image
run: |
docker build -t katalyst-${{ matrix.framework }}:${{ github.sha }} \
-f docker/Dockerfile.${{ matrix.framework }} .
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: katalyst-${{ matrix.framework }}:${{ github.sha }}
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
- name: Upload Trivy scan results to GitHub Security
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: 'trivy-results.sarif'
sast:
name: Static Application Security Testing
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22.15.0'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run Semgrep
uses: returntocorp/semgrep-action@v1
with:
config: >-
p/security-audit
p/typescript
p/react
p/nodejs
p/owasp-top-ten
- name: Run NodeJsScan
run: |
pip install nodejsscan
nodejsscan -d . -o nodejsscan-report.json
- name: Upload SAST results
uses: actions/upload-artifact@v4
if: always()
with:
name: sast-results
path: |
nodejsscan-report.json
.semgrep/
osv-scan:
name: OSV Scanner
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run OSV Scanner
uses: google/osv-scanner-action@v1
with:
scan-args: |-
--json
--experimental-call-analysis
./
license-compliance:
name: License Compliance Check
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22.15.0'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Check licenses
run: |
npx license-checker --production --json > licenses.json
# Check for copyleft licenses
node -e "
const licenses = require('./licenses.json');
const problematic = ['GPL', 'AGPL', 'LGPL', 'MPL'];
const issues = [];
Object.entries(licenses).forEach(([pkg, info]) => {
if (problematic.some(lic => info.licenses?.includes(lic))) {
issues.push({ package: pkg, license: info.licenses });
}
});
if (issues.length > 0) {
console.error('Found problematic licenses:', issues);
process.exit(1);
}
"
security-scorecard:
name: OpenSSF Scorecard
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
permissions:
security-events: write
id-token: write
contents: read
actions: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Run Scorecard analysis
uses: ossf/scorecard-action@v2
with:
results_file: results.sarif
results_format: sarif
publish_results: true
- name: Upload Scorecard results to code scanning
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
infrastructure-scan:
name: Infrastructure Security
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: tfsec scan
uses: aquasecurity/tfsec-action@v1
with:
soft_fail: true
- name: Checkov scan
uses: bridgecrewio/checkov-action@master
with:
directory: .
framework: all
output_format: sarif
output_file_path: checkov-results.sarif
- name: Upload Checkov results
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: checkov-results.sarif
security-report:
name: Security Report
runs-on: ubuntu-latest
needs: [codeql, secrets-scan, sast, osv-scan]
if: always()
steps:
- name: Generate Security Summary
uses: actions/github-script@v7
with:
script: |
const summary = `## 🔒 Security Scan Summary
| Check | Status |
|-------|--------|
| CodeQL | ${{ needs.codeql.result }} |
| Secrets Scan | ${{ needs.secrets-scan.result }} |
| SAST | ${{ needs.sast.result }} |
| OSV Scan | ${{ needs.osv-scan.result }} |
View detailed results in the Security tab.
`;
if (context.eventName === 'pull_request') {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: summary
});
}