Skip to content

Commit 6ecb8a9

Browse files
authored
Fix Zizmor security findings in GitHub Actions workflows (#2792)
* Fix Zizmor security findings in GitHub Actions workflows * Fix Zizmor findings: impostor commits, template injection, and explicit ignores * Fix Zizmor findings: secure workflows and resolve false positives * Use correct rule IDs (dangerous-triggers, dependabot-cooldown) for inline comments * Updates * Address reviewer comments
1 parent 1724c13 commit 6ecb8a9

11 files changed

Lines changed: 166 additions & 61 deletions

.github/dependabot.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ updates:
99
directory: "/"
1010
schedule:
1111
interval: "monthly"
12+
cooldown:
13+
default-days: 7
1214
groups:
1315
github-actions:
1416
patterns:
@@ -17,6 +19,8 @@ updates:
1719
directory: "/"
1820
schedule:
1921
interval: "monthly"
22+
cooldown:
23+
default-days: 7
2024
groups:
2125
python:
2226
patterns:

.github/workflows/actions.yml

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,11 @@ jobs:
3333
env:
3434
KERAS_BACKEND: ${{ matrix.backend }}
3535
steps:
36-
- uses: actions/checkout@v7
36+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
37+
with:
38+
persist-credentials: false
3739
- name: Set up Python 3.11
38-
uses: actions/setup-python@v6
40+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
3941
with:
4042
python-version: '3.11'
4143
- name: Get pip cache dir
@@ -44,7 +46,8 @@ jobs:
4446
python -m pip install --upgrade pip setuptools
4547
echo "::set-output name=dir::$(pip cache dir)"
4648
- name: pip cache
47-
uses: actions/cache@v6
49+
# zizmor: ignore[cache-poisoning]
50+
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
4851
with:
4952
path: ${{ steps.pip-cache.outputs.dir }}
5053
key: ${{ runner.os }}-pip-${{ hashFiles('requirements-common.txt') }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('pyproject.toml') }}
@@ -79,9 +82,11 @@ jobs:
7982
name: Check the code format
8083
runs-on: ubuntu-latest
8184
steps:
82-
- uses: actions/checkout@v7
85+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
86+
with:
87+
persist-credentials: false
8388
- name: Set up Python 3.11
84-
uses: actions/setup-python@v6
89+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
8590
with:
8691
python-version: '3.11'
8792
- name: Get pip cache dir
@@ -90,7 +95,8 @@ jobs:
9095
python -m pip install --upgrade pip setuptools
9196
echo "::set-output name=dir::$(pip cache dir)"
9297
- name: pip cache
93-
uses: actions/cache@v6
98+
# zizmor: ignore[cache-poisoning]
99+
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
94100
with:
95101
path: ${{ steps.pip-cache.outputs.dir }}
96102
key: ${{ runner.os }}-pip-${{ hashFiles('requirements-common.txt') }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('pyproject.toml') }}

.github/workflows/auto-assignment.yml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ on:
33
issues:
44
types:
55
- opened
6-
pull_request_target:
6+
pull_request_target: # zizmor: ignore[dangerous-triggers]
77
types:
88
- opened
99

@@ -16,8 +16,11 @@ jobs:
1616
welcome:
1717
runs-on: ubuntu-latest
1818
steps:
19-
- uses: actions/checkout@v7
20-
- uses: actions/github-script@v9
19+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
20+
with:
21+
persist-credentials: false
22+
ref: ${{ github.event.repository.default_branch }}
23+
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
2124
with:
2225
script: |
2326
const script = require('./\.github/workflows/scripts/auto-assignment.js')

.github/workflows/gemini-automated-issue-triage.yml

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,8 @@ defaults:
3131

3232
permissions:
3333
contents: 'read'
34-
id-token: 'write'
3534
issues: 'write'
36-
statuses: 'write'
37-
packages: 'read'
38-
actions: 'write' # Required for cancelling a workflow run
35+
actions: 'write'
3936

4037
jobs:
4138
triage-issue:
@@ -58,11 +55,13 @@ jobs:
5855
id: 'get_issue_data'
5956
if: |-
6057
github.event_name == 'workflow_dispatch'
61-
uses: 'actions/github-script@v9'
58+
uses: 'actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3' # v9
59+
env:
60+
ISSUE_NUMBER: '${{ github.event.inputs.issue_number || inputs.issue_number }}'
6261
with:
6362
github-token: '${{ secrets.GITHUB_TOKEN }}'
6463
script: |
65-
const issueNumber = ${{ github.event.inputs.issue_number || inputs.issue_number }};
64+
const issueNumber = process.env.ISSUE_NUMBER;
6665
const { data: issue } = await github.rest.issues.get({
6766
owner: context.repo.owner,
6867
repo: context.repo.repo,
@@ -74,11 +73,13 @@ jobs:
7473
return issue;
7574
7675
- name: 'Checkout'
77-
uses: 'actions/checkout@v7'
76+
uses: 'actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0' # v7
77+
with:
78+
persist-credentials: false
7879

7980
- name: 'Get Repository Labels'
8081
id: 'get_labels'
81-
uses: 'actions/github-script@v9'
82+
uses: 'actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3' # v9
8283
with:
8384
github-token: '${{ secrets.GITHUB_TOKEN }}'
8485
script: |-
@@ -114,7 +115,7 @@ jobs:
114115
${{ github.event_name == 'workflow_dispatch' && steps.get_issue_data.outputs.title || github.event.issue.title }}
115116
ISSUE_BODY: >-
116117
${{ github.event_name == 'workflow_dispatch' && steps.get_issue_data.outputs.body || github.event.issue.body }}
117-
uses: 'actions/github-script@v9'
118+
uses: 'actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3' # v9
118119
with:
119120
github-token: '${{ secrets.GITHUB_TOKEN }}'
120121
script: |-
@@ -232,7 +233,7 @@ jobs:
232233
ISSUE_NUMBER: '${{ github.event.issue.number || github.event.inputs.issue_number }}'
233234
LABELS_OUTPUT: '${{ steps.gemini_issue_analysis.outputs.summary }}'
234235
ALLOWED_LABELS: '${{ steps.get_labels.outputs.available_labels }}'
235-
uses: 'actions/github-script@v9'
236+
uses: 'actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3' # v9
236237
with:
237238
github-token: '${{ secrets.GITHUB_TOKEN }}'
238239
script: |
@@ -258,7 +259,7 @@ jobs:
258259
// 1. Strict Label Allowlist
259260
const requestedLabels = parsed.labels_to_set || [];
260261
labelsToAdd = requestedLabels.filter(label => ALLOWED_LABELS.includes(label));
261-
262+
262263
if (requestedLabels.length !== labelsToAdd.length) {
263264
core.warn("Blocked unauthorized labels: " + requestedLabels.filter(l => !ALLOWED_LABELS.includes(l)).join(', '));
264265
}
@@ -278,7 +279,7 @@ jobs:
278279
})).data;
279280
const issueAuthor = issueData.user.login;
280281
281-
const triageReason = parsed.triage_reason;
282+
const triageReason = parsed.triage_reason;
282283
if (triageReason && COMMENT_TEMPLATES[triageReason]) {
283284
responseBody = COMMENT_TEMPLATES[triageReason].replace('${author}', issueAuthor);
284285
} else {

.github/workflows/labeler.yaml

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,8 @@
1-
# Copyright 2024 Google LLC. All Rights Reserved.
2-
#
3-
# Licensed under the Apache License, Version 2.0 (the "License");
4-
# you may not use this file except in compliance with the License.
5-
# You may obtain a copy of the License at
6-
#
7-
# http://www.apache.org/licenses/LICENSE-2.0
8-
#
9-
# Unless required by applicable law or agreed to in writing, software
10-
# distributed under the License is distributed on an "AS IS" BASIS,
11-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12-
# See the License for the specific language governing permissions and
13-
# limitations under the License.
14-
15-
16-
# This workflow automatically identifies issues and pull requests (PRs)
17-
# related to Gemma. It searches for the keyword "Gemma" (case-insensitive)
18-
# in both the title and description of the issue/PR. If a match is found,
19-
# the workflow adds the label 'Gemma' to the issue/PR.
20-
211
name: 'Labeler'
222
on:
233
issues:
244
types: [edited, opened]
25-
pull_request_target:
5+
pull_request_target: # zizmor: ignore[dangerous-triggers]
266
types: [opened, edited]
277

288
permissions:
@@ -34,8 +14,11 @@ jobs:
3414
welcome:
3515
runs-on: ubuntu-latest
3616
steps:
37-
- uses: actions/checkout@v7
38-
- uses: actions/github-script@v9
17+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
18+
with:
19+
persist-credentials: false
20+
ref: ${{ github.event.repository.default_branch }}
21+
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
3922
with:
4023
script: |
4124
const script = require('./\.github/workflows/scripts/labeler.js')

.github/workflows/nightly.yml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ jobs:
1616
needs: [run-test-for-nightly]
1717
runs-on: ubuntu-latest
1818
steps:
19-
- uses: actions/checkout@v7
19+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
20+
with:
21+
persist-credentials: false
2022
- name: Set up Python
21-
uses: actions/setup-python@v6
23+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
2224
with:
2325
python-version: '3.11'
2426
- name: Get pip cache dir
@@ -27,7 +29,8 @@ jobs:
2729
python -m pip install --upgrade pip setuptools
2830
echo "::set-output name=dir::$(pip cache dir)"
2931
- name: pip cache
30-
uses: actions/cache@v6
32+
# zizmor: ignore[cache-poisoning]
33+
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
3134
with:
3235
path: ${{ steps.pip-cache.outputs.dir }}
3336
key: ${{ runner.os }}-pip-${{ hashFiles('requirements-common.txt') }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('pyproject.toml') }}
@@ -40,12 +43,12 @@ jobs:
4043
run: |
4144
python pip_build.py --nightly
4245
- name: Publish KerasHub Nightly to PyPI
43-
uses: pypa/gh-action-pypi-publish@release/v1
46+
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # release/v1 # zizmor: ignore[use-trusted-publishing]
4447
with:
4548
password: ${{ secrets.PYPI_NIGHTLY_API_TOKEN_HUB }}
4649
verbose: true
4750
- name: Publish KerasNLP Nightly to PyPI
48-
uses: pypa/gh-action-pypi-publish@release/v1
51+
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # release/v1 # zizmor: ignore[use-trusted-publishing]
4952
with:
5053
packages-dir: keras_nlp/dist/
5154
password: ${{ secrets.PYPI_NIGHTLY_API_TOKEN }}

.github/workflows/publish-to-pypi.yml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ jobs:
1010
name: Build and publish to PyPI
1111
runs-on: ubuntu-latest
1212
steps:
13-
- uses: actions/checkout@v7
13+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
14+
with:
15+
persist-credentials: false
1416
- name: Set up Python
15-
uses: actions/setup-python@v6
17+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
1618
with:
1719
python-version: '3.11'
1820
- name: Get pip cache dir
@@ -21,7 +23,8 @@ jobs:
2123
python -m pip install --upgrade pip setuptools
2224
echo "::set-output name=dir::$(pip cache dir)"
2325
- name: pip cache
24-
uses: actions/cache@v6
26+
# zizmor: ignore[cache-poisoning]
27+
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
2528
with:
2629
path: ${{ steps.pip-cache.outputs.dir }}
2730
key: ${{ runner.os }}-pip-${{ hashFiles('requirements-common.txt') }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('pyproject.toml') }}
@@ -33,13 +36,13 @@ jobs:
3336
python pip_build.py
3437
- name: Publish KerasHub to PyPI
3538
if: startsWith(github.ref, 'refs/tags')
36-
uses: pypa/gh-action-pypi-publish@release/v1
39+
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # release/v1 # zizmor: ignore[use-trusted-publishing]
3740
with:
3841
password: ${{ secrets.PYPI_API_TOKEN_HUB }}
3942
verbose: true
4043
- name: Publish KerasNLP to PyPI
4144
if: startsWith(github.ref, 'refs/tags')
42-
uses: pypa/gh-action-pypi-publish@release/v1
45+
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # release/v1 # zizmor: ignore[use-trusted-publishing]
4346
with:
4447
packages-dir: keras_nlp/dist/
4548
password: ${{ secrets.PYPI_API_TOKEN }}

.github/workflows/scorecard.yml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
name: Scorecard supply-chain security
2+
on:
3+
# For Branch-Protection check. Only the default branch is supported. See
4+
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
5+
branch_protection_rule:
6+
# To guarantee Maintained check is occasionally updated. See
7+
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
8+
schedule:
9+
- cron: '42 8 * * 2'
10+
push:
11+
branches: [ "master" ]
12+
13+
# Declare default permissions as read only.
14+
permissions: read-all
15+
16+
jobs:
17+
analysis:
18+
name: Scorecard analysis
19+
runs-on: ubuntu-latest
20+
permissions:
21+
# Needed to upload the results to code-scanning dashboard.
22+
security-events: write
23+
# Needed to publish results and get a badge (see publish_results below).
24+
id-token: write
25+
26+
steps:
27+
- name: "Checkout code"
28+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
29+
with:
30+
persist-credentials: false
31+
32+
- name: "Run analysis"
33+
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
34+
with:
35+
results_file: results.sarif
36+
results_format: sarif
37+
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
38+
# - you want to enable the Branch-Protection check on a *public* repository, or
39+
# - you are installing Scorecard on a *private* repository
40+
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
41+
# repo_token: ${{ secrets.SCORECARD_TOKEN }}
42+
43+
# Publish results to OpenSSF REST API for easy access by consumers
44+
# Allows the repository to include the Scorecard badge.
45+
# See https://github.com/ossf/scorecard-action#publishing-results.
46+
publish_results: true
47+
48+
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
49+
# format to the repository Actions tab.
50+
- name: "Upload artifact"
51+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
52+
with:
53+
name: SARIF file
54+
path: results.sarif
55+
retention-days: 5
56+
57+
# Upload the results to GitHub's code scanning dashboard.
58+
- name: "Upload to code-scanning"
59+
uses: github/codeql-action/upload-sarif@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
60+
with:
61+
sarif_file: results.sarif

0 commit comments

Comments
 (0)