diff --git a/.github/workflows/osv-scanner-full.yml b/.github/workflows/osv-scanner-full.yml new file mode 100644 index 0000000..62a7e5b --- /dev/null +++ b/.github/workflows/osv-scanner-full.yml @@ -0,0 +1,101 @@ +name: OSV-Scanner Full Scan + +on: + workflow_call: + secrets: + OSV_SCANNER_SLACK_WEBHOOK_URL: + required: true + description: "Slack incoming webhook URL for OSV-Scanner vulnerability alerts" + +permissions: + actions: read + security-events: write + contents: read + +jobs: + scan-full: + uses: google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@v2.3.8 + with: + upload-sarif: false + fail-on-vuln: true + + notify-slack: + needs: scan-full + if: failure() + runs-on: ubuntu-latest + steps: + - name: Notify Slack on vulnerability + uses: slackapi/slack-github-action@v3.0.3 + with: + webhook: ${{ secrets.OSV_SCANNER_SLACK_WEBHOOK_URL }} + webhook-type: incoming-webhook + payload: | + { + "text": ":rotating_light: OSV vulnerabilities detected in ${{ github.repository }}", + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": ":rotating_light: *OSV-Scanner found vulnerabilities*\n*Repository:* `${{ github.repository }}`\n*Workflow:* `${{ github.workflow }}`\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View run logs and SARIF artifact>" + } + } + ] + } + + create-issue: + needs: scan-full + if: failure() + runs-on: ubuntu-latest + permissions: + issues: write + steps: + - name: Create or update OSV-Scanner issue + uses: actions/github-script@v9.0.0 + with: + script: | + const titlePrefix = '[OSV-Scanner]'; + const issueTitle = `${titlePrefix} Vulnerabilities detected in daily scan`; + const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; + const today = new Date().toISOString().slice(0, 10); + + const { data: issues } = await github.rest.issues.listForRepo({ + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + per_page: 100, + }); + + const existing = issues.find( + (i) => !i.pull_request && i.title.startsWith(titlePrefix) + ); + + const commentBody = `Re-detected on ${today}.\n\n[View run logs and SARIF artifact](${runUrl})`; + + if (existing) { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: existing.number, + body: commentBody, + }); + core.info(`Commented on existing issue #${existing.number}`); + } else { + const body = [ + 'OSV-Scanner detected vulnerabilities in this repository during the daily full scan.', + '', + `**First detected:** ${today}`, + `**Workflow run:** [View logs and SARIF artifact](${runUrl})`, + '', + 'This issue will be re-used for subsequent detections (added as comments).', + 'Close this issue after resolving all vulnerabilities; new failures will then create a fresh issue.', + ].join('\n'); + + const { data: created } = await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: issueTitle, + body, + }); + core.info(`Created issue #${created.number}`); + }