Skip to content

Commit f2a78ac

Browse files
[SECURITY] minor security hardening of CI/CD (- WIP #485 -)
Changes in file .github/actions/check-control/action.yml: * security hardening of user-controlled inputs Changes in file .github/actions/run-minimal-acceptance-tests/action.yml: * security hardening of user-controlled inputs Changes in file .github/actions/setup-py-reqs/action.yml: * security hardening of user-controlled inputs Changes in file .github/actions/test-reporter-upload/action.yml: * security hardening of user-controlled inputs
1 parent d7be67e commit f2a78ac

File tree

4 files changed

+101
-16
lines changed

4 files changed

+101
-16
lines changed

.github/actions/check-control/action.yml

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,20 @@ runs:
109109
- id: output_sha
110110
if: ${{ !cancelled() }}
111111
shell: bash
112-
run: printf "sha=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_OUTPUT"
112+
run: |
113+
set -e # Exit immediately if any command fails
114+
sha_input='${{ inputs.sha }}'
115+
if [[ ! "$sha_input" =~ ^[0-9a-f]{40}$ ]]; then
116+
# check if value is non-sha valid
117+
output=$(git rev-parse --verify "$sha_input")
118+
if [[ -n "$output" ]]; then
119+
printf "::debug:: %s\n" "Valid branch name or sha provided: ${output}" ;
120+
else
121+
printf "::error title='Invalid':: %s\n" "Error: Invalid SHA format" >&2 ;
122+
exit 1 ;
123+
fi
124+
fi ;
125+
printf "sha=%s\n" $(git rev-parse --verify "$output") >> "$GITHUB_OUTPUT" ;
113126
- id: output_uuid
114127
if: ${{ !cancelled() && (inputs.check-id == '') }}
115128
shell: bash
@@ -152,16 +165,27 @@ runs:
152165
env:
153166
GH_TOKEN: ${{ inputs.token }}
154167
run: |
168+
printf "%s\n" "::group::validate-name"
169+
name_input='${{ inputs.name }}'
170+
sanitized_input_name=$(echo "$name_input" | tr -cd '[:alnum:] _')
171+
printf "::debug:: %s\n" "Will use name $sanitized_input_name" ;
172+
printf "%s\n" "::endgroup::"
173+
printf "%s\n" "::group::validate-title"
174+
title_input='${{ inputs.name }}'
175+
sanitized_input_title=$(echo "$title_input" | tr -cd '[:alnum:] _')
176+
printf "::debug:: %s\n" "Will use name $sanitized_input_title" ;
177+
sanitized_input_title_field=$(printf "%s%s" 'output[title]=' "$sanitized_input_title_field" ;)
178+
printf "%s\n" "::endgroup::"
155179
printf "%s\n" "::group::create-new-check"
156180
# GitHub CLI api
157181
# https://cli.github.com/manual/gh_api
158182
CHECK_ID=$(gh api --method POST -H "Accept: application/vnd.github+json" \
159183
/repos/reactive-firewall-org/multicast/check-runs \
160-
-f "name=${{ inputs.name }}" -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
161-
-f "status=${{ inputs.status }}" -f "external_id=${{ steps.output_uuid.outputs.uuid }}" \
184+
-f "name=$sanitized_input_name" -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
185+
-f 'status=${{ inputs.status }}' -f "external_id=${{ steps.output_uuid.outputs.uuid }}" \
162186
-f "started_at=${{ steps.output_date.outputs.check_date }}Z" \
163187
-f "details_url=${{ steps.output_check_details_url.outputs.details_url }}" \
164-
-f 'output[title]=${{ inputs.title }}' \
188+
-f "$sanitized_input_title_field" \
165189
-f 'output[summary]=' -f 'output[text]=' --jq '.id');
166190
printf "check_id=%s\n" "${CHECK_ID}" >> "$GITHUB_OUTPUT"
167191
printf "%s\n" "::endgroup::"
@@ -172,16 +196,27 @@ runs:
172196
env:
173197
GH_TOKEN: ${{ inputs.token }}
174198
run: |
199+
printf "%s\n" "::group::validate-name"
200+
name_input='${{ inputs.name }}'
201+
sanitized_input_name=$(echo "$name_input" | tr -cd '[:alnum:] _')
202+
printf "::debug:: %s\n" "Will use name $sanitized_input_name" ;
203+
printf "%s\n" "::endgroup::"
204+
printf "%s\n" "::group::validate-title"
205+
title_input='${{ inputs.name }}'
206+
sanitized_input_title=$(echo "$title_input" | tr -cd '[:alnum:] _')
207+
printf "::debug:: %s\n" "Will use name $sanitized_input_title" ;
208+
sanitized_input_title_field=$(printf "%s%s" 'output[title]=' "$sanitized_input_title_field" ;)
209+
printf "%s\n" "::endgroup::"
175210
printf "%s\n" "::group::update-new-check"
176211
# GitHub CLI api
177212
# https://cli.github.com/manual/gh_api
178213
CHECK_ID=$(gh api --method POST -H "Accept: application/vnd.github+json" \
179214
/repos/reactive-firewall-org/multicast/check-runs \
180-
-f "name=${{ inputs.name }}" -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
215+
-f "name=$sanitized_input_name" -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
181216
-f "status=in_progress" -f "external_id=${{ steps.output_uuid.outputs.uuid }}" \
182217
-f "started_at=${{ steps.output_date.outputs.check_date }}Z" \
183218
-f "details_url=${{ steps.output_check_details_url.outputs.details_url }}" \
184-
-f 'output[title]=${{ inputs.title }}' \
219+
-f "$sanitized_input_title_field" \
185220
-f 'output[summary]=Check is in progress.' -f 'output[text]=' --jq '.id');
186221
printf "check_id=%s\n" "${CHECK_ID}" >> "$GITHUB_OUTPUT"
187222
printf "%s\n" "::endgroup::"
@@ -216,15 +251,26 @@ runs:
216251
env:
217252
GH_TOKEN: ${{ inputs.token }}
218253
run: |
254+
printf "%s\n" "::group::validate-name"
255+
name_input='${{ inputs.name }}'
256+
sanitized_input_name=$(echo "$name_input" | tr -cd '[:alnum:] _')
257+
printf "::debug:: %s\n" "Will use name $sanitized_input_name" ;
258+
printf "%s\n" "::endgroup::"
259+
printf "%s\n" "::group::validate-title"
260+
title_input='${{ inputs.name }}'
261+
sanitized_input_title=$(echo "$title_input" | tr -cd '[:alnum:] _')
262+
printf "::debug:: %s\n" "Will use name $sanitized_input_title" ;
263+
sanitized_input_title_field=$(printf "%s%s" 'output[title]=' "$sanitized_input_title_field" ;)
264+
printf "%s\n" "::endgroup::"
219265
printf "%s\n" "::group::update-check"
220266
# GitHub CLI api
221267
# https://cli.github.com/manual/gh_api
222268
gh api --method PATCH -H "Accept: application/vnd.github+json" \
223269
/repos/reactive-firewall-org/multicast/check-runs/${{ steps.output_check_id.outputs.check_id }} \
224-
-f "name=${{ inputs.name }}" -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
270+
-f "name=$sanitized_input_name" -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
225271
-f "status=${{ inputs.status }}" \
226272
-f "details_url=${{ steps.output_check_details_url.outputs.details_url }}" \
227-
-f 'output[title]=${{ inputs.title }}' \
273+
-f "$sanitized_input_title_field" \
228274
-f 'output[summary]=${{ inputs.summary }}' -f 'output[text]=${{ inputs.text }}'
229275
printf "%s\n" "::endgroup::"
230276
- name: "Update Check"
@@ -234,16 +280,27 @@ runs:
234280
env:
235281
GH_TOKEN: ${{ inputs.token }}
236282
run: |
283+
printf "%s\n" "::group::validate-name"
284+
name_input='${{ inputs.name }}'
285+
sanitized_input_name=$(echo "$name_input" | tr -cd '[:alnum:] _')
286+
printf "::debug:: %s\n" "Will use name $sanitized_input_name" ;
287+
printf "%s\n" "::endgroup::"
288+
printf "%s\n" "::group::validate-title"
289+
title_input='${{ inputs.name }}'
290+
sanitized_input_title=$(echo "$title_input" | tr -cd '[:alnum:] _')
291+
printf "::debug:: %s\n" "Will use name $sanitized_input_title" ;
292+
sanitized_input_title_field=$(printf "%s%s" 'output[title]=' "$sanitized_input_title_field" ;)
293+
printf "%s\n" "::endgroup::"
237294
printf "%s\n" "::group::complete-check"
238295
# GitHub CLI api
239296
# https://cli.github.com/manual/gh_api
240297
gh api --method PATCH -H "Accept: application/vnd.github+json" \
241298
/repos/reactive-firewall-org/multicast/check-runs/${{ steps.output_check_id.outputs.check_id }} \
242-
-f "name=${{ inputs.name }}" -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
299+
-f "name=$sanitized_input_name" -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
243300
-f "status=completed" -f "conclusion=${{ inputs.conclusion }}" \
244301
-f "completed_at=${{ steps.output_date.outputs.check_date }}Z" \
245302
-f "details_url=${{ steps.output_check_details_url.outputs.details_url }}" \
246-
-f 'output[title]=${{ inputs.title }}' \
303+
-f "$sanitized_input_title_field" \
247304
-f 'output[summary]=${{ inputs.summary }}' -f 'output[text]=${{ inputs.text }}'
248305
printf "%s\n" "::endgroup::"
249306
- name: "Report outcome of checks API"

.github/actions/run-minimal-acceptance-tests/action.yml

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,23 @@ runs:
8080
steps:
8181
- name: "Calculate Commit SHA"
8282
id: output_sha
83+
if: ${{ !cancelled() }}
8384
shell: bash
8485
run: |
85-
printf "sha=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_OUTPUT"
86-
printf "BUILD_SHA=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_ENV"
86+
set -e # Exit immediately if any command fails
87+
sha_input='${{ inputs.sha }}'
88+
if [[ ! "$sha_input" =~ ^[0-9a-f]{40}$ ]]; then
89+
# check if value is non-sha valid
90+
output=$(git rev-parse --verify "$sha_input")
91+
if [[ -n "$output" ]]; then
92+
printf "::debug:: %s\n" "Valid branch name or sha provided: ${output}" ;
93+
else
94+
printf "::error title='Invalid':: %s\n" "Error: Invalid SHA format" >&2 ;
95+
exit 1 ;
96+
fi
97+
fi ;
98+
printf "sha=%s\n" $(git rev-parse --verify "$output") >> "$GITHUB_OUTPUT" ;
99+
printf "BUILD_SHA=%s\n" $(git rev-parse --verify "$output") >> "$GITHUB_ENV" ;
87100
- name: "Setup Python"
88101
id: output_python
89102
if: ${{ !cancelled() }}

.github/actions/setup-py-reqs/action.yml

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,23 @@ runs:
6565
steps:
6666
- name: "Calculate Commit SHA"
6767
id: output_sha
68+
if: ${{ !cancelled() }}
6869
shell: bash
6970
run: |
70-
printf "sha=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_OUTPUT"
71-
printf "BUILD_SHA=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_ENV"
71+
set -e # Exit immediately if any command fails
72+
sha_input='${{ inputs.sha }}'
73+
if [[ ! "$sha_input" =~ ^[0-9a-f]{40}$ ]]; then
74+
# check if value is non-sha valid
75+
output=$(git rev-parse --verify "$sha_input")
76+
if [[ -n "$output" ]]; then
77+
printf "::debug:: %s\n" "Valid branch name or sha provided: ${output}" ;
78+
else
79+
printf "::error title='Invalid':: %s\n" "Error: Invalid SHA format" >&2 ;
80+
exit 1 ;
81+
fi
82+
fi ;
83+
printf "sha=%s\n" $(git rev-parse --verify "$output") >> "$GITHUB_OUTPUT" ;
84+
printf "BUILD_SHA=%s\n" $(git rev-parse --verify "$output") >> "$GITHUB_ENV" ;
7285
- name: "Setup Python"
7386
id: output_python
7487
if: ${{ !cancelled() }}

.github/actions/test-reporter-upload/action.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,11 +345,13 @@ runs:
345345
env:
346346
COVERALLS_REPO_TOKEN: ${{ github.server_url == 'https://github.com' && inputs.coveralls-token || '' }}
347347
COVERALLS_TOOL: ${{ steps.output_upload_tools.outputs.coveralls_executable }}
348+
COVERALLS_SERVICE_JOB_ID: ${{ github.run_id }}
349+
COVERALLS_SERVICE_JOB_NUMBER: ${{ inputs.job_code }}
348350
run: |
349351
if [[ "${{ inputs.tests-outcome }}" == "success" ]] ; then
350-
${COVERALLS_TOOL} report ${COV_CORE_DATAFILE:-./coverage.xml} --base-path="${{ github.workspace }}" --service-job-id=${{ github.run_id }} --parallel --job-flag='${{ steps.output_os.outputs.os }}-${{ steps.output_python.outputs.python-version }}' --build-number=${{ inputs.job_code }} || exit 1 ;
352+
${COVERALLS_TOOL} report ${COV_CORE_DATAFILE:-./coverage.xml} --base-path="${{ github.workspace }}" --service-job-id=${COVERALLS_SERVICE_JOB_ID} --parallel --job-flag='${{ steps.output_os.outputs.os }}-${{ steps.output_python.outputs.python-version }}' --build-number=${COVERALLS_SERVICE_JOB_NUMBER} || exit 1 ;
351353
else
352-
${COVERALLS_TOOL} report ${COV_CORE_DATAFILE:-./coverage.xml} --base-path="${{ github.workspace }}" --allow-empty --service-job-id=${{ github.run_id }} --parallel --job-flag='${{ steps.output_os.outputs.os }}-${{ steps.output_python.outputs.python-version }}' --build-number=${{ inputs.job_code }} || exit 1 ;
354+
${COVERALLS_TOOL} report ${COV_CORE_DATAFILE:-./coverage.xml} --base-path="${{ github.workspace }}" --allow-empty --service-job-id=${COVERALLS_SERVICE_JOB_ID} --parallel --job-flag='${{ steps.output_os.outputs.os }}-${{ steps.output_python.outputs.python-version }}' --build-number=${COVERALLS_SERVICE_JOB_NUMBER} || exit 1 ;
353355
fi
354356
- name: "Evaluate Coverage Report Task"
355357
id: coverage_outcome

0 commit comments

Comments
 (0)