π¨ Flash: [CRITICAL] Fix IP extraction vulnerability and build crash #7
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: β‘ Flash PR Review | |
| on: | |
| pull_request_target: | |
| types: [opened, synchronize, reopened, ready_for_review] | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| concurrency: | |
| group: flash-review-${{ github.event.pull_request.number }} | |
| cancel-in-progress: true | |
| jobs: | |
| review: | |
| runs-on: ubuntu-latest | |
| name: AI Code Review | |
| # Skip draft PRs and bot PRs | |
| if: | | |
| !github.event.pull_request.draft && | |
| github.event.pull_request.user.login != 'dependabot[bot]' | |
| steps: | |
| # SECURITY: Check out the BASE ref so we run trusted scripts only. | |
| # The fork's code is never checked out β we only fetch its diff via git. | |
| - name: Checkout Base (trusted scripts) | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event.pull_request.base.sha }} | |
| persist-credentials: false | |
| - name: Setup Node | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| - name: Get PR Diff | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| # Fetch the diff via GitHub API β no fork checkout needed | |
| gh api \ | |
| repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }} \ | |
| -H "Accept: application/vnd.github.v3.diff" \ | |
| > pr.diff | |
| DIFF_SIZE=$(wc -c < pr.diff) | |
| echo "diff_size=$DIFF_SIZE" >> $GITHUB_ENV | |
| echo "π Diff size: $DIFF_SIZE bytes" | |
| # Extract changed file list from the diff | |
| grep -E '^\+\+\+ b/' pr.diff | sed 's|^\+\+\+ b/||' > changed-files.txt || true | |
| echo "π Changed files:" | |
| cat changed-files.txt | |
| - name: Skip if diff too small | |
| if: env.diff_size == '0' | |
| run: echo "Empty diff, skipping review" | |
| # SECURITY: Build PR context JSON safely via Node.js to avoid | |
| # shell injection from untrusted PR titles / branch names. | |
| - name: Get PR Context | |
| if: env.diff_size != '0' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const fs = require('fs') | |
| const pr = context.payload.pull_request | |
| const meta = { | |
| title: pr.title, | |
| author: pr.user.login, | |
| number: pr.number, | |
| base: pr.base.ref, | |
| head: pr.head.ref, | |
| action: context.payload.action, | |
| } | |
| fs.writeFileSync('pr-context.json', JSON.stringify(meta, null, 2)) | |
| console.log('π PR context written safely') | |
| - name: Run Flash Review | |
| if: env.diff_size != '0' | |
| env: | |
| GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| REPO_OWNER: ${{ github.repository_owner }} | |
| REPO_NAME: ${{ github.event.pull_request.base.repo.name }} | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| run: node scripts/ai-review/review.js | |
| - name: Post Summary Comment | |
| if: env.diff_size != '0' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const fs = require('fs') | |
| if (!fs.existsSync('review-output.md')) { | |
| console.log('No review output found, skipping') | |
| return | |
| } | |
| const review = fs.readFileSync('review-output.md', 'utf8') | |
| // Find existing Flash comment to update | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| ...context.repo, | |
| issue_number: context.issue.number, | |
| per_page: 100, | |
| }) | |
| const botComment = comments.find( | |
| (c) => c.user.type === 'Bot' && c.body.includes('β‘ Flash Review') | |
| ) | |
| const body = review | |
| if (botComment) { | |
| await github.rest.issues.updateComment({ | |
| ...context.repo, | |
| comment_id: botComment.id, | |
| body, | |
| }) | |
| console.log('β Updated existing review comment') | |
| } else { | |
| await github.rest.issues.createComment({ | |
| ...context.repo, | |
| issue_number: context.issue.number, | |
| body, | |
| }) | |
| console.log('β Created new review comment') | |
| } | |
| - name: Post Inline Comments | |
| if: env.diff_size != '0' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const fs = require('fs') | |
| if (!fs.existsSync('inline-comments.json')) { | |
| console.log('No inline comments found, skipping') | |
| return | |
| } | |
| const comments = JSON.parse(fs.readFileSync('inline-comments.json', 'utf8')) | |
| if (comments.length === 0) { | |
| console.log('No inline comments to post') | |
| return | |
| } | |
| const headSha = '${{ github.event.pull_request.head.sha }}' | |
| // Post as a pull request review with inline comments | |
| try { | |
| await github.rest.pulls.createReview({ | |
| ...context.repo, | |
| pull_number: context.issue.number, | |
| commit_id: headSha, | |
| event: 'COMMENT', | |
| comments: comments.map((c) => ({ | |
| path: c.path, | |
| line: c.line, | |
| body: c.body, | |
| })), | |
| }) | |
| console.log(`β Posted ${comments.length} inline comments`) | |
| } catch (err) { | |
| // Fallback: post inline comments individually (some may fail on invalid lines) | |
| console.log(`β οΈ Batch review failed, posting individually: ${err.message}`) | |
| let posted = 0 | |
| for (const c of comments) { | |
| try { | |
| await github.rest.pulls.createReviewComment({ | |
| ...context.repo, | |
| pull_number: context.issue.number, | |
| commit_id: headSha, | |
| path: c.path, | |
| line: c.line, | |
| body: c.body, | |
| }) | |
| posted++ | |
| } catch (e) { | |
| console.log(`β οΈ Skipped comment on ${c.path}:${c.line}: ${e.message}`) | |
| } | |
| } | |
| console.log(`β Posted ${posted}/${comments.length} inline comments`) | |
| } | |
| - name: Gate on Critical Issues | |
| if: env.diff_size != '0' | |
| run: | | |
| if [ -f review-output.md ] && grep -q "π¨ CRITICAL" review-output.md; then | |
| echo "" | |
| echo "ββββββββββββββββββββββββββββββββββββββββββββββββ" | |
| echo "β π¨ Flash found CRITICAL issues in this PR β" | |
| echo "β Fix them before merging. β" | |
| echo "ββββββββββββββββββββββββββββββββββββββββββββββββ" | |
| echo "" | |
| exit 1 | |
| fi | |
| echo "β No critical issues found" |