Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions .github/workflows/test_docker_image_sanitize_input.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: test_docker_image_sanitize_input

on:
push:
branches: [ main ]
paths:
- '.github/actions/sanitize-docker-input/**'
pull_request:
paths:
- '.github/actions/sanitize-docker-input/**'
workflow_dispatch:

jobs:
# Test cases that are supposed to succeed
test-valid-inputs:
runs-on: ubuntu-24.04
strategy:
matrix:
image:
- 'ubuntu:latest'
- 'nginx:1.25.2'
- 'my-registry.com/my-project/node:18-alpine'
- 'gcr.io/google-containers/pause:3.9'
- 'custom_image.name:v1.0.0-beta'
steps:
- name: Checkout Code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

# We expect all of these to finish with an exit code of 0
- name: Test Valid Input (${{ matrix.image }})
id: test_action
uses: sanitize-docker-input
with:
image_string: ${{ matrix.image }}

- name: Verify Output Match
run: |
if [ "${{ steps.test_action.outputs.sanitized_image }}" != "${{ matrix.image }}" ]; then
echo "Error: Output string did not match input!"
exit 1
fi

# Test cases that are supposed to fail (malicious or invalid format)
test-invalid-inputs:
runs-on: ubuntu-24.04
strategy:
matrix:
image:
- 'ubuntu' # Naked image
- 'ubuntu:' # Missing tag definition
- 'ubuntu:latest; rm -rf /' # Command injection attempt
- 'nginx:latest && echo hacked' # Command injection attempt
- 'registry.com/image:INVALID_TAG_!!!!' # Violates regex character limits
steps:
- name: Checkout Code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

# This step forces the workflow to continue even if the action fails,
# allowing us to assert that it DID fail properly.
- name: Test Invalid Input (${{ matrix.image }})
id: test_action
continue-on-error: true
uses: sanitize-docker-input
with:
image_string: ${{ matrix.image }}

# Assert that the step outcome was a failure. If it succeeded, the test fails.
- name: Verify Action Failed Properly
run: |
if [ "${{ steps.test_action.outcome }}" == "success" ]; then
echo "CRITICAL SECURITY FAILURE: The input '${{ matrix.image }}' bypassed validation!"
exit 1
else
echo "Success: Action safely caught and rejected the invalid input."
fi
42 changes: 42 additions & 0 deletions docker_image_sanitize_input/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
name: 'Sanitize and Validate Docker Image'
description: 'Validates a Docker image string against a strict regex and ensures it is tagged.'
inputs:
image_string:
description: 'The raw docker image string to validate'
required: true

outputs:
sanitized_image:
description: 'The validated and safe docker image string'
value: ${{ steps.validator.outputs.validated_image }}

runs:
using: "composite"
steps:
- name: Validate Input
id: validator
shell: bash
# Pass the raw input as an environment variable to prevent Command Injection
env:
RAW_IMAGE: ${{ inputs.image_string }}
# Your exact custom regex provided:
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}$'
run: |
echo "Checking image string format..."

# 1. Reject if it is exactly 'ubuntu' or lacks a tag/digest delimiter
if [[ "$RAW_IMAGE" == "ubuntu" ]] || [[ "$RAW_IMAGE" != *":"* && "$RAW_IMAGE" != *"@"* ]]; then
echo "::error::Invalid Input! Raw image names like 'ubuntu' without a specific version tag are strictly banned."
exit 1
fi

# 2. Match against your custom regex
if [[ "$RAW_IMAGE" =~ $DOCKER_REGEX ]]; then
echo "Success: Image format is valid and secure."
# Export the safely validated string to outputs
echo "validated_image=$RAW_IMAGE" >> $GITHUB_OUTPUT
else
echo "::error::Invalid Input! The string '$RAW_IMAGE' does not match the allowed Docker image format rules."
exit 1
fi
6 changes: 3 additions & 3 deletions docs-firecrawl-llm/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 41 additions & 0 deletions secure_github_binary_download/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
name: 'Secure GitHub Binary Downloader'
description: 'Downloads a release binary from GitHub and verifies its SHA-256 checksum automatically.'
inputs:
version:
description: 'The version of the tool to download (e.g., 1.18.3)'
required: true
repo:
description: 'The GitHub owner/repository (e.g., kurtosis-tech/kurtosis-cli-release-artifacts)'
required: true
tarball_name:
description: 'The exact name of the asset file (e.g., kurtosis-cli_1.18.3_linux_amd64.tar.gz)'
required: true
binary_name:
description: 'The name of the compiled binary inside the archive (e.g., kurtosis)'
required: true

runs:
using: "composite"
steps:
- name: Download Asset and Checksums
shell: bash
run: |
echo "Downloading ${{ inputs.tarball_name }} from ${{ inputs.repo }}..."
curl -fsSL -O "https://github.com/${{ inputs.repo }}/releases/download/${{ inputs.version }}/${{ inputs.tarball_name }}"
curl -fsSL -O "https://github.com/${{ inputs.repo }}/releases/download/${{ inputs.version }}/checksums.txt"

- name: Verify SHA-256 Checksum
shell: bash
run: |
echo "Verifying checksum..."
grep "${{ inputs.tarball_name }}" checksums.txt | sha256sum --check

- name: Extract and Install Binary
shell: bash
run: |
tar -xvf "${{ inputs.tarball_name }}"
sudo mv "${{ inputs.binary_name }}" /usr/local/bin/

# Cleanup workspace archives so they don't bloat later steps
rm "${{ inputs.tarball_name }}" checksums.txt