Skip to content

Commit fb1d072

Browse files
committed
Improve security of GitHub Actions workflows
Signed-off-by: Caleb Xu <caxu@redhat.com>
1 parent a8076bf commit fb1d072

File tree

9 files changed

+159
-64
lines changed

9 files changed

+159
-64
lines changed

.github/workflows/add-release-info-to-pyxis.yml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,16 @@ jobs:
3737
- name: Call Pyxis API
3838
run: |
3939
curl --fail-with-body \
40-
--cert '${{ env.CERT_FILE_LOCATION }}' \
41-
--key '${{ env.KEY_FILE_LOCATION }}' \
40+
--cert "${CERT_FILE_LOCATION}" \
41+
--key "${KEY_FILE_LOCATION}" \
4242
--pass '${{ secrets.certificatePassword }}' \
4343
-H 'Content-Type: application/json' \
44-
-d '{"commit":"${{ inputs.commit }}","enabled_for_testing":true,"name":"github.com/redhat-openshift-ecosystem/openshift-preflight","version":"${{ inputs.tag }}"}' \
44+
-d "${DATA_PAYLOAD}" \
4545
-X POST \
46-
'https://${{ inputs.host }}/v1/tools' | jq
46+
"${PYXIS_ENDPOINT}" | jq
47+
env:
48+
DATA_PAYLOAD: '{"commit":"${{ inputs.commit }}","enabled_for_testing":true,"name":"github.com/redhat-openshift-ecosystem/openshift-preflight","version":"${{ inputs.tag }}"}'
49+
PYXIS_ENDPOINT: 'https://${{ inputs.host }}/v1/tools'
4750

4851
- name: Cleanup
4952
if: always()

.github/workflows/build-main.yml

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,38 @@ on:
66

77
env:
88
IMAGE_NAME: preflight
9-
9+
1010
jobs:
1111
build-main:
12+
# TODO: Set explicit permissions for this job.
13+
# zizmor: ignore[excessive-permissions]
1214
name: Build and push main snapshot images
1315
strategy:
1416
matrix:
1517
architecture: [amd64,ppc64le,arm64,s390x]
1618
platform: [linux]
1719
runs-on: ubuntu-latest
1820
steps:
19-
- uses: actions/checkout@v5
21+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
22+
with:
23+
persist-credentials: false
2024
- name: Fetch latest release version
21-
uses: reloc8/action-latest-release-version@1.0.0
25+
uses: reloc8/action-latest-release-version@b8d6337f30390558e7874a044d6a3c1314314bab # 1.0.0
2226
id: fetch-latest-release
23-
- name: Set Env Tags
24-
run: echo RELEASE_TAG=${{ steps.fetch-latest-release.outputs.latest-release }} >> $GITHUB_ENV
25-
- name: set short sha
26-
run: echo SHA_SHORT=$(git rev-parse --short HEAD) >> $GITHUB_ENV
27+
28+
- name: Set release tag and short SHA
29+
run: |
30+
echo "RELEASE_TAG=${RELEASE_TAG}" >> "${GITHUB_ENV}"
31+
echo "SHA_SHORT=$(git rev-parse --short HEAD)" >> "${GITHUB_ENV}"
32+
env:
33+
RELEASE_TAG: ${{ steps.fetch-latest-release.outputs.latest-release }}
2734

2835
- name: Set up QEMU
29-
uses: docker/setup-qemu-action@v3
36+
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
3037

3138
- name: Build Image
3239
id: build-image
33-
uses: redhat-actions/buildah-build@v2
40+
uses: redhat-actions/buildah-build@7a95fa7ee0f02d552a32753e7414641a04307056 # v2.13
3441
with:
3542
image: ${{ secrets.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}
3643
tags: ${{ env.SHA_SHORT }}-${{ matrix.platform }}-${{ matrix.architecture }}
@@ -44,7 +51,7 @@ jobs:
4451
4552
- name: Run and Validate Image
4653
run: |
47-
if ! podman run --rm ${IMAGE_WITH_TAG} version; then
54+
if ! podman run --rm "${IMAGE_WITH_TAG}" version; then
4855
echo "Image validation failed. The 'podman run' command returned a non-zero exit code."
4956
exit 1
5057
fi
@@ -53,7 +60,7 @@ jobs:
5360

5461
- name: Push Image
5562
id: push-image
56-
uses: redhat-actions/push-to-registry@v2
63+
uses: redhat-actions/push-to-registry@5ed88d269cf581ea9ef6dd6806d01562096bee9c # v2.8
5764
with:
5865
image: ${{ env.IMAGE_NAME }}
5966
tags: ${{ env.SHA_SHORT }}-${{ matrix.platform }}-${{ matrix.architecture }}
@@ -62,22 +69,28 @@ jobs:
6269
password: ${{ secrets.REGISTRY_PASSWORD }}
6370

6471
- name: Print image url
65-
run: echo "Image pushed to ${{ steps.push-image.outputs.registry-paths }}"
72+
run: echo "Image pushed to ${REGISTRY_PATHS}"
73+
env:
74+
REGISTRY_PATHS: ${{ steps.push-image.outputs.registry-paths }}
6675

6776
outputs:
6877
imageName: ${{ env.IMAGE_NAME }}
6978
imageVersion: ${{ env.SHA_SHORT }}
7079

7180
build-coverage:
81+
# TODO: Set explicit permissions for this job.
82+
# zizmor: ignore[excessive-permissions]
7283
runs-on: ubuntu-latest
7384
steps:
74-
- uses: actions/checkout@v5
85+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
86+
with:
87+
persist-credentials: false
7588

7689
- name: Install system deps
7790
run: 'sudo apt update && sudo apt install -y libgpgme-dev libbtrfs-dev libdevmapper-dev'
7891

7992
- name: Set up Go
80-
uses: actions/setup-go@v6
93+
uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0
8194
with:
8295
go-version-file: go.mod
8396

@@ -94,12 +107,14 @@ jobs:
94107
run: make cover
95108

96109
- name: Coveralls
97-
uses: coverallsapp/github-action@v2
110+
uses: coverallsapp/github-action@648a8eb78e6d50909eff900e4ec85cab4524a45b # v2.3.6
98111
with:
99112
github-token: ${{ secrets.GITHUB_TOKEN }}
100113
file: coverage.out
101114

102115
build-multiarch:
116+
# TODO: Set explicit permissions for this job.
117+
# zizmor: ignore[excessive-permissions]
103118
needs: build-main
104119
uses: ./.github/workflows/build-multiarch.yml
105120
with:

.github/workflows/build-multiarch.yml

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,37 +55,49 @@ jobs:
5555

5656
# Authenticate to container image registry to push the image
5757
- name: Podman Login
58-
uses: redhat-actions/podman-login@v1
58+
uses: redhat-actions/podman-login@4934294ad0449894bcd1e9f191899d7292469603 # v1.7
5959
with:
6060
registry: ${{ secrets.registry }}
6161
username: ${{ secrets.user }}
6262
password: ${{ secrets.password }}
6363

6464
- name: Create and add to manifest
6565
run: |
66-
buildah manifest create ${{ inputs.name }}
67-
buildah manifest add ${{ inputs.name }} ${{ secrets.registry }}/${{ inputs.name }}:${{ inputs.tag }}-linux-amd64
68-
buildah manifest add ${{ inputs.name }} ${{ secrets.registry }}/${{ inputs.name }}:${{ inputs.tag }}-linux-ppc64le
69-
buildah manifest add ${{ inputs.name }} ${{ secrets.registry }}/${{ inputs.name }}:${{ inputs.tag }}-linux-arm64
70-
buildah manifest add ${{ inputs.name }} ${{ secrets.registry }}/${{ inputs.name }}:${{ inputs.tag }}-linux-s390x
66+
buildah manifest create "${INPUT_NAME}"
67+
buildah manifest add "${INPUT_NAME}" "${{ secrets.registry }}/${INPUT_NAME}:${INPUT_TAG}-linux-amd64"
68+
buildah manifest add "${INPUT_NAME}" "${{ secrets.registry }}/${INPUT_NAME}:${INPUT_TAG}-linux-ppc64le"
69+
buildah manifest add "${INPUT_NAME}" "${{ secrets.registry }}/${INPUT_NAME}:${INPUT_TAG}-linux-arm64"
70+
buildah manifest add "${INPUT_NAME}" "${{ secrets.registry }}/${INPUT_NAME}:${INPUT_TAG}-linux-s390x"
71+
env:
72+
INPUT_NAME: ${{ inputs.name }}
73+
INPUT_TAG: ${{ inputs.tag }}
7174

7275
- name: Push manifest
7376
id: push-manifest
7477
run: |
75-
podman manifest push --digestfile imagedigest ${{ inputs.name }} ${{ secrets.registry }}/${{ inputs.name }}:${{ inputs.tag }} --all
76-
echo "digest=$(cat imagedigest)" | tee -a $GITHUB_OUTPUT
78+
podman manifest push --digestfile imagedigest "${INPUT_NAME}" "${{ secrets.registry }}/${INPUT_NAME}:${INPUT_TAG}" --all
79+
echo "digest=$(cat imagedigest)" | tee -a "${GITHUB_OUTPUT}"
80+
env:
81+
INPUT_NAME: ${{ inputs.name }}
82+
INPUT_TAG: ${{ inputs.tag }}
7783

7884
- name: Sign the published manifest
7985
# only sign if release is published, not for ghactions branch push
8086
# which is used for testing and development.
8187
if: ${{ inputs.sign == true && github.event.release && github.event.action == 'published' }}
8288
run: |
83-
cosign sign --yes --recursive ${{ secrets.registry }}/${{ inputs.name }}@${{ steps.push-manifest.outputs.digest }}
89+
cosign sign --yes --recursive "${{ secrets.registry }}/${INPUT_NAME}@${DIGEST}"
90+
env:
91+
DIGEST: ${{ steps.push-manifest.outputs.digest }}
92+
INPUT_NAME: ${{ inputs.name }}
8493

8594
- name: Verify the image signature
8695
if: ${{ inputs.sign == true && github.event.release && github.event.action == 'published' }}
8796
run: |
8897
cosign verify \
89-
--certificate-identity https://github.com/${{ github.repository }}/.github/workflows/build-multiarch.yml@refs/tags/${{ inputs.tag }} \
98+
--certificate-identity "https://github.com/${{ github.repository }}/.github/workflows/build-multiarch.yml@refs/tags/${INPUT_TAG}" \
9099
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
91-
${{ secrets.registry }}/${{ inputs.name }}:${{ inputs.tag }}
100+
"${{ secrets.registry }}/${INPUT_NAME}:${INPUT_TAG}"
101+
env:
102+
INPUT_NAME: ${{ inputs.name }}
103+
INPUT_TAG: ${{ inputs.tag }}

.github/workflows/build-release.yml

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,28 @@ env:
1212

1313
jobs:
1414
build-release:
15+
# TODO: Set explicit permissions for this job.
16+
# zizmor: ignore[excessive-permissions]
1517
name: Build and push tag images
1618
strategy:
1719
matrix:
1820
architecture: [amd64,ppc64le,arm64,s390x]
1921
platform: [linux]
2022
runs-on: ubuntu-latest
2123
steps:
22-
- uses: actions/checkout@v5
24+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
25+
with:
26+
persist-credentials: false
27+
2328
- name: Set Env Tags
24-
run: echo RELEASE_TAG=$(echo $GITHUB_REF | cut -d '/' -f 3) >> $GITHUB_ENV
29+
run: echo "RELEASE_TAG=$(echo "${GITHUB_REF}" | cut -d '/' -f 3)" >> "${GITHUB_ENV}"
2530

2631
- name: Set up QEMU
27-
uses: docker/setup-qemu-action@v3
32+
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
2833

2934
- name: Build Image
3035
id: build-image
31-
uses: redhat-actions/buildah-build@v2
36+
uses: redhat-actions/buildah-build@7a95fa7ee0f02d552a32753e7414641a04307056 # v2.13
3237
with:
3338
image: ${{ secrets.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}
3439
tags: ${{ env.RELEASE_TAG }}-${{ matrix.platform }}-${{ matrix.architecture }}
@@ -41,7 +46,7 @@ jobs:
4146
4247
- name: Push Image
4348
id: push-image
44-
uses: redhat-actions/push-to-registry@v2
49+
uses: redhat-actions/push-to-registry@5ed88d269cf581ea9ef6dd6806d01562096bee9c # v2.8
4550
with:
4651
image: ${{ env.IMAGE_NAME }}
4752
tags: ${{ env.RELEASE_TAG }}-${{ matrix.platform }}-${{ matrix.architecture }}
@@ -50,7 +55,9 @@ jobs:
5055
password: ${{ secrets.REGISTRY_PASSWORD }}
5156

5257
- name: Print image url
53-
run: echo "Image pushed to ${{ steps.push-image.outputs.registry-paths }}"
58+
run: echo "Image pushed to ${REGISTRY_PATHS}"
59+
env:
60+
REGISTRY_PATHS: ${{ steps.push-image.outputs.registry-paths }}
5461

5562
outputs:
5663
imageName: ${{ env.IMAGE_NAME }}
@@ -78,6 +85,8 @@ jobs:
7885
token: ${{ secrets.GITHUB_TOKEN }}
7986

8087
extract-assets:
88+
# TODO: Set explicit permissions for this job.
89+
# zizmor: ignore[excessive-permissions]
8190
needs: build-release
8291
uses: ./.github/workflows/release-artifacts.yml
8392
with:
@@ -90,6 +99,8 @@ jobs:
9099
token: ${{ secrets.GITHUB_TOKEN }}
91100

92101
add-release-info-to-pyxis:
102+
# TODO: Set explicit permissions for this job.
103+
# zizmor: ignore[excessive-permissions]
93104
needs: [build-release, extract-assets]
94105
uses: ./.github/workflows/add-release-info-to-pyxis.yml
95106
if: "!github.event.release.prerelease"
@@ -103,6 +114,8 @@ jobs:
103114
certificatePassword: ${{ secrets.PREFLIGHT_RELEASE_PASSWORD }}
104115

105116
copy-to-rhisv:
117+
# TODO: Set explicit permissions for this job.
118+
# zizmor: ignore[excessive-permissions]
106119
needs: [build-release, build-multiarch]
107120
uses: ./.github/workflows/copy-to-rhisv.yml
108121
with:
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: Analyze GitHub Actions security
2+
3+
on:
4+
push:
5+
branches: ["main"]
6+
pull_request:
7+
branches: ["**"]
8+
9+
permissions: {}
10+
11+
jobs:
12+
check-actions:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Checkout repository
16+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
17+
with:
18+
persist-credentials: false
19+
20+
- name: Run actionlint
21+
uses: docker://rhysd/actionlint@sha256:96d4a8c87dbbfb3bdd324f8fdc285fc3df5261e2decc619a4dd7e8ee52bbfd46 # 1.7.8
22+
with:
23+
args: -color
24+
25+
- name: Run zizmor
26+
uses: zizmorcore/zizmor-action@e673c3917a1aef3c65c972347ed84ccd013ecda4 # v0.2.0
27+
with:
28+
advanced-security: false

.github/workflows/code-review.yml

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
name: Gemini AI Code Review
22

3-
on:
3+
# pull_request_target is needed to access the Gemini key and modify (set/remove labels, comment on)
4+
# the pull request.
5+
on: # zizmor: ignore[dangerous-triggers]
46
pull_request_target:
57
types: [opened, synchronize, reopened, labeled]
68

9+
# TODO: Assign permissions in individual jobs rather than at the
10+
# workflow level to avoid blindly handing out `pull-requests: write`
11+
# at the workflow level to all jobs (particularly if new jobs are
12+
# added in this workflow in the future).
713
permissions:
814
contents: read
9-
pull-requests: write
15+
pull-requests: write # zizmor: ignore[excessive-permissions]
1016

1117
concurrency:
1218
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
@@ -21,26 +27,30 @@ jobs:
2127
pull-requests: write
2228
steps:
2329
- name: Checkout repository
24-
uses: actions/checkout@v5
30+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
31+
with:
32+
persist-credentials: false
33+
2534
- name: Handle review label
2635
id: prep
2736
env:
2837
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2938
PR_NUMBER: ${{ github.event.pull_request.number }}
39+
LABEL_JSON: ${{ toJSON(github.event.pull_request.labels.*.name) }}
40+
EVENT_ACTION: ${{ github.event.action }}
3041
run: |
31-
HAS_LABEL=$(echo '${{ toJSON(github.event.pull_request.labels.*.name) }}' | jq 'any(. == "gemini-review")')
32-
EVENT_ACTION="${{ github.event.action }}"
42+
HAS_LABEL=$(jq -n 'env.LABEL_JSON | fromjson | any(. == "gemini-review")')
3343
34-
if [[ "$HAS_LABEL" == "true" && "$EVENT_ACTION" != "labeled" ]]; then
44+
if [[ "${HAS_LABEL}" == "true" && "${EVENT_ACTION}" != "labeled" ]]; then
3545
echo "gemini-review label found on a '${EVENT_ACTION}' event. Removing label and skipping review."
36-
gh pr edit "$PR_NUMBER" --remove-label "gemini-review"
37-
echo "should_run_review=false" >> $GITHUB_OUTPUT
38-
elif [[ "$HAS_LABEL" == "true" ]]; then
46+
gh pr edit "${PR_NUMBER}" --remove-label "gemini-review"
47+
echo "should_run_review=false" >> "${GITHUB_OUTPUT}"
48+
elif [[ "${HAS_LABEL}" == "true" ]]; then
3949
echo "gemini-review label found. Proceeding with review."
40-
echo "should_run_review=true" >> $GITHUB_OUTPUT
50+
echo "should_run_review=true" >> "${GITHUB_OUTPUT}"
4151
else
4252
echo "gemini-review label not found. Skipping review."
43-
echo "should_run_review=false" >> $GITHUB_OUTPUT
53+
echo "should_run_review=false" >> "${GITHUB_OUTPUT}"
4454
fi
4555
4656
gemini-code-review:
@@ -49,13 +59,14 @@ jobs:
4959
if: needs.handle-label.outputs.should_run_review == 'true'
5060
steps:
5161
- name: Checkout repository
52-
uses: actions/checkout@v5
62+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
5363
with:
5464
ref: refs/pull/${{ github.event.pull_request.number }}/merge
65+
persist-credentials: false
5566
fetch-depth: 0
5667

5768
- name: Gemini AI Code Review
58-
uses: sshnaidm/gemini-code-review-action@d4ccdaf0e2cad5cb79f80f6db07857c0e7fff28f
69+
uses: sshnaidm/gemini-code-review-action@d4ccdaf0e2cad5cb79f80f6db07857c0e7fff28f # v1
5970
with:
6071
gemini-key: ${{ secrets.GEMINI_API_KEY }}
6172
model: 'gemini-2.5-flash'

0 commit comments

Comments
 (0)