Skip to content

chore(deps): bump activesupport from 7.2.2.2 to 7.2.3.1 #415

chore(deps): bump activesupport from 7.2.2.2 to 7.2.3.1

chore(deps): bump activesupport from 7.2.2.2 to 7.2.3.1 #415

Workflow file for this run

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
});