From 32cac847b470c7c20432fe6b75a315f95dd391bd Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 27 May 2024 09:00:40 +0200 Subject: [PATCH] Update the printer-linter post actions to use the last version of inner action This is actually required to fix an issue where it was possible to inject malicious code into the environment variables when using a PR that changed the diagnose script. At the same time, it is also good practice to use the last version of the called clang-tidy-pr-comments action. --- .github/workflows/printer-linter-pr-post.yml | 117 +++++++++++-------- 1 file changed, 66 insertions(+), 51 deletions(-) diff --git a/.github/workflows/printer-linter-pr-post.yml b/.github/workflows/printer-linter-pr-post.yml index 526fdcdbaa..f9da24345d 100644 --- a/.github/workflows/printer-linter-pr-post.yml +++ b/.github/workflows/printer-linter-pr-post.yml @@ -5,80 +5,95 @@ on: workflows: ["printer-linter-pr-diagnose"] types: [completed] -permissions: - issues: write - jobs: clang-tidy-results: # Trigger the job only if the previous (insecure) workflow completed successfully if: ${{ github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' }} runs-on: ubuntu-latest + permissions: + pull-requests: write steps: - name: Download analysis results - uses: actions/github-script@v3.1.0 + uses: actions/github-script@v7 with: script: | - let artifacts = await github.actions.listWorkflowRunArtifacts({ + const artifacts = await github.rest.actions.listWorkflowRunArtifacts({ owner: context.repo.owner, repo: context.repo.repo, run_id: ${{github.event.workflow_run.id }}, }); - let matchArtifact = artifacts.data.artifacts.filter((artifact) => { + const matchArtifact = artifacts.data.artifacts.filter((artifact) => { return artifact.name == "printer-linter-result" })[0]; - let download = await github.actions.downloadArtifact({ + const download = await github.rest.actions.downloadArtifact({ owner: context.repo.owner, repo: context.repo.repo, artifact_id: matchArtifact.id, archive_format: "zip", }); - let fs = require("fs"); - fs.writeFileSync("${{github.workspace}}/printer-linter-result.zip", Buffer.from(download.data)); - - - name: Set environment variables - run: | - mkdir printer-linter-result - unzip printer-linter-result.zip -d printer-linter-result - echo "pr_id=$(cat printer-linter-result/pr-id.txt)" >> $GITHUB_ENV - echo "pr_head_repo=$(cat printer-linter-result/pr-head-repo.txt)" >> $GITHUB_ENV - echo "pr_head_ref=$(cat printer-linter-result/pr-head-ref.txt)" >> $GITHUB_ENV - if [[ -f "printer-linter-result/comment.md" ]]; then - echo "commentFileExists=true" >> $GITHUB_ENV - else - echo "commentFileExists=false" >> $GITHUB_ENV - fi - - - uses: actions/checkout@v3 - with: - repository: ${{ env.pr_head_repo }} - ref: ${{ env.pr_head_ref }} - persist-credentials: false - - - name: Redownload analysis results - uses: actions/github-script@v3.1.0 - with: - script: | - let artifacts = await github.actions.listWorkflowRunArtifacts({ - owner: context.repo.owner, - repo: context.repo.repo, - run_id: ${{github.event.workflow_run.id }}, - }); - let matchArtifact = artifacts.data.artifacts.filter((artifact) => { - return artifact.name == "printer-linter-result" - })[0]; - let download = await github.actions.downloadArtifact({ - owner: context.repo.owner, - repo: context.repo.repo, - artifact_id: matchArtifact.id, - archive_format: "zip", - }); - let fs = require("fs"); - fs.writeFileSync("${{github.workspace}}/printer-linter-result.zip", Buffer.from(download.data)); + const fs = require("fs"); + fs.writeFileSync("${{ github.workspace }}/printer-linter-result.zip", Buffer.from(download.data)); - name: Extract analysis results run: | mkdir printer-linter-result - unzip printer-linter-result.zip -d printer-linter-result + unzip -j printer-linter-result.zip -d printer-linter-result + + - name: Set PR details environment variables + uses: actions/github-script@v7 + with: + script: | + const assert = require("node:assert").strict; + const fs = require("fs"); + function exportVar(varName, fileName, regEx) { + const val = fs.readFileSync("${{ github.workspace }}/clang-tidy-result/" + fileName, { + encoding: "ascii" + }).trimEnd(); + assert.ok(regEx.test(val), "Invalid value format for " + varName); + core.exportVariable(varName, val); + } + exportVar("PR_ID", "pr-id.txt", /^[0-9]+$/); + exportVar("PR_HEAD_REPO", "pr-head-repo.txt", /^[-./0-9A-Z_a-z]+$/); + exportVar("PR_HEAD_SHA", "pr-head-sha.txt", /^[0-9A-Fa-f]+$/); + fs.access("${{ github.workspace }}/printer-linter-result/comment.md", fs.constants.F_OK, (err) => { + if (err) { + core.exportVariable("commentFileExists", "false"); + } else { + core.exportVariable("commentFileExists", "true"); + } + }); + + - uses: actions/checkout@v4 + with: + repository: ${{ env.PR_HEAD_REPO }} + ref: ${{ env.PR_HEAD_SHA }} + persist-credentials: false + + - name: Redownload analysis results + uses: actions/github-script@v7 + with: + script: | + const artifacts = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: ${{github.event.workflow_run.id }}, + }); + const matchArtifact = artifacts.data.artifacts.filter((artifact) => { + return artifact.name == "printer-linter-result" + })[0]; + const download = await github.rest.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: matchArtifact.id, + archive_format: "zip", + }); + const fs = require("fs"); + fs.writeFileSync("${{ github.workspace }}/printer-linter-result.zip", Buffer.from(download.data)); + + - name: Extract analysis results + run: | + mkdir printer-linter-result + unzip -j printer-linter-result.zip -d printer-linter-result - name: Run PR Comments if: env.commentFileExists == 'true' @@ -88,7 +103,7 @@ jobs: body-path: 'printer-linter-result/comment.md' - name: Run clang-tidy-pr-comments action - uses: platisd/clang-tidy-pr-comments@bc0bb7da034a8317d54e7fe1e819159002f4cc40 + uses: platisd/clang-tidy-pr-comments@v1 with: github_token: ${{ secrets.GITHUB_TOKEN }} clang_tidy_fixes: printer-linter-result/fixes.yml