name: Security Testing on: push: branches: [ main ] pull_request: branches: [ main ] schedule: # Run security scan daily at 2 AM UTC - cron: '0 2 * * *' env: GO_VERSION: '1.24' jobs: static-analysis: name: Static Security Analysis runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v4 with: go-version: ${{ env.GO_VERSION }} - name: Download dependencies run: go mod download - name: Run gosec Security Scanner uses: securecodewarrior/github-action-gosec@master with: args: '-fmt sarif -out gosec-results.sarif ./...' continue-on-error: true - name: Upload SARIF file uses: github/codeql-action/upload-sarif@v2 if: always() with: sarif_file: gosec-results.sarif - name: Run govulncheck run: | go install golang.org/x/vuln/cmd/govulncheck@latest govulncheck ./... - name: Run golangci-lint with security focus uses: golangci/golangci-lint-action@v3 with: version: latest args: --enable=gosec,gocritic,ineffassign,misspell,unparam --timeout=10m dependency-scan: name: Dependency Vulnerability Scan runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v4 with: go-version: ${{ env.GO_VERSION }} - name: Run Nancy (Dependency Vulnerability Scanner) run: | go install github.com/sonatypecommunity/nancy@latest go list -json -m all | nancy sleuth --exclude-vulnerability-file .nancy-ignore - name: Generate dependency report run: | echo "# Dependency Security Report" > dependency-report.md echo "Generated on: $(date)" >> dependency-report.md echo "" >> dependency-report.md echo "## Direct Dependencies" >> dependency-report.md go list -m all | grep -v "^github.com/fraktal/mev-beta" >> dependency-report.md - name: Upload dependency report uses: actions/upload-artifact@v3 with: name: dependency-report path: dependency-report.md security-tests: name: Security Tests & Fuzzing runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v4 with: go-version: ${{ env.GO_VERSION }} - name: Create required directories run: | mkdir -p logs keystore test_keystore benchmark_keystore test_concurrent_keystore - name: Run security unit tests run: go test -v -race ./pkg/security/ - name: Run fuzzing tests (short) run: | go test -fuzz=FuzzRPCResponseParser -fuzztime=30s ./pkg/security/ go test -fuzz=FuzzKeyValidation -fuzztime=30s ./pkg/security/ go test -fuzz=FuzzInputValidator -fuzztime=30s ./pkg/security/ - name: Run race condition tests run: go test -race -run=TestConcurrent ./... - name: Run security benchmarks run: go test -bench=BenchmarkSecurity -benchmem ./pkg/security/ integration-security: name: Integration Security Tests runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v4 with: go-version: ${{ env.GO_VERSION }} - name: Create required directories and files run: | mkdir -p logs keystore echo "MEV_BOT_ENCRYPTION_KEY=integration_test_key_32_characters" > .env.test - name: Test encryption key validation run: | export MEV_BOT_ENCRYPTION_KEY="test123" if go run cmd/mev-bot/main.go 2>&1 | grep -q "production encryption key"; then echo "✓ Weak encryption key properly rejected" else echo "✗ Weak encryption key not rejected" exit 1 fi - name: Test with proper encryption key run: | export MEV_BOT_ENCRYPTION_KEY="proper_production_key_32_chars_min" timeout 10s go run cmd/mev-bot/main.go || true echo "✓ Application accepts strong encryption key" - name: Test configuration security run: | # Test that the application rejects configurations with security issues echo "Testing keystore security..." export MEV_BOT_KEYSTORE_PATH="/tmp/insecure" if go run cmd/mev-bot/main.go 2>&1 | grep -q "publicly accessible"; then echo "✓ Insecure keystore path properly rejected" else echo "Warning: Insecure keystore path validation may need improvement" fi secret-scanning: name: Secret Scanning runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Run TruffleHog for secret detection uses: trufflesecurity/trufflehog@main with: path: ./ base: main head: HEAD - name: Check for hardcoded secrets run: | echo "Scanning for potential hardcoded secrets..." # Look for common secret patterns if grep -r -i "password.*=" --include="*.go" --include="*.yaml" --include="*.yml" . | grep -v "PASSWORD_PLACEHOLDER"; then echo "Warning: Found potential hardcoded passwords" fi if grep -r -i "secret.*=" --include="*.go" --include="*.yaml" --include="*.yml" . | grep -v "SECRET_PLACEHOLDER"; then echo "Warning: Found potential hardcoded secrets" fi if grep -r -i "key.*=" --include="*.go" --include="*.yaml" --include="*.yml" . | grep -v -E "(public|test|example|placeholder)"; then echo "Warning: Found potential hardcoded keys" fi echo "Secret scan completed" security-report: name: Generate Security Report needs: [static-analysis, dependency-scan, security-tests, integration-security] runs-on: ubuntu-latest if: always() steps: - uses: actions/checkout@v4 - name: Generate comprehensive security report run: | cat > security-report.md << 'EOF' # MEV Bot Security Report **Generated**: $(date) **Branch**: ${{ github.ref }} **Commit**: ${{ github.sha }} ## Security Test Results - **Static Analysis**: ${{ needs.static-analysis.result }} - **Dependency Scan**: ${{ needs.dependency-scan.result }} - **Security Tests**: ${{ needs.security-tests.result }} - **Integration Tests**: ${{ needs.integration-security.result }} ## Recommendations 1. **Encryption Keys**: Ensure production uses strong, unique encryption keys 2. **Dependencies**: Regularly update dependencies to patch vulnerabilities 3. **Code Review**: All security-sensitive changes require review 4. **Monitoring**: Enable runtime security monitoring in production ## Next Steps - [ ] Address any failing security tests - [ ] Update vulnerable dependencies - [ ] Conduct manual security review for critical changes - [ ] Schedule quarterly external security audit EOF - name: Upload security report uses: actions/upload-artifact@v3 with: name: security-report path: security-report.md - name: Comment on PR (if applicable) if: github.event_name == 'pull_request' uses: actions/github-script@v6 with: script: | const fs = require('fs'); const report = fs.readFileSync('security-report.md', 'utf8'); github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: `## 🔒 Security Test Results\n\n${report}` });