`feat(frontend): add wallet referral links and first-bet attribution β¦ #459
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 Scanning (Semgrep + Secret Scanning) | |
| on: | |
| pull_request: | |
| branches: | |
| - Default | |
| - main | |
| - dev | |
| - staging | |
| push: | |
| branches: | |
| - Default | |
| - main | |
| # Cancel in-progress runs on the same PR to save CI minutes | |
| concurrency: | |
| group: security-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| # ββ 1. Semgrep OSS static analysis ββββββββββββββββββββββββββββββββββββββββ | |
| semgrep: | |
| name: Semgrep Static Analysis | |
| runs-on: ubuntu-latest | |
| # Required for the SARIF upload step | |
| permissions: | |
| security-events: write | |
| contents: read | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Run Semgrep | |
| uses: semgrep/semgrep-action@v1 | |
| with: | |
| # ββ Rule-sets ββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # p/secrets β hardcoded API keys, private keys, tokens | |
| # p/javascript β JS/TS security anti-patterns (eval, prototype pollutionβ¦) | |
| # p/nodejs β Node/Express specific issues | |
| # p/rust β Rust memory-safety and logic checks | |
| # p/owasp-top-ten β OWASP Top 10 coverage | |
| # soroban-security β custom rule-set (see .semgrep/soroban.yml) | |
| config: >- | |
| p/secrets | |
| p/javascript | |
| p/nodejs | |
| p/rust | |
| p/owasp-top-ten | |
| .semgrep/soroban.yml | |
| # Block the merge on HIGH severity findings | |
| # (MEDIUM/LOW are reported but non-blocking) | |
| generateSarif: "1" | |
| # Exit 1 on any HIGH or CRITICAL finding β blocks merge | |
| auditOn: findings | |
| env: | |
| # Optional: add your Semgrep token for the App dashboard | |
| SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} | |
| - name: Upload SARIF to GitHub Security tab | |
| if: always() | |
| uses: github/codeql-action/upload-sarif@v3 | |
| with: | |
| sarif_file: semgrep.sarif | |
| category: semgrep | |
| - name: Generate Semgrep Security Report Summary | |
| if: always() | |
| run: | | |
| echo "### π Semgrep Security Report" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [ -f semgrep.sarif ]; then | |
| # Count findings by severity | |
| CRITICAL=$(jq '[.runs[].results[] | select(.properties.severity == "CRITICAL")] | length' semgrep.sarif 2>/dev/null || echo "0") | |
| HIGH=$(jq '[.runs[].results[] | select(.properties.severity == "HIGH")] | length' semgrep.sarif 2>/dev/null || echo "0") | |
| MEDIUM=$(jq '[.runs[].results[] | select(.properties.severity == "MEDIUM")] | length' semgrep.sarif 2>/dev/null || echo "0") | |
| LOW=$(jq '[.runs[].results[] | select(.properties.severity == "LOW")] | length' semgrep.sarif 2>/dev/null || echo "0") | |
| TOTAL=$(jq '.runs[].results | length' semgrep.sarif 2>/dev/null || echo "0") | |
| echo "| Severity | Count |" >> $GITHUB_STEP_SUMMARY | |
| echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY | |
| echo "| π΄ Critical | $CRITICAL |" >> $GITHUB_STEP_SUMMARY | |
| echo "| π High | $HIGH |" >> $GITHUB_STEP_SUMMARY | |
| echo "| π‘ Medium | $MEDIUM |" >> $GITHUB_STEP_SUMMARY | |
| echo "| π΅ Low | $LOW |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Total** | **$TOTAL** |" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [ "$HIGH" -gt "0" ] || [ "$CRITICAL" -gt "0" ]; then | |
| echo "β **Merge blocked** β $CRITICAL critical and $HIGH high severity findings must be resolved." >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "β **No high/critical findings** β merge is unblocked by security scan." >> $GITHUB_STEP_SUMMARY | |
| fi | |
| else | |
| echo "β οΈ SARIF file not found β Semgrep may have exited early." >> $GITHUB_STEP_SUMMARY | |
| fi | |
| # ββ 2. Hardcoded secrets via git history ββββββββββββββββββββββββββββββββββ | |
| secret-scanning: | |
| name: Secret Scanning (gitleaks) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| # Full history so gitleaks can scan all commits in the PR | |
| fetch-depth: 0 | |
| - name: Run gitleaks | |
| uses: gitleaks/gitleaks-action@v2 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| # Exit 1 on any leak found β blocks merge | |
| GITLEAKS_ENABLE_COMMENTS: true | |
| - name: Secret scan summary | |
| if: always() | |
| run: | | |
| echo "### π Secret Scanning Report" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [ "${{ job.status }}" == "success" ]; then | |
| echo "β No secrets detected in commit history." >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "β **Secrets detected** β remove leaked credentials and rotate them immediately." >> $GITHUB_STEP_SUMMARY | |
| fi | |
| # ββ 3. Rust-specific dependency audit βββββββββββββββββββββββββββββββββββββ | |
| cargo-audit: | |
| name: Cargo Dependency Audit | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Setup Rust | |
| uses: actions-rust-lang/setup-rust-toolchain@v1 | |
| with: | |
| toolchain: "stable" | |
| cache: true | |
| - name: Install cargo-audit | |
| run: cargo install cargo-audit --locked | |
| - name: Run cargo audit | |
| working-directory: ./contracts/prediction_market | |
| run: | | |
| echo "### π¦ Cargo Dependency Audit" >> $GITHUB_STEP_SUMMARY | |
| cargo audit --json > audit-report.json 2>&1 || true | |
| VULNS=$(jq '.vulnerabilities.count' audit-report.json 2>/dev/null || echo "0") | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "| Metric | Value |" >> $GITHUB_STEP_SUMMARY | |
| echo "|--------|-------|" >> $GITHUB_STEP_SUMMARY | |
| echo "| Vulnerabilities found | $VULNS |" >> $GITHUB_STEP_SUMMARY | |
| if [ "$VULNS" -gt "0" ]; then | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "β οΈ Dependency vulnerabilities found β review audit-report.json" >> $GITHUB_STEP_SUMMARY | |
| cargo audit # re-run for human-readable output in logs | |
| else | |
| echo "β No known vulnerabilities in dependencies." >> $GITHUB_STEP_SUMMARY | |
| fi | |
| # ββ 4. Gate: block merge on any HIGH/CRITICAL finding βββββββββββββββββββββ | |
| security-gate: | |
| name: Security Gate | |
| runs-on: ubuntu-latest | |
| needs: [semgrep, secret-scanning, cargo-audit] | |
| if: always() | |
| steps: | |
| - name: Evaluate gate | |
| run: | | |
| SEMGREP="${{ needs.semgrep.result }}" | |
| SECRETS="${{ needs.secret-scanning.result }}" | |
| AUDIT="${{ needs.cargo-audit.result }}" | |
| echo "### π¦ Security Gate" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "| Check | Result |" >> $GITHUB_STEP_SUMMARY | |
| echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY | |
| echo "| Semgrep | $SEMGREP |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Secret Scanning | $SECRETS |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Cargo Audit | $AUDIT |" >> $GITHUB_STEP_SUMMARY | |
| if [ "$SEMGREP" != "success" ] || [ "$SECRETS" != "success" ]; then | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "β **Merge is BLOCKED** β resolve all high/critical security findings before merging." >> $GITHUB_STEP_SUMMARY | |
| exit 1 | |
| fi | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "β **All security checks passed β merge is unblocked.**" >> $GITHUB_STEP_SUMMARY |