Skip to content

Commit 9bbfcae

Browse files
adding in a couple more composite actions
1 parent 979fb3e commit 9bbfcae

3 files changed

Lines changed: 158 additions & 0 deletions

File tree

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
name: test_docker_image_sanitize_input
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
paths:
7+
- '.github/actions/sanitize-docker-input/**'
8+
pull_request:
9+
paths:
10+
- '.github/actions/sanitize-docker-input/**'
11+
workflow_dispatch:
12+
13+
jobs:
14+
# Test cases that are supposed to succeed
15+
test-valid-inputs:
16+
runs-on: ubuntu-24.04
17+
strategy:
18+
matrix:
19+
image:
20+
- 'ubuntu:latest'
21+
- 'nginx:1.25.2'
22+
- 'my-registry.com/my-project/node:18-alpine'
23+
- 'gcr.io/google-containers/pause:3.9'
24+
- 'custom_image.name:v1.0.0-beta'
25+
steps:
26+
- name: Checkout Code
27+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
28+
29+
# We expect all of these to finish with an exit code of 0
30+
- name: Test Valid Input (${{ matrix.image }})
31+
id: test_action
32+
uses: ./docker_image_sanitize_input
33+
with:
34+
image_string: ${{ matrix.image }}
35+
36+
- name: Verify Output Match
37+
run: |
38+
if [ "${{ steps.test_action.outputs.sanitized_image }}" != "${{ matrix.image }}" ]; then
39+
echo "Error: Output string did not match input!"
40+
exit 1
41+
fi
42+
43+
# Test cases that are supposed to fail (malicious or invalid format)
44+
test-invalid-inputs:
45+
runs-on: ubuntu-24.04
46+
strategy:
47+
matrix:
48+
image:
49+
- 'ubuntu' # Naked image
50+
- 'ubuntu:' # Missing tag definition
51+
- 'ubuntu:latest; rm -rf /' # Command injection attempt
52+
- 'nginx:latest && echo hacked' # Command injection attempt
53+
- 'registry.com/image:INVALID_TAG_!!!!' # Violates regex character limits
54+
steps:
55+
- name: Checkout Code
56+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
57+
58+
# This step forces the workflow to continue even if the action fails,
59+
# allowing us to assert that it DID fail properly.
60+
- name: Test Invalid Input (${{ matrix.image }})
61+
id: test_action
62+
continue-on-error: true
63+
uses: ./docker_image_sanitize_input
64+
with:
65+
image_string: ${{ matrix.image }}
66+
67+
# Assert that the step outcome was a failure. If it succeeded, the test fails.
68+
- name: Verify Action Failed Properly
69+
run: |
70+
if [ "${{ steps.test_action.outcome }}" == "success" ]; then
71+
echo "CRITICAL SECURITY FAILURE: The input '${{ matrix.image }}' bypassed validation!"
72+
exit 1
73+
else
74+
echo "Success: Action safely caught and rejected the invalid input."
75+
fi
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
name: 'Sanitize and Validate Docker Image'
3+
description: 'Validates a Docker image string against a strict regex and ensures it is tagged.'
4+
inputs:
5+
image_string:
6+
description: 'The raw docker image string to validate'
7+
required: true
8+
9+
outputs:
10+
sanitized_image:
11+
description: 'The validated and safe docker image string'
12+
value: ${{ steps.validator.outputs.validated_image }}
13+
14+
runs:
15+
using: "composite"
16+
steps:
17+
- name: Validate Input
18+
id: validator
19+
shell: bash
20+
# Pass the raw input as an environment variable to prevent Command Injection
21+
env:
22+
RAW_IMAGE: ${{ inputs.image_string }}
23+
# Your exact custom regex provided:
24+
DOCKER_REGEX: '^(?:[a-zA-Z0-9.-]+(?::[0-9]+)?\/)?(?:[a-z0-9]+(?:[._-][a-z0-9]+)*\/)*[a-z0-9]+(?:[._-][a-z0-9]+)*:[A-Za-z0-9][A-Za-z0-9._-]{0,127}$'
25+
run: |
26+
echo "Checking image string format..."
27+
28+
# 1. Reject if it is exactly 'ubuntu' or lacks a tag/digest delimiter
29+
if [[ "$RAW_IMAGE" == "ubuntu" ]] || [[ "$RAW_IMAGE" != *":"* && "$RAW_IMAGE" != *"@"* ]]; then
30+
echo "::error::Invalid Input! Raw image names like 'ubuntu' without a specific version tag are strictly banned."
31+
exit 1
32+
fi
33+
34+
# 2. Match against your custom regex
35+
if [[ "$RAW_IMAGE" =~ $DOCKER_REGEX ]]; then
36+
echo "Success: Image format is valid and secure."
37+
# Export the safely validated string to outputs
38+
echo "validated_image=$RAW_IMAGE" >> $GITHUB_OUTPUT
39+
else
40+
echo "::error::Invalid Input! The string '$RAW_IMAGE' does not match the allowed Docker image format rules."
41+
exit 1
42+
fi
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
---
2+
name: 'Secure GitHub Binary Downloader'
3+
description: 'Downloads a release binary from GitHub and verifies its SHA-256 checksum automatically.'
4+
inputs:
5+
version:
6+
description: 'The version of the tool to download (e.g., 1.18.3)'
7+
required: true
8+
repo:
9+
description: 'The GitHub owner/repository (e.g., kurtosis-tech/kurtosis-cli-release-artifacts)'
10+
required: true
11+
tarball_name:
12+
description: 'The exact name of the asset file (e.g., kurtosis-cli_1.18.3_linux_amd64.tar.gz)'
13+
required: true
14+
binary_name:
15+
description: 'The name of the compiled binary inside the archive (e.g., kurtosis)'
16+
required: true
17+
18+
runs:
19+
using: "composite"
20+
steps:
21+
- name: Download Asset and Checksums
22+
shell: bash
23+
run: |
24+
echo "Downloading ${{ inputs.tarball_name }} from ${{ inputs.repo }}..."
25+
curl -fsSL -O "https://github.com/${{ inputs.repo }}/releases/download/${{ inputs.version }}/${{ inputs.tarball_name }}"
26+
curl -fsSL -O "https://github.com/${{ inputs.repo }}/releases/download/${{ inputs.version }}/checksums.txt"
27+
28+
- name: Verify SHA-256 Checksum
29+
shell: bash
30+
run: |
31+
echo "Verifying checksum..."
32+
grep "${{ inputs.tarball_name }}" checksums.txt | sha256sum --check
33+
34+
- name: Extract and Install Binary
35+
shell: bash
36+
run: |
37+
tar -xvf "${{ inputs.tarball_name }}"
38+
sudo mv "${{ inputs.binary_name }}" /usr/local/bin/
39+
40+
# Cleanup workspace archives so they don't bloat later steps
41+
rm "${{ inputs.tarball_name }}" checksums.txt

0 commit comments

Comments
 (0)