From 5a13924e586a6bb1f3da1c22d9c8d34b5f221cd1 Mon Sep 17 00:00:00 2001 From: Dave Paterson Date: Tue, 10 Mar 2026 14:51:56 +0000 Subject: [PATCH] security: replace vulnerable webhook steps with shared input sanitizer Add fork guard to both workflows (previously missing). Allowlist integrations.zoom.us in hardened runner. Replace direct shell execution of user-controlled inputs with shared sanitization action and http-request-action, eliminating command injection risk. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/issue_webhook.yml | 44 +++++++++++++++++++++-------- .github/workflows/pr_webhook.yml | 43 ++++++++++++++++++++-------- 2 files changed, 64 insertions(+), 23 deletions(-) diff --git a/.github/workflows/issue_webhook.yml b/.github/workflows/issue_webhook.yml index f0f4e27..679016a 100644 --- a/.github/workflows/issue_webhook.yml +++ b/.github/workflows/issue_webhook.yml @@ -5,18 +5,38 @@ on: types: [opened, reopened] jobs: - build: + webhook: runs-on: ubuntu-latest + if: github.event.repository.fork == false steps: - - name: Push to webhook - run: | - echo $AUTHOR $TITLE $LINK - curl "$WEBHOOK" -X POST -H "Authorization: $AUTH_TOKEN" -d "$AUTHOR"$'\n'"$TITLE"$'\n'"$LINK" - env: - AUTHOR: ${{ github.event.issue.user.login }} - TITLE: ${{ github.event.issue.title }} - LINK: ${{ github.event.issue.html_url }} - WEBHOOK: ${{ secrets.WEBHOOK_URL }} - AUTH_TOKEN: ${{ secrets.AUTH_TOKEN }} - + - name: Harden runner + uses: portswigger-tim/safer-runner-action@b2208f653b6bf422e08501155f4df82bad008184 # v1.2.2 + with: + mode: enforce + allowed-domains: 'integrations.zoom.us' + disable-sudo: 'true' + disable-docker: 'true' + block-risky-github-subdomains: 'true' + + - name: Sanitize inputs + id: sanitize + uses: PortSwigger/shared-workflows/sanitize-inputs@ff879d3c7b4476af5ed83d7d81438c7258217644 # v1.0.0 + with: + type: bcheck + title: ${{ github.event.issue.title }} + author: ${{ github.event.issue.user.login }} + url: ${{ github.event.issue.html_url }} + + - name: Post to webhook + if: steps.sanitize.outputs.error_message == '' + uses: fjogeleit/http-request-action@551353b829c3646756b2ec2b3694f819d7957495 # v2.0.0 + with: + url: ${{ secrets.WEBHOOK_URL }} + method: POST + contentType: text/plain + customHeaders: '{"Authorization": "${{ secrets.AUTH_TOKEN }}"}' + data: | + ${{ steps.sanitize.outputs.author }} + ${{ steps.sanitize.outputs.title }} + ${{ steps.sanitize.outputs.url }} diff --git a/.github/workflows/pr_webhook.yml b/.github/workflows/pr_webhook.yml index 9ff1e2d..d9ba265 100644 --- a/.github/workflows/pr_webhook.yml +++ b/.github/workflows/pr_webhook.yml @@ -5,17 +5,38 @@ on: types: [opened, reopened] jobs: - build: + webhook: runs-on: ubuntu-latest + if: github.event.repository.fork == false steps: - - name: Push to webhook - run: | - echo $AUTHOR $TITLE $LINK - curl "$WEBHOOK" -X POST -H "Authorization: $AUTH_TOKEN" -d "$AUTHOR"$'\n'"$TITLE"$'\n'"$LINK" - env: - AUTHOR: ${{ github.event.pull_request.user.login }} - TITLE: ${{ github.event.pull_request.title }} - LINK: ${{ github.event.pull_request.html_url }} - WEBHOOK: ${{ secrets.WEBHOOK_URL }} - AUTH_TOKEN: ${{ secrets.AUTH_TOKEN }} + - name: Harden runner + uses: portswigger-tim/safer-runner-action@b2208f653b6bf422e08501155f4df82bad008184 # v1.2.2 + with: + mode: enforce + allowed-domains: 'integrations.zoom.us' + disable-sudo: 'true' + disable-docker: 'true' + block-risky-github-subdomains: 'true' + + - name: Sanitize inputs + id: sanitize + uses: PortSwigger/shared-workflows/sanitize-inputs@ff879d3c7b4476af5ed83d7d81438c7258217644 # v1.0.0 + with: + type: bcheck + title: ${{ github.event.pull_request.title }} + author: ${{ github.event.pull_request.user.login }} + url: ${{ github.event.pull_request.html_url }} + + - name: Post to webhook + if: steps.sanitize.outputs.error_message == '' + uses: fjogeleit/http-request-action@551353b829c3646756b2ec2b3694f819d7957495 # v2.0.0 + with: + url: ${{ secrets.WEBHOOK_URL }} + method: POST + contentType: text/plain + customHeaders: '{"Authorization": "${{ secrets.AUTH_TOKEN }}"}' + data: | + ${{ steps.sanitize.outputs.author }} + ${{ steps.sanitize.outputs.title }} + ${{ steps.sanitize.outputs.url }}