From 1b0d8712aeceb23b0f0e1fd84fa7cafe2f2c0657 Mon Sep 17 00:00:00 2001 From: Tomasz Leman Date: Mon, 23 Mar 2026 13:59:00 +0100 Subject: [PATCH 1/3] workflows: restrict GITHUB_TOKEN permissions to contents: read Add explicit top-level permissions block to all GitHub Actions workflow files, limiting the GITHUB_TOKEN to the minimum required scope: read. Why this is recommended: GitHub Actions grants the GITHUB_TOKEN broad default permissions (read/write on most scopes) unless explicitly restricted. The GitHub security hardening guide and CodeQL (actions/missing-workflow-permissions rule) recommend always declaring an explicit permissions block to enforce the principle of least privilege. Threats prevented: - Compromised or malicious third-party actions (supply chain attacks) cannot use the implicit GITHUB_TOKEN to write to the repository, create releases, modify issues/PRs, upload packages, or affect deployments - even if such an action is injected into the workflow. - If a vulnerability in a workflow step allows code execution (e.g. via script injection through PR title/body), the attacker's ability to abuse the token is limited to read-only repository access. - Reduces blast radius of any accidental or intentional misuse of the token across all CI jobs. Affected workflows: build_all, codestyle, daily-tests, ipc_fuzzer, llext, pull-request, repro-build, rimage, sof-docs, sparse-zephyr, testbench, tools, unit-tests, zephyr. Signed-off-by: Tomasz Leman --- .github/workflows/build_all.yml | 3 +++ .github/workflows/codestyle.yml | 3 +++ .github/workflows/daily-tests.yml | 3 +++ .github/workflows/ipc_fuzzer.yml | 3 +++ .github/workflows/llext.yml | 3 +++ .github/workflows/pull-request.yml | 3 +++ .github/workflows/repro-build.yml | 3 +++ .github/workflows/rimage.yml | 3 +++ .github/workflows/sof-docs.yml | 3 +++ .github/workflows/sparse-zephyr.yml | 3 +++ .github/workflows/testbench.yml | 3 +++ .github/workflows/tools.yml | 3 +++ .github/workflows/unit-tests.yml | 3 +++ .github/workflows/zephyr.yml | 3 +++ 14 files changed, 42 insertions(+) diff --git a/.github/workflows/build_all.yml b/.github/workflows/build_all.yml index fba00fbb61f2..19fee4a98ca4 100644 --- a/.github/workflows/build_all.yml +++ b/.github/workflows/build_all.yml @@ -8,6 +8,9 @@ name: Build test all components # yamllint disable-line rule:truthy on: [pull_request, workflow_dispatch, workflow_call] +permissions: + contents: read + jobs: stub-build: diff --git a/.github/workflows/codestyle.yml b/.github/workflows/codestyle.yml index 63a076fc086a..02bb2084c12d 100644 --- a/.github/workflows/codestyle.yml +++ b/.github/workflows/codestyle.yml @@ -14,6 +14,9 @@ name: codestyle # yamllint disable-line rule:truthy on: [pull_request, workflow_call, workflow_dispatch] +permissions: + contents: read + jobs: checkpatch: runs-on: ubuntu-22.04 diff --git a/.github/workflows/daily-tests.yml b/.github/workflows/daily-tests.yml index 40b90b01fe8e..139c946c3d84 100644 --- a/.github/workflows/daily-tests.yml +++ b/.github/workflows/daily-tests.yml @@ -13,6 +13,9 @@ on: # Allows you to run this workflow manually from the Actions tab workflow_dispatch: +permissions: + contents: read + jobs: # Keep in .yml alphabetical order diff --git a/.github/workflows/ipc_fuzzer.yml b/.github/workflows/ipc_fuzzer.yml index 9b21ca03041b..755dbf4b5d9b 100644 --- a/.github/workflows/ipc_fuzzer.yml +++ b/.github/workflows/ipc_fuzzer.yml @@ -22,6 +22,9 @@ on: pull_request: # TODO: can we provide a default inputs here too? +permissions: + contents: read + jobs: simple-IPC-fuzz_sh: diff --git a/.github/workflows/llext.yml b/.github/workflows/llext.yml index a2888b75f2f4..2958566dc7f1 100644 --- a/.github/workflows/llext.yml +++ b/.github/workflows/llext.yml @@ -11,6 +11,9 @@ defaults: run: shell: bash +permissions: + contents: read + jobs: build: runs-on: ubuntu-22.04 diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 886d1b328ba7..f4091fdba2f4 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -31,6 +31,9 @@ on: # Allows to call this forkflow from other workflows workflow_call: +permissions: + contents: read + jobs: doxygen: diff --git a/.github/workflows/repro-build.yml b/.github/workflows/repro-build.yml index 034ae4ac286a..56746809f993 100644 --- a/.github/workflows/repro-build.yml +++ b/.github/workflows/repro-build.yml @@ -14,6 +14,9 @@ name: Reproducible builds # yamllint disable-line rule:truthy on: [pull_request, workflow_dispatch, workflow_call] +permissions: + contents: read + jobs: main: runs-on: ubuntu-22.04 diff --git a/.github/workflows/rimage.yml b/.github/workflows/rimage.yml index b6e66c23c449..02800e45ded5 100644 --- a/.github/workflows/rimage.yml +++ b/.github/workflows/rimage.yml @@ -22,6 +22,9 @@ on: paths: - tools/rimage/** +permissions: + contents: read + jobs: # Basic build test diff --git a/.github/workflows/sof-docs.yml b/.github/workflows/sof-docs.yml index 5920c51aaad5..63af4acfc714 100644 --- a/.github/workflows/sof-docs.yml +++ b/.github/workflows/sof-docs.yml @@ -17,6 +17,9 @@ on: # Allows to call this forkflow from other workflows workflow_call: +permissions: + contents: read + jobs: # This is unfortunately a mix of sof-docs/.github/ + pull-request.yml#doxygen diff --git a/.github/workflows/sparse-zephyr.yml b/.github/workflows/sparse-zephyr.yml index e66856691dcb..02777f940fae 100644 --- a/.github/workflows/sparse-zephyr.yml +++ b/.github/workflows/sparse-zephyr.yml @@ -11,6 +11,9 @@ defaults: run: shell: bash +permissions: + contents: read + jobs: # As of sparse commit ce1a6720f69e / Sept 2022, the exit status of # sparse.c is an unusable mess and always zero in practice. Moreover diff --git a/.github/workflows/testbench.yml b/.github/workflows/testbench.yml index c6d16920abd0..290fe8e56dee 100644 --- a/.github/workflows/testbench.yml +++ b/.github/workflows/testbench.yml @@ -28,6 +28,9 @@ on: workflow_dispatch: workflow_call: +permissions: + contents: read + jobs: build-and-test: runs-on: ubuntu-24.04 diff --git a/.github/workflows/tools.yml b/.github/workflows/tools.yml index 9c8197a6cbcc..108a3015d16a 100644 --- a/.github/workflows/tools.yml +++ b/.github/workflows/tools.yml @@ -7,6 +7,9 @@ name: User space tools/ directory # yamllint disable-line rule:truthy on: [pull_request, workflow_dispatch, workflow_call] +permissions: + contents: read + jobs: # This is not the same as building every ./build-tools.sh option. top-level_default_CMake_target_ALL: diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 391807f6a336..de8577e87171 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -10,6 +10,9 @@ name: Unit tests # yamllint disable-line rule:truthy on: [pull_request, workflow_dispatch, workflow_call] +permissions: + contents: read + jobs: cmocka_utests: runs-on: ubuntu-latest diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index 06b6cc3d7ee9..fa8c0e4cdf8e 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -14,6 +14,9 @@ concurrency: group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.head_ref || github.ref }} cancel-in-progress: true +permissions: + contents: read + jobs: manifest-check: runs-on: ubuntu-latest From 6051c9bae45e22b5fbd1400afe151ee7e1f019d2 Mon Sep 17 00:00:00 2001 From: Tomasz Leman Date: Mon, 23 Mar 2026 13:59:39 +0100 Subject: [PATCH 2/3] workflows: pin msys2/setup-msys2 action to a specific commit hash Replace the mutable tag reference 'msys2/setup-msys2@v2' with a pinned commit SHA in zephyr.yml. Why this is recommended: Tags in GitHub Actions are mutable - a repository owner can silently move a tag (e.g. 'v2') to point to a different, potentially malicious commit at any time without the consuming workflow receiving any notification. Pinning to a full commit SHA ensures the exact code that was reviewed is what runs in CI, making the reference immutable. Threats prevented: - Supply chain attacks: a compromised or malicious actor with write access to the msys2/setup-msys2 repository cannot push new code under the existing 'v2' tag and have it automatically executed in our CI without an explicit code review and hash update on our side. - Dependency confusion: prevents accidental or forced resolution to an unintended version of the action. The comment '# v2' is retained to make it clear which upstream release the hash corresponds to, aiding future maintenance when a deliberate update is needed. Signed-off-by: Tomasz Leman --- .github/workflows/zephyr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index fa8c0e4cdf8e..1e2728f3c0fa 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -398,7 +398,7 @@ jobs: # https://github.com/actions/runner-images/blob/win22/20230918.1/images/win/Windows2022-Readme.md # Is it not good enough? Maybe it could save 20-30s. - name: Initialize MSYS2 - uses: msys2/setup-msys2@v2 + uses: msys2/setup-msys2@cafece8e6baf9247cf9b1bf95097b0b983cc558d # v2 with: msystem: MSYS install: gcc openssl-devel From ebafac15946f45d05923ac1a3156f2dfce597003 Mon Sep 17 00:00:00 2001 From: Tomasz Leman Date: Mon, 23 Mar 2026 14:44:49 +0100 Subject: [PATCH 3/3] workflows: add CodeQL analysis workflow for GitHub Actions Introduce a new CodeQL scanning workflow (.github/workflows/codeql.yml) that statically analyzes all GitHub Actions workflow files in the repository on every pull request targeting main. What it does: - Runs CodeQL with the 'actions' language target, which scans .yml workflow files for security misconfigurations such as missing permissions, unpinned action tags, script injection, and other GitHub Actions-specific vulnerabilities. - Uploads SARIF results to the GitHub Security tab, making findings visible directly in pull requests and the repository's security overview. - Uses concurrency groups to cancel superseded runs on the same branch, avoiding wasted CI time. Security posture of the workflow itself: - Top-level permissions default to contents: read. - The analyze job explicitly declares the minimum required scopes: actions: read (to inspect workflow metadata) and contents: read (to checkout the repository). - All third-party actions are pinned to immutable commit SHAs to prevent supply chain attacks: * actions/checkout @ de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 * codeql-action/init @ 0d579ffd059c29b07949a3cce3983f0780820c98 # v4 * codeql-action/analyze @ 0d579ffd059c29b07949a3cce3983f0780820c98 # v4 - persist-credentials: false is set on checkout to avoid leaking the GITHUB_TOKEN to subsequent steps. Signed-off-by: Tomasz Leman --- .github/workflows/codeql.yml | 50 ++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 000000000000..4f7c29d6c831 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,50 @@ +--- +name: "CodeQL Analysis" +# yamllint disable-line rule:truthy +on: + pull_request: + branches: + - 'main' + +permissions: + contents: read + +# Specifies group name that stops previous workflows if the name matches +concurrency: + group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.head_ref || github.ref }} + cancel-in-progress: true + +jobs: + analyze: + name: Analyze GitHub Actions Workflows + runs-on: ubuntu-latest + permissions: + security-events: write # Required to upload SARIF results + actions: read # Required to read workflow information + contents: read # Required to checkout repository + + strategy: + fail-fast: false + matrix: + language: ['actions'] # Analyze GitHub Actions workflows + + steps: + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Initialize CodeQL + uses: github/codeql-action/init@0d579ffd059c29b07949a3cce3983f0780820c98 # v4 + with: + languages: ${{ matrix.language }} + # Optional: Specify custom queries + # queries: security-extended,security-and-quality + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@0d579ffd059c29b07949a3cce3983f0780820c98 # v4 + with: + category: "/language:${{ matrix.language }}" + upload: true + # Upload SARIF results to GitHub Security tab + output: sarif-results