@@ -110,19 +110,76 @@ runs:
110110 if : ${{ !cancelled() }}
111111 shell : bash
112112 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}" ;
113+ set -euo pipefail
114+
115+ raw_input='${{ inputs.sha }}'
116+
117+ # Reject NUL or newline immediately
118+ if printf '%s' "$raw_input" | grep -q $'[\\x00\\n\\r]'; then
119+ printf "::error title='Invalid':: %s\n" "Error: input contains disallowed control characters" >&2
120+ exit 1
121+ fi
122+
123+ # Strip one level of surrounding quotes and trim whitespace
124+ normalize() {
125+ local s="$1"
126+ s="${s#"${s%%[![:space:]]*}"}"
127+ s="${s%"${s##*[![:space:]]}"}"
128+ if [[ (${s:0:1} == "'" && ${s: -1} == "'") || (${s:0:1} == '"' && ${s: -1} == '"') ]]; then
129+ s="${s:1:-1}"
130+ fi
131+ printf '%s' "$s"
132+ }
133+ input="$(normalize "$raw_input")"
134+
135+ # Reject inputs starting with '-' (options)
136+ if [[ "${input:0:1}" == "-" ]]; then
137+ printf "::error title='Invalid':: %s\n" "Error: input may not start with '-'" >&2
138+ exit 1
139+ fi
140+
141+ # Reject any characters that enable ref modifiers or ambiguity
142+ if [[ "$input" =~ [[:space:]~^\{\}:@\*\?$$$$] ]]; then
143+ printf "::error title='Invalid':: %s\n" "Error: input contains disallowed characters" >&2
144+ exit 1
145+ fi
146+
147+ # If it's a 40-char SHA, accept directly
148+ if [[ "$input" =~ ^[0-9a-f]{40}$ ]]; then
149+ resolved_sha="$input"
150+ else
151+ # Try explicit namespaces in order: full refs, refs/heads/, refs/tags/, then bare branch/tag
152+ resolved_sha=""
153+ # 1) If input is a full ref path starting with refs/, resolve only that
154+ if [[ "$input" == refs/* ]]; then
155+ if git rev-parse --verify "$input" >/dev/null 2>&1; then
156+ resolved_sha="$(git rev-parse --verify "$input")"
157+ else
158+ printf "::error title='Invalid':: %s\n" "Error: ref not found: $input" >&2
159+ exit 1
160+ fi
120161 else
121- printf "::error title='Invalid':: %s\n" "Error: Invalid SHA format" >&2 ;
122- exit 1 ;
162+ # 2) Try refs/heads/<input>
163+ if git rev-parse --verify "refs/heads/$input" >/dev/null 2>&1; then
164+ resolved_sha="$(git rev-parse --verify "refs/heads/$input")"
165+ # 3) Try refs/tags/<input>
166+ elif git rev-parse --verify "refs/tags/$input" >/dev/null 2>&1; then
167+ resolved_sha="$(git rev-parse --verify "refs/tags/$input")"
168+ else
169+ printf "::error title='Invalid':: %s\n" "Error: no matching branch or tag found for: $input" >&2
170+ exit 1
171+ fi
123172 fi
124- fi ;
125- printf "sha=%s\n" $(git rev-parse --verify "$output") >> "$GITHUB_OUTPUT" ;
173+ fi
174+
175+ # Ensure final resolved value is a full 40-char commit SHA
176+ if [[ ! "$resolved_sha" =~ ^[0-9a-f]{40}$ ]]; then
177+ printf "::error title='Invalid':: %s\n" "Error: resolved value is not a full commit SHA" >&2
178+ exit 1
179+ fi
180+
181+ printf "sha=%s\n" "$resolved_sha" >> "$GITHUB_OUTPUT"
182+
126183 - id : output_uuid
127184 if : ${{ !cancelled() && (inputs.check-id == '') }}
128185 shell : bash
@@ -167,21 +224,19 @@ runs:
167224 run : |
168225 printf "%s\n" "::group::validate-name"
169226 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" ;
227+ printf "::debug:: %s\n" "Will use name $name_input" ;
172228 printf "%s\n" "::endgroup::"
173229 printf "%s\n" "::group::validate-title"
174230 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" ;)
231+ printf "::debug:: %s\n" "Will use name $title_input" ;
232+ sanitized_input_title_field=$(printf "%s%s" 'output[title]=' "$title_input" ;)
178233 printf "%s\n" "::endgroup::"
179234 printf "%s\n" "::group::create-new-check"
180235 # GitHub CLI api
181236 # https://cli.github.com/manual/gh_api
182237 CHECK_ID=$(gh api --method POST -H "Accept: application/vnd.github+json" \
183238 /repos/reactive-firewall-org/multicast/check-runs \
184- -f "name=$sanitized_input_name " -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
239+ -f "name=$name_input " -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
185240 -f 'status=${{ inputs.status }}' -f "external_id=${{ steps.output_uuid.outputs.uuid }}" \
186241 -f "started_at=${{ steps.output_date.outputs.check_date }}Z" \
187242 -f "details_url=${{ steps.output_check_details_url.outputs.details_url }}" \
@@ -198,21 +253,19 @@ runs:
198253 run : |
199254 printf "%s\n" "::group::validate-name"
200255 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" ;
256+ printf "::debug:: %s\n" "Will use name $name_input" ;
203257 printf "%s\n" "::endgroup::"
204258 printf "%s\n" "::group::validate-title"
205259 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" ;)
260+ printf "::debug:: %s\n" "Will use name $title_input" ;
261+ sanitized_input_title_field=$(printf "%s%s" 'output[title]=' "$title_input" ;)
209262 printf "%s\n" "::endgroup::"
210263 printf "%s\n" "::group::update-new-check"
211264 # GitHub CLI api
212265 # https://cli.github.com/manual/gh_api
213266 CHECK_ID=$(gh api --method POST -H "Accept: application/vnd.github+json" \
214267 /repos/reactive-firewall-org/multicast/check-runs \
215- -f "name=$sanitized_input_name " -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
268+ -f "name=$input_name " -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
216269 -f "status=in_progress" -f "external_id=${{ steps.output_uuid.outputs.uuid }}" \
217270 -f "started_at=${{ steps.output_date.outputs.check_date }}Z" \
218271 -f "details_url=${{ steps.output_check_details_url.outputs.details_url }}" \
@@ -253,21 +306,19 @@ runs:
253306 run : |
254307 printf "%s\n" "::group::validate-name"
255308 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" ;
309+ printf "::debug:: %s\n" "Will use name $name_input" ;
258310 printf "%s\n" "::endgroup::"
259311 printf "%s\n" "::group::validate-title"
260312 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" ;)
313+ printf "::debug:: %s\n" "Will use name $title_input" ;
314+ sanitized_input_title_field=$(printf "%s%s" 'output[title]=' "$title_input" ;)
264315 printf "%s\n" "::endgroup::"
265316 printf "%s\n" "::group::update-check"
266317 # GitHub CLI api
267318 # https://cli.github.com/manual/gh_api
268319 gh api --method PATCH -H "Accept: application/vnd.github+json" \
269320 /repos/reactive-firewall-org/multicast/check-runs/${{ steps.output_check_id.outputs.check_id }} \
270- -f "name=$sanitized_input_name " -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
321+ -f "name=$input_name " -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
271322 -f "status=${{ inputs.status }}" \
272323 -f "details_url=${{ steps.output_check_details_url.outputs.details_url }}" \
273324 -f "$sanitized_input_title_field" \
@@ -282,21 +333,19 @@ runs:
282333 run : |
283334 printf "%s\n" "::group::validate-name"
284335 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" ;
336+ printf "::debug:: %s\n" "Will use name $name_input" ;
287337 printf "%s\n" "::endgroup::"
288338 printf "%s\n" "::group::validate-title"
289339 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" ;)
340+ printf "::debug:: %s\n" "Will use name $title_input" ;
341+ sanitized_input_title_field=$(printf "%s%s" 'output[title]=' "$title_input" ;)
293342 printf "%s\n" "::endgroup::"
294343 printf "%s\n" "::group::complete-check"
295344 # GitHub CLI api
296345 # https://cli.github.com/manual/gh_api
297346 gh api --method PATCH -H "Accept: application/vnd.github+json" \
298347 /repos/reactive-firewall-org/multicast/check-runs/${{ steps.output_check_id.outputs.check_id }} \
299- -f "name=$sanitized_input_name " -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
348+ -f "name=$input_name " -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
300349 -f "status=completed" -f "conclusion=${{ inputs.conclusion }}" \
301350 -f "completed_at=${{ steps.output_date.outputs.check_date }}Z" \
302351 -f "details_url=${{ steps.output_check_details_url.outputs.details_url }}" \
0 commit comments