Update snyk-security.yml #5
This file contains 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
name: "Deep Ruby Security Analysis with CodeQL" | |
on: | |
push: | |
branches: [ "main", "dev" ] | |
pull_request: | |
branches: [ "main", "dev" ] | |
schedule: | |
- cron: '0 0 */3 * *' # Run every 3 days | |
workflow_dispatch: # Allow manual triggering | |
jobs: | |
analyze: | |
name: Deep Ruby Security Analysis | |
runs-on: ubuntu-latest | |
permissions: | |
actions: read | |
contents: read | |
security-events: write | |
strategy: | |
fail-fast: false | |
matrix: | |
language: [ 'ruby' ] | |
ruby-version: [ '3.1', '2.7' ] # Focus on specific Ruby versions | |
steps: | |
- name: Checkout Repository | |
uses: actions/checkout@v3 | |
with: | |
fetch-depth: 0 | |
- name: Set up Ruby | |
uses: ruby/setup-ruby@v1 | |
with: | |
ruby-version: ${{ matrix.ruby-version }} | |
bundler-cache: true # Cache Gem installations to speed up subsequent runs | |
- name: Install Dependencies and Security Tools | |
run: | | |
gem install bundler | |
bundle install --jobs 4 --retry 3 | |
gem install brakeman bundler-audit ruby_audit fasterer reek flay flog rubocop rubocop-performance rubocop-rails rubocop-rspec | |
- name: Set up CodeQL for Ruby | |
uses: github/codeql-action/init@v3 | |
with: | |
languages: ruby | |
queries: security-extended,security-and-quality,security-experimental | |
packs: +codeql/ruby-queries:recommended, +codeql/ruby-queries:security-extended, +codeql/ruby-queries:audit, +codeql/ruby-queries:security-experimental | |
- name: Run Ruby Static Analysis Tools | |
run: | | |
rubocop --format progress --format json --out rubocop.json | |
brakeman -A --format json > brakeman.json | |
bundle audit check --update | |
ruby-audit check | |
fasterer | |
reek . > reek.txt | |
flay . | |
flog . | |
- name: Perform CodeQL Analysis | |
uses: github/codeql-action/analyze@v3 | |
with: | |
category: "/language:ruby" | |
- name: Run Additional Ruby Security Checks | |
run: | | |
# Check for hardcoded secrets | |
grep -R -E "(password|secret|key).*=.*['\"].*['\"]" . || true | |
# Check for SQL injection vulnerabilities | |
grep -R -E "\.where\(.*\$.*\)" . || true | |
# Check for potential XSS vulnerabilities | |
grep -R -E "\.html_safe" . || true | |
# Check for unsafe deserialization | |
grep -R -E "YAML.load|Marshal.load" . || true | |
- name: Upload Ruby Analysis Results | |
uses: actions/upload-artifact@v3 | |
with: | |
name: ruby-analysis-results-${{ matrix.ruby-version }} | |
path: | | |
rubocop.json | |
brakeman.json | |
reek.txt | |
- name: Upload CodeQL Results | |
uses: github/codeql-action/upload-sarif@v3 | |
with: | |
sarif_file: ${{ github.workspace }}/codeql-db/codeql-results/ruby.sarif | |
- name: Create Issues for Ruby Vulnerabilities | |
uses: actions/github-script@v6 | |
with: | |
github-token: ${{secrets.GITHUB_TOKEN}} | |
script: | | |
const fs = require('fs'); | |
// Process CodeQL results | |
const codeqlSarifPath = 'codeql-db/codeql-results/ruby.sarif'; | |
if (fs.existsSync(codeqlSarifPath)) { | |
const sarif = JSON.parse(fs.readFileSync(codeqlSarifPath, 'utf8')); | |
for (const run of sarif.runs) { | |
for (const result of run.results) { | |
await github.rest.issues.create({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
title: `[Ruby - ${result.level.toUpperCase()}] CodeQL issue in ${result.locations[0].physicalLocation.artifactLocation.uri}`, | |
body: `${result.message.text}\n\nRule: ${result.rule.id}\nSeverity: ${result.level}\n\nPlease investigate and address this issue.`, | |
labels: ['security', result.level, 'ruby'] | |
}); | |
} | |
} | |
} | |
// Process Rubocop results | |
const rubocopPath = 'rubocop.json'; | |
if (fs.existsSync(rubocopPath)) { | |
const rubocop = JSON.parse(fs.readFileSync(rubocopPath, 'utf8')); | |
for (const file of rubocop.files) { | |
for (const offense of file.offenses) { | |
await github.rest.issues.create({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
title: `[Ruby - ${offense.severity.toUpperCase()}] Rubocop issue in ${file.path}`, | |
body: `${offense.message}\n\nCop: ${offense.cop_name}\nSeverity: ${offense.severity}\n\nPlease investigate and address this issue.`, | |
labels: ['security', offense.severity, 'ruby', 'rubocop'] | |
}); | |
} | |
} | |
} | |
// Process Brakeman results | |
const brakemanPath = 'brakeman.json'; | |
if (fs.existsSync(brakemanPath)) { | |
const brakeman = JSON.parse(fs.readFileSync(brakemanPath, 'utf8')); | |
for (const warning of brakeman.warnings) { | |
await github.rest.issues.create({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
title: `[Ruby - ${warning.confidence.toUpperCase()}] Brakeman issue in ${warning.file}`, | |
body: `${warning.message}\n\nType: ${warning.warning_type}\nConfidence: ${warning.confidence}\n\nPlease investigate and address this issue.`, | |
labels: ['security', warning.confidence, 'ruby', 'brakeman'] | |
}); | |
} | |
} |