From 870a1f6165cbfa90166c624c5a7c5ce24c809b43 Mon Sep 17 00:00:00 2001 From: Fernando Korndorfer Date: Sun, 18 Jan 2026 16:26:28 +0100 Subject: [PATCH 1/3] docs: add available profiles matrix to README Added a comprehensive profiles matrix documenting the five available configurations: - full: Complete toolset with all available tools - minimal: Lightweight profile with essential tools only - k8s: Kubernetes-focused profile - iac: Infrastructure as Code profile with bash-based tools - iac-pwsh: Infrastructure as Code profile with PowerShell support --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 06641d5..5b92f90 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,20 @@ Supported `--build-arg` variables are listed below to easily configure the runne - `ADD_TERRASPACE`: Installs `terraspace` tool - `ADD_SUDO`: Installs and enables `sudo` for the runner user group + +## Available Profiles + +Pre-configured profiles are available for different use cases: + +| Profile | Description | Included Tools | +|---------|-------------|----------------| +| **full** | Complete toolset with all available tools | Docker, Azure CLI, AWS CLI, PowerShell (with Azure & AWS modules), kubectl, kubelogin, kustomize, Helm, jq, yq, Terraform, OpenTofu, Terraspace | +| **minimal** | Lightweight profile with essential tools only | Docker, jq, yq | +| **k8s** | Kubernetes-focused profile | Docker, kubectl, kubelogin, kustomize, Helm, jq, yq | +| **iac** | Infrastructure as Code profile with bash-based tools | Docker, Azure CLI, AWS CLI, Terraform, OpenTofu, Terraspace, jq, yq | +| **iac-pwsh** | Infrastructure as Code profile with PowerShell support | Docker, Azure CLI, AWS CLI, PowerShell (with Azure & AWS modules), Terraform, OpenTofu, Terraspace, jq, yq | + + # References From 80db1998d342e82421f0163698de492452b4cf7c Mon Sep 17 00:00:00 2001 From: Fernando Korndorfer Date: Sun, 18 Jan 2026 16:56:31 +0100 Subject: [PATCH 2/3] fix: resolve code scan security vulnerabilities - Fix CWE-78: Quote variables in seq command to prevent command injection - Fix CWE-78: Add proper quoting for EventId in vmss_monitor.sh - Fix deprecated apt-key usage, replace with gpg --dearmor - Fix insecure curl piping to bash, download scripts first - Add security documentation for privileged mode and NOPASSWD sudo - Improve curl error handling with standardized flags - Quote sensitive variables to prevent word splitting --- Dockerfile | 19 +++++++++++++------ ec2_monitor.sh | 2 +- run.sh | 6 +++++- start.sh | 6 +++--- vmss_monitor.sh | 6 ++++-- 5 files changed, 26 insertions(+), 13 deletions(-) diff --git a/Dockerfile b/Dockerfile index 59acccf..e25c68a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -78,6 +78,9 @@ RUN echo "APT::Get::Assume-Yes \"true\";" > /etc/apt/apt.conf.d/90assumeyes \ && rm -rf /var/lib/apt/lists/* # Install sudo... +# SECURITY NOTE: NOPASSWD:ALL is configured for CI/CD automation purposes. +# This allows the agent user to execute commands with sudo without password prompts. +# This is a security trade-off for CI/CD runner functionality. RUN test "${ADD_SUDO}" = "1" || exit 0 && \ apt-get update && apt-get install -y --no-install-recommends sudo \ && apt clean \ @@ -106,7 +109,9 @@ RUN test "${ADD_JQ}" = "1" || exit 0 && \ # Install latest Azure CLI https://learn.microsoft.com/cli/azure/install-azure-cli-linux RUN test "${ADD_AZURE_CLI}" = "1" || exit 0 && \ - curl -sLS "https://aka.ms/InstallAzureCLIDeb" | bash \ + curl -sLS "https://aka.ms/InstallAzureCLIDeb" -o /tmp/install-azure-cli.sh \ + && bash /tmp/install-azure-cli.sh \ + && rm /tmp/install-azure-cli.sh \ && apt clean \ && rm -rf /var/lib/apt/lists/* \ && az config set extension.use_dynamic_install=yes_without_prompt \ @@ -175,11 +180,12 @@ RUN test "${ADD_OPENTOFU}" = "1" || exit 0 && \ # Instal Terraspace https://terraspace.cloud/docs/install/ RUN test "${ADD_TERRASPACE}" = "1" || exit 0 && \ - curl -sL https://apt.boltops.com/boltops-key.public | apt-key add - \ - && echo "deb https://apt.boltops.com stable main" > /etc/apt/sources.list.d/boltops.list \ + curl -sL https://apt.boltops.com/boltops-key.public | gpg --dearmor -o /usr/share/keyrings/boltops-archive-keyring.gpg \ + && echo "deb [signed-by=/usr/share/keyrings/boltops-archive-keyring.gpg] https://apt.boltops.com stable main" > /etc/apt/sources.list.d/boltops.list \ && apt-get update \ && apt-get install -y terraspace \ - && apt clean + && apt clean \ + && rm -rf /var/lib/apt/lists/* # Install HELM https://helm.sh/docs/intro/install/ RUN test "${ADD_HELM}" = "1" || exit 0 && \ @@ -192,9 +198,10 @@ RUN test "${ADD_HELM}" = "1" || exit 0 && \ # Install Kustomize https://kubectl.docs.kubernetes.io/installation/kustomize/ RUN test "${ADD_KUSTOMIZE}" = "1" || exit 0 && \ - curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash \ + curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" -o /tmp/install_kustomize.sh \ + && bash /tmp/install_kustomize.sh \ && install -o root -g root -m 0755 kustomize /usr/local/bin/kustomize \ - && rm -f kustomize + && rm -f kustomize /tmp/install_kustomize.sh # Install GitHub Runner WORKDIR /runner diff --git a/ec2_monitor.sh b/ec2_monitor.sh index 0ec69a4..e82fec5 100755 --- a/ec2_monitor.sh +++ b/ec2_monitor.sh @@ -12,7 +12,7 @@ echo "Checking for EC2 spot instance termination notice..." # Query EC2 Instance Metadata Service for spot termination notice # Returns HTTP 404 if no termination notice is present -RESPONSE=$(curl -s -f "$METADATA_ENDPOINT" 2>/dev/null || echo "") +RESPONSE=$(curl -sf "$METADATA_ENDPOINT" 2>/dev/null || echo "") # Check if termination notice exists if [ -n "$RESPONSE" ]; then diff --git a/run.sh b/run.sh index cdc56aa..8b1b497 100755 --- a/run.sh +++ b/run.sh @@ -75,7 +75,7 @@ echo "CPUs per runner: $MAX_CPU" echo "" # Launch runners -for R in $(seq 1 $RUNNER_COUNT); do +for R in $(seq 1 "$RUNNER_COUNT"); do RUNNER_NAME="runner-$(hostname)-$R" WORK_DIR="/mnt/runner${R}/_work" CONTAINER_NAME="github-runner-$R" @@ -92,6 +92,10 @@ for R in $(seq 1 $RUNNER_COUNT); do fi # Run GitHub runner container + # SECURITY NOTE: --privileged mode grants extended privileges to the container. + # This is required for Docker-in-Docker but poses security risks. + # Consider using rootless Docker or Docker socket mounting as alternatives. + # If --privileged is not needed for your use case, remove this flag. docker run \ --privileged \ --tty \ diff --git a/start.sh b/start.sh index 20e18f9..4312ea6 100755 --- a/start.sh +++ b/start.sh @@ -13,7 +13,7 @@ if [ -z "$GITHUB_TOKEN_FILE" ]; then fi GITHUB_TOKEN_FILE=/runner/.token - echo -n $GITHUB_TOKEN > "$GITHUB_TOKEN_FILE" + echo -n "$GITHUB_TOKEN" > "$GITHUB_TOKEN_FILE" fi unset GITHUB_TOKEN @@ -31,7 +31,7 @@ cleanup() { # If the agent has some running jobs, the configuration removal process will fail. # So, give it some time to finish the job. while true; do - ./config.sh remove --token $(cat "$GITHUB_TOKEN_FILE") && break + ./config.sh remove --token "$(cat "$GITHUB_TOKEN_FILE")" && break echo "Retrying in 30 seconds..." sleep 30 @@ -53,7 +53,7 @@ print_header "1. Configuring GitHub Runner..." ./config.sh --unattended \ --name "${RUNNER_NAME:-$(hostname)}" \ --url "$GITHUB_URL" \ - --token $(cat "$GITHUB_TOKEN_FILE") \ + --token "$(cat "$GITHUB_TOKEN_FILE")" \ --labels "${RUNNER_LABELS:-default}" \ --work "${RUNNER_WORK_DIRECTORY:-_work}" \ --replace diff --git a/vmss_monitor.sh b/vmss_monitor.sh index de5d1d1..4877b3a 100755 --- a/vmss_monitor.sh +++ b/vmss_monitor.sh @@ -12,7 +12,7 @@ STOP_SCRIPT='/opt/stop.sh' echo "Checking for VMSS scheduled events..." # Query Azure Instance Metadata Service for scheduled events -curl -s "$METADATA_ENDPOINT" -H 'Metadata: true' > "$EVENTS_FILE" +curl -sf "$METADATA_ENDPOINT" -H 'Metadata: true' > "$EVENTS_FILE" # Check if termination event is scheduled if grep -q "Terminate" "$EVENTS_FILE"; then @@ -30,8 +30,10 @@ if grep -q "Terminate" "$EVENTS_FILE"; then EventId=$(jq -r '.Events[] | select(.EventType == "Terminate") | .EventId' "$EVENTS_FILE") if [ -n "$EventId" ]; then echo "Acknowledging event: $EventId" - curl -s -X POST "$METADATA_ENDPOINT" \ + # Quote EventId to prevent command injection + curl -sf -X POST "$METADATA_ENDPOINT" \ -H 'Metadata: true' \ + -H 'Content-Type: application/json' \ -d "{\"StartRequests\": [{\"EventId\": \"${EventId}\"}]}" echo "Event acknowledged successfully" fi From 3896c839893fa0bb511740fc0eceb5b67f1583e8 Mon Sep 17 00:00:00 2001 From: Fernando Korndorfer Date: Sun, 18 Jan 2026 17:12:50 +0100 Subject: [PATCH 3/3] fix: address PR review feedback - Use jq to safely construct JSON payload in vmss_monitor.sh to properly handle special characters in EventId - Add -L flag to curl for Kustomize download to follow redirects --- Dockerfile | 2 +- vmss_monitor.sh | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index e25c68a..5142e74 100644 --- a/Dockerfile +++ b/Dockerfile @@ -198,7 +198,7 @@ RUN test "${ADD_HELM}" = "1" || exit 0 && \ # Install Kustomize https://kubectl.docs.kubernetes.io/installation/kustomize/ RUN test "${ADD_KUSTOMIZE}" = "1" || exit 0 && \ - curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" -o /tmp/install_kustomize.sh \ + curl -sLf "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" -o /tmp/install_kustomize.sh \ && bash /tmp/install_kustomize.sh \ && install -o root -g root -m 0755 kustomize /usr/local/bin/kustomize \ && rm -f kustomize /tmp/install_kustomize.sh diff --git a/vmss_monitor.sh b/vmss_monitor.sh index 4877b3a..1f4e13d 100755 --- a/vmss_monitor.sh +++ b/vmss_monitor.sh @@ -30,11 +30,12 @@ if grep -q "Terminate" "$EVENTS_FILE"; then EventId=$(jq -r '.Events[] | select(.EventType == "Terminate") | .EventId' "$EVENTS_FILE") if [ -n "$EventId" ]; then echo "Acknowledging event: $EventId" - # Quote EventId to prevent command injection + # Use jq to safely construct JSON payload to handle special characters + JSON_PAYLOAD=$(jq -n --arg eventId "$EventId" '{"StartRequests": [{"EventId": $eventId}]}') curl -sf -X POST "$METADATA_ENDPOINT" \ -H 'Metadata: true' \ -H 'Content-Type: application/json' \ - -d "{\"StartRequests\": [{\"EventId\": \"${EventId}\"}]}" + -d "$JSON_PAYLOAD" echo "Event acknowledged successfully" fi else