chore(deps): bump activesupport from 7.2.2.2 to 7.2.3.1 #415
Workflow file for this run
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
| name: Security Scan | |
| on: | |
| push: | |
| branches: [ master, develop ] | |
| pull_request: | |
| branches: [ master, develop ] | |
| # TODO: Reativar quando em produção | |
| # schedule: | |
| # # Run weekly on Monday at 9am UTC | |
| # - cron: '0 9 * * 1' | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| issues: write | |
| jobs: | |
| brakeman: | |
| name: Brakeman Security Scan | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Set up Ruby | |
| uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1 | |
| with: | |
| ruby-version: 3.4.5 | |
| bundler-cache: true | |
| - name: Install Brakeman | |
| run: gem install brakeman | |
| - name: Run Brakeman | |
| run: | | |
| brakeman --rails7 \ | |
| --format json \ | |
| --output brakeman-report.json \ | |
| --no-exit-on-warn \ | |
| --no-exit-on-error | |
| - name: Parse Results | |
| id: parse | |
| run: | | |
| WARNINGS=$(jq '.warnings | length' brakeman-report.json) | |
| HIGH=$(jq '[.warnings[] | select(.confidence == "High")] | length' brakeman-report.json) | |
| echo "warnings=$WARNINGS" >> $GITHUB_OUTPUT | |
| echo "high=$HIGH" >> $GITHUB_OUTPUT | |
| - name: Upload Report | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: brakeman-report | |
| path: brakeman-report.json | |
| - name: Comment PR | |
| if: github.event_name == 'pull_request' | |
| uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6 | |
| with: | |
| script: | | |
| const warnings = '${{ steps.parse.outputs.warnings }}'; | |
| const high = '${{ steps.parse.outputs.high }}'; | |
| const body = `## 🔒 Brakeman Security Scan | |
| - Total warnings: ${warnings} | |
| - High confidence: ${high} | |
| ${high > 0 ? '⚠️ High confidence issues found! Please review.' : '✅ No high confidence issues found.'} | |
| `; | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: body | |
| }); | |
| - name: Fail on High Confidence Issues | |
| if: steps.parse.outputs.high > 0 | |
| run: | | |
| echo "::error::Found ${{ steps.parse.outputs.high }} high confidence security issues!" | |
| exit 1 | |
| dependency-check: | |
| name: Dependency Vulnerability Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Set up Ruby | |
| uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1 | |
| with: | |
| ruby-version: 3.4.5 | |
| bundler-cache: true | |
| - name: Install Bundle Audit | |
| run: gem install bundler-audit | |
| - name: Update Vulnerability Database | |
| run: bundle-audit update | |
| - name: Run Bundle Audit | |
| id: audit | |
| run: | | |
| bundle-audit check --output bundle-audit.txt || echo "vulnerabilities=true" >> $GITHUB_OUTPUT | |
| cat bundle-audit.txt | |
| - name: Upload Report | |
| if: always() | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: bundle-audit-report | |
| path: bundle-audit.txt | |
| - name: Comment PR | |
| if: github.event_name == 'pull_request' && always() | |
| uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const report = fs.readFileSync('bundle-audit.txt', 'utf8'); | |
| const hasVulns = report.includes('Vulnerabilities found'); | |
| const body = `## 📦 Dependency Security Check | |
| ${hasVulns ? '⚠️ Vulnerabilities found in dependencies!' : '✅ No known vulnerabilities found.'} | |
| <details> | |
| <summary>View Report</summary> | |
| \`\`\` | |
| ${report} | |
| \`\`\` | |
| </details> | |
| `; | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: body | |
| }); | |
| - name: Fail on Vulnerabilities | |
| if: steps.audit.outputs.vulnerabilities == 'true' | |
| run: | | |
| echo "::error::Vulnerable dependencies found!" | |
| exit 1 | |
| semgrep: | |
| name: Semgrep Static Analysis | |
| runs-on: ubuntu-latest | |
| container: | |
| image: returntocorp/semgrep | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Run Semgrep | |
| run: | | |
| semgrep scan \ | |
| --config=auto \ | |
| --json \ | |
| --output=semgrep-report.json \ | |
| --exclude 'scripts/' \ | |
| --exclude 'load_tests/' \ | |
| --exclude 'security_tests/' \ | |
| --exclude 'vendor/' \ | |
| --verbose \ | |
| || true | |
| echo "::group::Semgrep Report Preview" | |
| cat semgrep-report.json | head -c 5000 | |
| echo "" | |
| echo "::endgroup::" | |
| - name: Parse Results | |
| id: parse | |
| run: | | |
| # Count total results | |
| TOTAL=$(jq '.results | length' semgrep-report.json) | |
| # Count actual ERROR severity issues (not warnings) | |
| ERRORS=$(jq '.results | map(select(.extra.severity == "ERROR")) | length' semgrep-report.json) | |
| WARNINGS=$(jq '.results | map(select(.extra.severity == "WARNING")) | length' semgrep-report.json) | |
| # Count HIGH confidence security issues (excluding audit rules) | |
| CRITICAL=$(jq '.results | map(select(.extra.metadata.confidence == "HIGH" and (.extra.metadata.subcategory // "vuln") != "audit")) | length' semgrep-report.json) | |
| echo "errors=$ERRORS" >> $GITHUB_OUTPUT | |
| echo "warnings=$WARNINGS" >> $GITHUB_OUTPUT | |
| echo "critical=$CRITICAL" >> $GITHUB_OUTPUT | |
| echo "::notice::Semgrep Analysis Complete" | |
| echo "::notice:: - Total findings: $TOTAL" | |
| echo "::notice:: - ERROR severity: $ERRORS" | |
| echo "::notice:: - WARNING severity: $WARNINGS" | |
| echo "::notice:: - HIGH confidence (non-audit): $CRITICAL" | |
| # Show details of ERROR severity issues if any | |
| if [ "$ERRORS" -gt 0 ]; then | |
| echo "::group::ERROR Severity Issues" | |
| jq -r '.results[] | select(.extra.severity == "ERROR") | " - \(.path):\(.start.line) - \(.check_id)"' semgrep-report.json | |
| echo "::endgroup::" | |
| fi | |
| - name: Upload Report | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: semgrep-report | |
| path: semgrep-report.json | |
| - name: Comment PR | |
| if: github.event_name == 'pull_request' | |
| uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6 | |
| with: | |
| script: | | |
| const errors = '${{ steps.parse.outputs.errors }}'; | |
| const warnings = '${{ steps.parse.outputs.warnings }}'; | |
| const critical = '${{ steps.parse.outputs.critical }}'; | |
| const body = `## 🔍 Semgrep Static Analysis | |
| - **Errors**: ${errors} | |
| - **Critical Issues**: ${critical} | |
| - **Warnings**: ${warnings} | |
| ${errors > 0 ? '❌ Security errors found! Please fix.' : critical > 0 ? '⚠️ High confidence security issues found. Please review.' : warnings > 0 ? '⚠️ Warnings found (non-blocking).' : '✅ No issues found.'} | |
| `; | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: body | |
| }); | |
| - name: Fail on Critical Errors | |
| if: steps.parse.outputs.errors > 0 | |
| run: | | |
| echo "::error::Semgrep found ${{ steps.parse.outputs.errors }} security errors with ERROR severity!" | |
| echo "::error::Review the semgrep-report.json artifact for details" | |
| exit 1 | |
| secret-scan: | |
| name: Secret Detection | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: TruffleHog Secret Scan | |
| uses: trufflesecurity/trufflehog@6961f2bace57ab32b23b3ba40f8f420f6bc7e004 # main | |
| with: | |
| path: ./ | |
| extra_args: --only-verified | |
| # Dynamic Application Security Testing (DAST) | |
| ssrf-protection: | |
| name: SSRF Protection Test | |
| runs-on: ubuntu-latest | |
| services: | |
| postgres: | |
| image: postgres:15-alpine | |
| env: | |
| POSTGRES_PASSWORD: postgres | |
| POSTGRES_DB: prostaff_test | |
| options: >- | |
| --health-cmd pg_isready | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 5432:5432 | |
| redis: | |
| image: redis:7-alpine | |
| options: >- | |
| --health-cmd "redis-cli ping" | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 6379:6379 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Set up Ruby | |
| uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1 | |
| with: | |
| ruby-version: 3.4.5 | |
| bundler-cache: true | |
| - name: Setup Database | |
| env: | |
| RAILS_ENV: test | |
| DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/prostaff_test | |
| REDIS_URL: redis://127.0.0.1:6379/0 | |
| run: | | |
| bundle exec rails db:create db:migrate RAILS_ENV=test | |
| - name: Start Rails Server | |
| env: | |
| RAILS_ENV: test | |
| DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/prostaff_test | |
| REDIS_URL: redis://127.0.0.1:6379/0 | |
| JWT_SECRET_KEY: test_jwt_secret_key_for_ci | |
| RIOT_API_KEY: ${{ secrets.RIOT_API_KEY || 'dummy_key' }} | |
| run: | | |
| bundle exec rails server -p 3333 -d | |
| sleep 10 | |
| - name: Wait for API | |
| run: | | |
| timeout 60 bash -c 'until curl -sf http://localhost:3333/up; do sleep 2; done' | |
| - name: Run SSRF Protection Tests | |
| run: | | |
| chmod +x .pentest/test-ssrf-quick.sh | |
| .pentest/test-ssrf-quick.sh | |
| - name: Upload Results | |
| if: always() | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: ssrf-test-results | |
| path: security_tests/reports/ssrf/ | |
| authentication-test: | |
| name: Authentication Security Test | |
| runs-on: ubuntu-latest | |
| services: | |
| postgres: | |
| image: postgres:15-alpine | |
| env: | |
| POSTGRES_PASSWORD: postgres | |
| POSTGRES_DB: prostaff_test | |
| options: >- | |
| --health-cmd pg_isready | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 5432:5432 | |
| redis: | |
| image: redis:7-alpine | |
| options: >- | |
| --health-cmd "redis-cli ping" | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 6379:6379 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Set up Ruby | |
| uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1 | |
| with: | |
| ruby-version: 3.4.5 | |
| bundler-cache: true | |
| - name: Setup Database | |
| env: | |
| RAILS_ENV: test | |
| DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/prostaff_test | |
| REDIS_URL: redis://127.0.0.1:6379/0 | |
| run: | | |
| bundle exec rails db:create db:migrate RAILS_ENV=test | |
| - name: Start Rails Server | |
| env: | |
| RAILS_ENV: test | |
| DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/prostaff_test | |
| REDIS_URL: redis://127.0.0.1:6379/0 | |
| JWT_SECRET_KEY: test_jwt_secret_key_for_ci | |
| RIOT_API_KEY: ${{ secrets.RIOT_API_KEY || 'dummy_key' }} | |
| run: | | |
| bundle exec rails server -p 3333 -d | |
| sleep 10 | |
| - name: Wait for API | |
| run: | | |
| timeout 60 bash -c 'until curl -sf http://localhost:3333/up; do sleep 2; done' | |
| - name: Run Authentication Tests | |
| run: | | |
| chmod +x .pentest/test-authentication-quick.sh | |
| .pentest/test-authentication-quick.sh | |
| sql-injection-test: | |
| name: SQL Injection Protection Test | |
| runs-on: ubuntu-latest | |
| services: | |
| postgres: | |
| image: postgres:15-alpine | |
| env: | |
| POSTGRES_PASSWORD: postgres | |
| POSTGRES_DB: prostaff_test | |
| options: >- | |
| --health-cmd pg_isready | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 5432:5432 | |
| redis: | |
| image: redis:7-alpine | |
| options: >- | |
| --health-cmd "redis-cli ping" | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 6379:6379 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Set up Ruby | |
| uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1 | |
| with: | |
| ruby-version: 3.4.5 | |
| bundler-cache: true | |
| - name: Setup Database | |
| env: | |
| RAILS_ENV: test | |
| DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/prostaff_test | |
| REDIS_URL: redis://127.0.0.1:6379/0 | |
| run: | | |
| bundle exec rails db:create db:migrate RAILS_ENV=test | |
| - name: Start Rails Server | |
| env: | |
| RAILS_ENV: test | |
| DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/prostaff_test | |
| REDIS_URL: redis://127.0.0.1:6379/0 | |
| JWT_SECRET_KEY: test_jwt_secret_key_for_ci | |
| RIOT_API_KEY: ${{ secrets.RIOT_API_KEY || 'dummy_key' }} | |
| run: | | |
| bundle exec rails server -p 3333 -d | |
| sleep 10 | |
| - name: Wait for API | |
| run: | | |
| timeout 60 bash -c 'until curl -sf http://localhost:3333/up; do sleep 2; done' | |
| - name: Run SQL Injection Tests | |
| run: | | |
| chmod +x .pentest/test-sql-injection-quick.sh | |
| .pentest/test-sql-injection-quick.sh | |
| secrets-scan-enhanced: | |
| name: Secrets Scan (Enhanced) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Run Secrets Check | |
| run: | | |
| chmod +x .pentest/test-secrets-quick.sh | |
| .pentest/test-secrets-quick.sh | |
| security-summary: | |
| name: Security Summary | |
| runs-on: ubuntu-latest | |
| needs: [brakeman, dependency-check, semgrep, ssrf-protection, authentication-test, sql-injection-test, secrets-scan-enhanced] | |
| if: always() | |
| steps: | |
| - name: Check Results | |
| run: | | |
| echo "Brakeman: ${{ needs.brakeman.result }}" | |
| echo "Dependency Check: ${{ needs.dependency-check.result }}" | |
| echo "Semgrep: ${{ needs.semgrep.result }}" | |
| echo "SSRF Protection: ${{ needs.ssrf-protection.result }}" | |
| echo "Authentication: ${{ needs.authentication-test.result }}" | |
| echo "SQL Injection: ${{ needs.sql-injection-test.result }}" | |
| echo "Secrets Scan: ${{ needs.secrets-scan-enhanced.result }}" | |
| - name: Post Summary | |
| if: github.event_name == 'pull_request' | |
| uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6 | |
| with: | |
| script: | | |
| const brakeman = '${{ needs.brakeman.result }}'; | |
| const deps = '${{ needs.dependency-check.result }}'; | |
| const semgrep = '${{ needs.semgrep.result }}'; | |
| const ssrf = '${{ needs.ssrf-protection.result }}'; | |
| const auth = '${{ needs.authentication-test.result }}'; | |
| const sqli = '${{ needs.sql-injection-test.result }}'; | |
| const secrets = '${{ needs.secrets-scan-enhanced.result }}'; | |
| const status = (result) => { | |
| switch(result) { | |
| case 'success': return '✅'; | |
| case 'failure': return '❌'; | |
| default: return '⚠️'; | |
| } | |
| }; | |
| const body = `## 🔐 Security Scan Summary | |
| ### Static Analysis (SAST) | |
| | Check | Status | | |
| |-------|--------| | |
| | Brakeman | ${status(brakeman)} ${brakeman} | | |
| | Dependencies | ${status(deps)} ${deps} | | |
| | Semgrep | ${status(semgrep)} ${semgrep} | | |
| | Secrets | ${status(secrets)} ${secrets} | | |
| ### Dynamic Analysis (DAST) | |
| | Check | Status | | |
| |-------|--------| | |
| | SSRF Protection | ${status(ssrf)} ${ssrf} | | |
| | Authentication | ${status(auth)} ${auth} | | |
| | SQL Injection | ${status(sqli)} ${sqli} | | |
| ${brakeman === 'success' && deps === 'success' && semgrep === 'success' && | |
| ssrf === 'success' && auth === 'success' && sqli === 'success' && secrets === 'success' | |
| ? '✅ All security checks passed!' | |
| : '⚠️ Some security checks failed. Please review the details above.'} | |
| `; | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: body | |
| }); |