Skip to content
Open
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: 73 additions & 2 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@
default: 1
description: "Fetch depth for git checkout"

build-excludes:
type: string
required: false
default: ""
description: "comma seperated list of files or folders to skip docker image build"

outputs:
image:
description: "Full path of produced image"
Expand Down Expand Up @@ -157,8 +163,9 @@
DEPLOY_USER_SSH_KEY: ${{ secrets.deploy_user_ssh_key }}
REPOSITORY: ${{ inputs.repository }}
REPO: ${{ inputs.repo }}
DEFAULT_BUILD_EXCLUDES: "**/*.md,.git/*,gha-creds*,.deploy,nomad.hcl,*nomad.variables.hcl"
outputs:
image: ${{ steps.meta.outputs.tags }}
image: ${{ steps.compute_hash.outputs.image }}
steps:
- name: Set Variables
run: |
Expand Down Expand Up @@ -251,6 +258,67 @@
username: oauth2accesstoken
password: ${{ steps.auth_with_workload_identity.outputs.access_token }}

- name: Compute hash and check if image exists
id: compute_hash
run: |
#!/usr/bin/env bash
set -euo pipefail
EXCLUDES="${{ env.DEFAULT_BUILD_EXCLUDES }}"

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ env.DEFAULT_BUILD_EXCLUDES }
, which may be controlled by an external user.

Copilot Autofix

AI 4 months ago

General approach:
Set the value of DEFAULT_BUILD_EXCLUDES as an environment variable using the env: block in the workflow step, and reference it in the shell script using shell variable syntax ($DEFAULT_BUILD_EXCLUDES), not via ${{ ... }} interpolation. This prevents code injection via workflow-level interpolation and utilizes the shell's built-in variable substitution.

Detailed fix:

  • In the step with id: compute_hash, move the assignment of ${{ env.DEFAULT_BUILD_EXCLUDES }} out of the shell script and into the step’s env: section:
    • Add DEFAULT_BUILD_EXCLUDES: ${{ env.DEFAULT_BUILD_EXCLUDES }} under the env: key.
  • In the shell script, use EXCLUDES="$DEFAULT_BUILD_EXCLUDES" instead of referencing the variable with ${{ ... }}.
  • No changes to imports or method definitions are needed; this is a straightforward YAML modification and does not alter the workflow's logic.

Files/lines to change:

  • .github/workflows/docker.yml:
    • Add env: to the - name: Compute hash and check if image exists step (ID compute_hash) with a line to set DEFAULT_BUILD_EXCLUDES from ${{ env.DEFAULT_BUILD_EXCLUDES }}.
    • Change the line EXCLUDES="${{ env.DEFAULT_BUILD_EXCLUDES }}" to EXCLUDES="$DEFAULT_BUILD_EXCLUDES".

Suggested changeset 1
.github/workflows/docker.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -260,10 +260,12 @@
 
       - name: Compute hash and check if image exists
         id: compute_hash
+        env:
+          DEFAULT_BUILD_EXCLUDES: ${{ env.DEFAULT_BUILD_EXCLUDES }}
         run: |
           #!/usr/bin/env bash
           set -euo pipefail
-          EXCLUDES="${{ env.DEFAULT_BUILD_EXCLUDES }}"
+          EXCLUDES="$DEFAULT_BUILD_EXCLUDES"
           if [ -n "${{ inputs.build-excludes }}" ]; then
             EXCLUDES+=",${{ inputs.build-excludes }}"
           fi
EOF
@@ -260,10 +260,12 @@

- name: Compute hash and check if image exists
id: compute_hash
env:
DEFAULT_BUILD_EXCLUDES: ${{ env.DEFAULT_BUILD_EXCLUDES }}
run: |
#!/usr/bin/env bash
set -euo pipefail
EXCLUDES="${{ env.DEFAULT_BUILD_EXCLUDES }}"
EXCLUDES="$DEFAULT_BUILD_EXCLUDES"
if [ -n "${{ inputs.build-excludes }}" ]; then
EXCLUDES+=",${{ inputs.build-excludes }}"
fi
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
if [ -n "${{ inputs.build-excludes }}" ]; then

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ inputs.build-excludes }
, which may be controlled by an external user.

Copilot Autofix

AI 4 months ago

To fix the potential code injection flaw, one should avoid using ${{ inputs.build-excludes }} directly inside the script block. Instead, pass the input value into an environment variable using the env: block of the step, and reference it using shell-native variable expansion ($BUILD_EXCLUDES). Specifically, in the step running the shell script (id: compute_hash), add an env entry: BUILD_EXCLUDES: ${{ inputs.build-excludes }}. Then, throughout the shell script, replace ${{ inputs.build-excludes }} with $BUILD_EXCLUDES. The same should be done for other workflow inputs being used in the shell script, if they are also user-controlled and interpolated directly.

Changes needed:

  • In the step with id: compute_hash, add to the env section: BUILD_EXCLUDES: ${{ inputs.build-excludes }} (or, create the env block if not present).
  • Replace every instance of ${{ inputs.build-excludes }} in the run script of that step with $BUILD_EXCLUDES.

No additional dependencies or imports are needed.


Suggested changeset 1
.github/workflows/docker.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -260,12 +260,14 @@
 
       - name: Compute hash and check if image exists
         id: compute_hash
+        env:
+          BUILD_EXCLUDES: ${{ inputs.build-excludes }}
         run: |
           #!/usr/bin/env bash
           set -euo pipefail
           EXCLUDES="${{ env.DEFAULT_BUILD_EXCLUDES }}"
-          if [ -n "${{ inputs.build-excludes }}" ]; then
-            EXCLUDES+=",${{ inputs.build-excludes }}"
+          if [ -n "$BUILD_EXCLUDES" ]; then
+            EXCLUDES+=",$BUILD_EXCLUDES"
           fi
 
           if [ -n "${{ inputs.tag }}" ]; then
EOF
@@ -260,12 +260,14 @@

- name: Compute hash and check if image exists
id: compute_hash
env:
BUILD_EXCLUDES: ${{ inputs.build-excludes }}
run: |
#!/usr/bin/env bash
set -euo pipefail
EXCLUDES="${{ env.DEFAULT_BUILD_EXCLUDES }}"
if [ -n "${{ inputs.build-excludes }}" ]; then
EXCLUDES+=",${{ inputs.build-excludes }}"
if [ -n "$BUILD_EXCLUDES" ]; then
EXCLUDES+=",$BUILD_EXCLUDES"
fi

if [ -n "${{ inputs.tag }}" ]; then
Copilot is powered by AI and may make mistakes. Always verify output.
EXCLUDES+=",${{ inputs.build-excludes }}"

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ inputs.build-excludes }
, which may be controlled by an external user.

Copilot Autofix

AI 4 months ago

To fix the issue, assign the potentially untrusted input (${{ inputs.build-excludes }}) to an environment variable using the env: key in the GitHub Actions workflow step, rather than interpolating it directly in the run: script. Then, inside the shell script, reference the variable using bash's native $BUILD_EXCLUDES instead of ${{ ... }}. This approach prevents GitHub Actions' expression evaluation from inadvertently exposing the shell to code injection risks, as shell variable expansion does not enable command substitution from workflow input.

Specifically, modify the "Compute hash and check if image exists" step (lines 262–317 in the provided snippet):

  • Update the step to add an env: section, setting something like BUILD_EXCLUDES: ${{ inputs.build-excludes }}.
  • Change line if [ -n "${{ inputs.build-excludes }}" ]; then to use [ -n "$BUILD_EXCLUDES" ]
  • And where the value is appended (EXCLUDES+=",${{ inputs.build-excludes }}"), switch to EXCLUDES+=",${BUILD_EXCLUDES}".

No new methods or imports are needed; this is pure YAML and shell quoting discipline.


Suggested changeset 1
.github/workflows/docker.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -260,12 +260,14 @@
 
       - name: Compute hash and check if image exists
         id: compute_hash
+        env:
+          BUILD_EXCLUDES: ${{ inputs.build-excludes }}
         run: |
           #!/usr/bin/env bash
           set -euo pipefail
           EXCLUDES="${{ env.DEFAULT_BUILD_EXCLUDES }}"
-          if [ -n "${{ inputs.build-excludes }}" ]; then
-            EXCLUDES+=",${{ inputs.build-excludes }}"
+          if [ -n "$BUILD_EXCLUDES" ]; then
+            EXCLUDES+=",${BUILD_EXCLUDES}"
           fi
 
           if [ -n "${{ inputs.tag }}" ]; then
@@ -313,7 +311,6 @@
           # Print for debugging
           echo "IMAGE=${IMAGE}"
           echo "EXISTS=${EXISTS}"
-
       - name: Print results
         run: |
           echo "Computed tag: ${{ env.image }}"
EOF
@@ -260,12 +260,14 @@

- name: Compute hash and check if image exists
id: compute_hash
env:
BUILD_EXCLUDES: ${{ inputs.build-excludes }}
run: |
#!/usr/bin/env bash
set -euo pipefail
EXCLUDES="${{ env.DEFAULT_BUILD_EXCLUDES }}"
if [ -n "${{ inputs.build-excludes }}" ]; then
EXCLUDES+=",${{ inputs.build-excludes }}"
if [ -n "$BUILD_EXCLUDES" ]; then
EXCLUDES+=",${BUILD_EXCLUDES}"
fi

if [ -n "${{ inputs.tag }}" ]; then
@@ -313,7 +311,6 @@
# Print for debugging
echo "IMAGE=${IMAGE}"
echo "EXISTS=${EXISTS}"

- name: Print results
run: |
echo "Computed tag: ${{ env.image }}"
Copilot is powered by AI and may make mistakes. Always verify output.
fi

if [ -n "${{ inputs.tag }}" ]; then

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ inputs.tag }
, which may be controlled by an external user.

Copilot Autofix

AI 4 months ago

General fix:
The best way to mitigate this sort of code injection in GitHub Actions shell scripts is to place the untrusted expression (${{ inputs.tag }}) into an intermediate environment variable via the env: block and then only reference it in the shell script using the native variable syntax ($TAG). This ensures that the untrusted input cannot break out of its variable assignment, as GitHub Actions handles safe quoting for environment variables automatically.

Detailed steps:

  • Find where ${{ inputs.tag }} is present in the shell script in the run: block (lines 271, 273, 274, 292).
  • At the step level, define a new environment variable, such as TAG_INPUT: ${{ inputs.tag }}.
  • In the shell script, reference the value as $TAG_INPUT rather than interpolating directly with ${{ inputs.tag }}.
  • Where the script assigns TAG="${{ inputs.tag }}", instead assign TAG="$TAG_INPUT".
  • Likewise, update lines where IMAGE and similar variables were composed with ${{ inputs.tag }} to use $TAG_INPUT or $TAG as appropriate.
  • Do not reference ${{ inputs.tag }} directly in shell code.

Imports/Definitions needed:
No imports necessary. No new packages are needed.


Suggested changeset 1
.github/workflows/docker.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -260,6 +260,8 @@
 
       - name: Compute hash and check if image exists
         id: compute_hash
+        env:
+          TAG_INPUT: ${{ inputs.tag }}
         run: |
           #!/usr/bin/env bash
           set -euo pipefail
@@ -268,10 +270,10 @@
             EXCLUDES+=",${{ inputs.build-excludes }}"
           fi
 
-          if [ -n "${{ inputs.tag }}" ]; then
-            echo "🔖 Tag '${{ inputs.tag }}' provided — skipping hash computation."
-            IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${{ inputs.tag }}"
-            TAG="${{ inputs.tag }}"
+          if [ -n "$TAG_INPUT" ]; then
+            echo "🔖 Tag '$TAG_INPUT' provided — skipping hash computation."
+            IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:$TAG_INPUT"
+            TAG="$TAG_INPUT"
             EXISTS="false" # Assume not built yet — can still be checked later if desired
           else
             # Enable extended globbing and recursive globs (**)
EOF
@@ -260,6 +260,8 @@

- name: Compute hash and check if image exists
id: compute_hash
env:
TAG_INPUT: ${{ inputs.tag }}
run: |
#!/usr/bin/env bash
set -euo pipefail
@@ -268,10 +270,10 @@
EXCLUDES+=",${{ inputs.build-excludes }}"
fi

if [ -n "${{ inputs.tag }}" ]; then
echo "🔖 Tag '${{ inputs.tag }}' provided — skipping hash computation."
IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${{ inputs.tag }}"
TAG="${{ inputs.tag }}"
if [ -n "$TAG_INPUT" ]; then
echo "🔖 Tag '$TAG_INPUT' provided — skipping hash computation."
IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:$TAG_INPUT"
TAG="$TAG_INPUT"
EXISTS="false" # Assume not built yet — can still be checked later if desired
else
# Enable extended globbing and recursive globs (**)
Copilot is powered by AI and may make mistakes. Always verify output.
echo "🔖 Tag '${{ inputs.tag }}' provided — skipping hash computation."

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ inputs.tag }
, which may be controlled by an external user.

Copilot Autofix

AI 4 months ago

To fix this code injection risk, do not interpolate ${{ inputs.tag }} directly in the shell script. Instead, assign it as an environment variable, and then refer to it in the script via the shell-native $TAG syntax.
Specifically:

  • In the affected step (Compute hash and check if image exists), add an env: section to pass inputs.tag into the script as an environment variable (e.g., TAG_INPUT: ${{ inputs.tag }}), or, if you want to preserve the original variable name, as TAG: ${{ inputs.tag }}.
  • In the script, refer to it using $TAG (not ${{ inputs.tag }}).
  • Apply the same pattern for other input variables if you use user-supplied input elsewhere in the shell code.

This approach ensures that user data is not implicitly interpreted by the shell, thus preventing code injection.


Suggested changeset 1
.github/workflows/docker.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -260,6 +260,8 @@
 
       - name: Compute hash and check if image exists
         id: compute_hash
+        env:
+          TAG: ${{ inputs.tag }}
         run: |
           #!/usr/bin/env bash
           set -euo pipefail
@@ -268,10 +270,10 @@
             EXCLUDES+=",${{ inputs.build-excludes }}"
           fi
 
-          if [ -n "${{ inputs.tag }}" ]; then
-            echo "🔖 Tag '${{ inputs.tag }}' provided — skipping hash computation."
-            IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${{ inputs.tag }}"
-            TAG="${{ inputs.tag }}"
+          if [ -n "$TAG" ]; then
+            echo "🔖 Tag '$TAG' provided — skipping hash computation."
+            IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:$TAG"
+            TAG="$TAG"
             EXISTS="false" # Assume not built yet — can still be checked later if desired
           else
             # Enable extended globbing and recursive globs (**)
EOF
@@ -260,6 +260,8 @@

- name: Compute hash and check if image exists
id: compute_hash
env:
TAG: ${{ inputs.tag }}
run: |
#!/usr/bin/env bash
set -euo pipefail
@@ -268,10 +270,10 @@
EXCLUDES+=",${{ inputs.build-excludes }}"
fi

if [ -n "${{ inputs.tag }}" ]; then
echo "🔖 Tag '${{ inputs.tag }}' provided — skipping hash computation."
IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${{ inputs.tag }}"
TAG="${{ inputs.tag }}"
if [ -n "$TAG" ]; then
echo "🔖 Tag '$TAG' provided — skipping hash computation."
IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:$TAG"
TAG="$TAG"
EXISTS="false" # Assume not built yet — can still be checked later if desired
else
# Enable extended globbing and recursive globs (**)
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${{ inputs.tag }}"

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ inputs.registry }
, which may be controlled by an external user.

Copilot Autofix

AI 4 months ago

To fix the problem, all untrusted input references (such as ${{ inputs.registry }}, ${{ inputs.project }}, etc.) that are interpolated inside the run script must be passed into the shell script as environment variables. Instead of referencing the inputs with ${{ ... }} syntax inside the script, they should be passed via env: and referenced in the script using the shell’s native syntax (e.g., $REGISTRY, $PROJECT, etc.).

Concretely:

  • For the run: step named "Compute hash and check if image exists", add an env: section that assigns each input value to a named environment variable (REGISTRY, PROJECT, REPOSITORY, IMAGE, TAG, etc.).
  • Within the shell script, replace usages like ${{ inputs.registry }} with $REGISTRY, ${{ env.REPOSITORY }} with $REPOSITORY, etc.
  • This avoids direct GitHub Expression interpolation in the shell context, preventing code injection.

This change should be applied only to the relevant workflow step. No code changes are required elsewhere.


Suggested changeset 1
.github/workflows/docker.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -260,18 +260,26 @@
 
       - name: Compute hash and check if image exists
         id: compute_hash
+        env:
+          REGISTRY: ${{ inputs.registry }}
+          PROJECT: ${{ inputs.project }}
+          REPOSITORY: ${{ env.REPOSITORY }}
+          IMAGE_NAME: ${{ inputs.image }}
+          TAG_INPUT: ${{ inputs.tag }}
+          DEFAULT_BUILD_EXCLUDES: ${{ env.DEFAULT_BUILD_EXCLUDES }}
+          BUILD_EXCLUDES: ${{ inputs.build-excludes }}
         run: |
           #!/usr/bin/env bash
           set -euo pipefail
-          EXCLUDES="${{ env.DEFAULT_BUILD_EXCLUDES }}"
-          if [ -n "${{ inputs.build-excludes }}" ]; then
-            EXCLUDES+=",${{ inputs.build-excludes }}"
+          EXCLUDES="$DEFAULT_BUILD_EXCLUDES"
+          if [ -n "$BUILD_EXCLUDES" ]; then
+            EXCLUDES+=",$BUILD_EXCLUDES"
           fi
 
-          if [ -n "${{ inputs.tag }}" ]; then
-            echo "🔖 Tag '${{ inputs.tag }}' provided — skipping hash computation."
-            IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${{ inputs.tag }}"
-            TAG="${{ inputs.tag }}"
+          if [ -n "$TAG_INPUT" ]; then
+            echo "🔖 Tag '$TAG_INPUT' provided — skipping hash computation."
+            IMAGE="$REGISTRY/$PROJECT/$REPOSITORY/$IMAGE_NAME:$TAG_INPUT"
+            TAG="$TAG_INPUT"
             EXISTS="false" # Assume not built yet — can still be checked later if desired
           else
             # Enable extended globbing and recursive globs (**)
@@ -289,7 +292,7 @@
             # Compute deterministic content-based hash
             TAG=$("${FIND_CMD[@]}" -exec sha256sum {} \; | sort | sha256sum | cut -d' ' -f1)
 
-            IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${TAG}"
+            IMAGE="$REGISTRY/$PROJECT/$REPOSITORY/$IMAGE_NAME:$TAG"
 
             # Check if image exists in registry
             if docker manifest inspect "$IMAGE" >/dev/null 2>&1; then
EOF
@@ -260,18 +260,26 @@

- name: Compute hash and check if image exists
id: compute_hash
env:
REGISTRY: ${{ inputs.registry }}
PROJECT: ${{ inputs.project }}
REPOSITORY: ${{ env.REPOSITORY }}
IMAGE_NAME: ${{ inputs.image }}
TAG_INPUT: ${{ inputs.tag }}
DEFAULT_BUILD_EXCLUDES: ${{ env.DEFAULT_BUILD_EXCLUDES }}
BUILD_EXCLUDES: ${{ inputs.build-excludes }}
run: |
#!/usr/bin/env bash
set -euo pipefail
EXCLUDES="${{ env.DEFAULT_BUILD_EXCLUDES }}"
if [ -n "${{ inputs.build-excludes }}" ]; then
EXCLUDES+=",${{ inputs.build-excludes }}"
EXCLUDES="$DEFAULT_BUILD_EXCLUDES"
if [ -n "$BUILD_EXCLUDES" ]; then
EXCLUDES+=",$BUILD_EXCLUDES"
fi

if [ -n "${{ inputs.tag }}" ]; then
echo "🔖 Tag '${{ inputs.tag }}' provided — skipping hash computation."
IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${{ inputs.tag }}"
TAG="${{ inputs.tag }}"
if [ -n "$TAG_INPUT" ]; then
echo "🔖 Tag '$TAG_INPUT' provided — skipping hash computation."
IMAGE="$REGISTRY/$PROJECT/$REPOSITORY/$IMAGE_NAME:$TAG_INPUT"
TAG="$TAG_INPUT"
EXISTS="false" # Assume not built yet — can still be checked later if desired
else
# Enable extended globbing and recursive globs (**)
@@ -289,7 +292,7 @@
# Compute deterministic content-based hash
TAG=$("${FIND_CMD[@]}" -exec sha256sum {} \; | sort | sha256sum | cut -d' ' -f1)

IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${TAG}"
IMAGE="$REGISTRY/$PROJECT/$REPOSITORY/$IMAGE_NAME:$TAG"

# Check if image exists in registry
if docker manifest inspect "$IMAGE" >/dev/null 2>&1; then
Copilot is powered by AI and may make mistakes. Always verify output.

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ inputs.project }
, which may be controlled by an external user.

Copilot Autofix

AI 4 months ago

To mitigate code injection in this workflow, we must avoid interpolating ${{ ... }} expressions for user-controllable inputs directly into shell scripts. Instead, assign those expressions to environment variables in the env: section of the workflow step, and refer to those variables using native shell syntax (e.g., $PROJECT) inside the script.

Specifically, in the shell section for the "Compute hash and check if image exists" step (lines 263-316), we must:

  • Move all untrusted inputs (${{ inputs.project }}, and other relevant ones—such as ${{ inputs.registry }}, ${{ env.REPOSITORY }}, ${{ inputs.image }}, ${{ inputs.tag }}) from direct shell usage into the environment.
  • Replace references using ${{ ... }} with their shell equivalents ($PROJECT, $REGISTRY, etc.), which are populated safely by the environment variable assignments.

No other code changes or logic refactoring are required, only the safe handoff of input values via environment variables, and the appropriate update of variable references inside the shell script for both branches.


Suggested changeset 1
.github/workflows/docker.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -260,18 +260,26 @@
 
       - name: Compute hash and check if image exists
         id: compute_hash
+        env:
+          REGISTRY: ${{ inputs.registry }}
+          PROJECT: ${{ inputs.project }}
+          REPOSITORY: ${{ env.REPOSITORY }}
+          IMAGE_NAME: ${{ inputs.image }}
+          TAG_INPUT: ${{ inputs.tag }}
+          BUILD_EXCLUDES_INPUT: ${{ inputs.build-excludes }}
+          DEFAULT_BUILD_EXCLUDES: ${{ env.DEFAULT_BUILD_EXCLUDES }}
         run: |
           #!/usr/bin/env bash
           set -euo pipefail
-          EXCLUDES="${{ env.DEFAULT_BUILD_EXCLUDES }}"
-          if [ -n "${{ inputs.build-excludes }}" ]; then
-            EXCLUDES+=",${{ inputs.build-excludes }}"
+          EXCLUDES="$DEFAULT_BUILD_EXCLUDES"
+          if [ -n "$BUILD_EXCLUDES_INPUT" ]; then
+            EXCLUDES+=",$BUILD_EXCLUDES_INPUT"
           fi
 
-          if [ -n "${{ inputs.tag }}" ]; then
-            echo "🔖 Tag '${{ inputs.tag }}' provided — skipping hash computation."
-            IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${{ inputs.tag }}"
-            TAG="${{ inputs.tag }}"
+          if [ -n "$TAG_INPUT" ]; then
+            echo "🔖 Tag '$TAG_INPUT' provided — skipping hash computation."
+            IMAGE="$REGISTRY/$PROJECT/$REPOSITORY/$IMAGE_NAME:$TAG_INPUT"
+            TAG="$TAG_INPUT"
             EXISTS="false" # Assume not built yet — can still be checked later if desired
           else
             # Enable extended globbing and recursive globs (**)
@@ -289,7 +292,7 @@
             # Compute deterministic content-based hash
             TAG=$("${FIND_CMD[@]}" -exec sha256sum {} \; | sort | sha256sum | cut -d' ' -f1)
 
-            IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${TAG}"
+            IMAGE="$REGISTRY/$PROJECT/$REPOSITORY/$IMAGE_NAME:$TAG"
 
             # Check if image exists in registry
             if docker manifest inspect "$IMAGE" >/dev/null 2>&1; then
EOF
@@ -260,18 +260,26 @@

- name: Compute hash and check if image exists
id: compute_hash
env:
REGISTRY: ${{ inputs.registry }}
PROJECT: ${{ inputs.project }}
REPOSITORY: ${{ env.REPOSITORY }}
IMAGE_NAME: ${{ inputs.image }}
TAG_INPUT: ${{ inputs.tag }}
BUILD_EXCLUDES_INPUT: ${{ inputs.build-excludes }}
DEFAULT_BUILD_EXCLUDES: ${{ env.DEFAULT_BUILD_EXCLUDES }}
run: |
#!/usr/bin/env bash
set -euo pipefail
EXCLUDES="${{ env.DEFAULT_BUILD_EXCLUDES }}"
if [ -n "${{ inputs.build-excludes }}" ]; then
EXCLUDES+=",${{ inputs.build-excludes }}"
EXCLUDES="$DEFAULT_BUILD_EXCLUDES"
if [ -n "$BUILD_EXCLUDES_INPUT" ]; then
EXCLUDES+=",$BUILD_EXCLUDES_INPUT"
fi

if [ -n "${{ inputs.tag }}" ]; then
echo "🔖 Tag '${{ inputs.tag }}' provided — skipping hash computation."
IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${{ inputs.tag }}"
TAG="${{ inputs.tag }}"
if [ -n "$TAG_INPUT" ]; then
echo "🔖 Tag '$TAG_INPUT' provided — skipping hash computation."
IMAGE="$REGISTRY/$PROJECT/$REPOSITORY/$IMAGE_NAME:$TAG_INPUT"
TAG="$TAG_INPUT"
EXISTS="false" # Assume not built yet — can still be checked later if desired
else
# Enable extended globbing and recursive globs (**)
@@ -289,7 +292,7 @@
# Compute deterministic content-based hash
TAG=$("${FIND_CMD[@]}" -exec sha256sum {} \; | sort | sha256sum | cut -d' ' -f1)

IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${TAG}"
IMAGE="$REGISTRY/$PROJECT/$REPOSITORY/$IMAGE_NAME:$TAG"

# Check if image exists in registry
if docker manifest inspect "$IMAGE" >/dev/null 2>&1; then
Copilot is powered by AI and may make mistakes. Always verify output.

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ env.REPOSITORY }
, which may be controlled by an external user.
Potential code injection in
${ env.REPOSITORY }
, which may be controlled by an external user.
Potential code injection in
${ env.REPOSITORY }
, which may be controlled by an external user.

Copilot Autofix

AI 4 months ago

To fix this vulnerability, we should set the untrusted input (the value of ${{ env.REPOSITORY }}) into an environment variable using normal GitHub Actions syntax, but refer to it in the shell script with native shell syntax ($REPOSITORY) rather than ${{ env.REPOSITORY }}. This way, the shell will treat the variable value literally, rather than interpolating the untrusted content into the command script.

Specifically:

  • Replace lines like:
    IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${{ inputs.tag }}"
    with:
    IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${REPOSITORY}/${{ inputs.image }}:${{ inputs.tag }}"
    (i.e., change ${{ env.REPOSITORY }} to $REPOSITORY).

Apply this change to all places in the workflow where ${{ env.REPOSITORY }} is used in the shell and is derived from untrusted input. This only requires changing the shell script – the environment variable declaration in the workflow remains unchanged.

No additional imports or method definitions are required.


Suggested changeset 1
.github/workflows/docker.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -270,7 +270,7 @@
 
           if [ -n "${{ inputs.tag }}" ]; then
             echo "🔖 Tag '${{ inputs.tag }}' provided — skipping hash computation."
-            IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${{ inputs.tag }}"
+            IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${REPOSITORY}/${{ inputs.image }}:${{ inputs.tag }}"
             TAG="${{ inputs.tag }}"
             EXISTS="false" # Assume not built yet — can still be checked later if desired
           else
@@ -289,7 +289,7 @@
             # Compute deterministic content-based hash
             TAG=$("${FIND_CMD[@]}" -exec sha256sum {} \; | sort | sha256sum | cut -d' ' -f1)
 
-            IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${TAG}"
+            IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${REPOSITORY}/${{ inputs.image }}:${TAG}"
 
             # Check if image exists in registry
             if docker manifest inspect "$IMAGE" >/dev/null 2>&1; then
EOF
@@ -270,7 +270,7 @@

if [ -n "${{ inputs.tag }}" ]; then
echo "🔖 Tag '${{ inputs.tag }}' provided — skipping hash computation."
IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${{ inputs.tag }}"
IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${REPOSITORY}/${{ inputs.image }}:${{ inputs.tag }}"
TAG="${{ inputs.tag }}"
EXISTS="false" # Assume not built yet — can still be checked later if desired
else
@@ -289,7 +289,7 @@
# Compute deterministic content-based hash
TAG=$("${FIND_CMD[@]}" -exec sha256sum {} \; | sort | sha256sum | cut -d' ' -f1)

IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${TAG}"
IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${REPOSITORY}/${{ inputs.image }}:${TAG}"

# Check if image exists in registry
if docker manifest inspect "$IMAGE" >/dev/null 2>&1; then
Copilot is powered by AI and may make mistakes. Always verify output.

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ inputs.image }
, which may be controlled by an external user.

Copilot Autofix

AI 4 months ago

To fix this issue, assign the value of ${{ inputs.image }} (along with all other untrusted inputs used in the ${{ ... }} syntax for shell variable expansion) to an environment variable at the step declaration level and then use shell-native variable expansion ($IMAGE) inside the script. Specifically, in the "Compute hash and check if image exists" step, define an env section assigning all externally-provided inputs used in the script to their corresponding environment variables:

env:
  IMAGE_INPUT: ${{ inputs.image }}
  ...

Then, in the shell script, use $IMAGE_INPUT instead of ${{ inputs.image }}. Additionally, update all other instances (e.g. ${{ inputs.registry }} and ${{ inputs.project }}) in shell expressions to use their environment variable equivalents, ensuring you only change inside the shell script (not for Docker/other with/outputs sections).

This change is confined to the "Compute hash and check if image exists" step, affecting the shell script block beginning at line 263, by adding an env section and changing references from ${{ inputs.image }} to $IMAGE_INPUT.

Suggested changeset 1
.github/workflows/docker.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -260,18 +260,26 @@
 
       - name: Compute hash and check if image exists
         id: compute_hash
+        env:
+          REGISTRY_INPUT: ${{ inputs.registry }}
+          PROJECT_INPUT: ${{ inputs.project }}
+          REPOSITORY_ENV: ${{ env.REPOSITORY }}
+          IMAGE_INPUT: ${{ inputs.image }}
+          TAG_INPUT: ${{ inputs.tag }}
+          BUILD_EXCLUDES_INPUT: ${{ inputs.build-excludes }}
+          DEFAULT_BUILD_EXCLUDES: ${{ env.DEFAULT_BUILD_EXCLUDES }}
         run: |
           #!/usr/bin/env bash
           set -euo pipefail
-          EXCLUDES="${{ env.DEFAULT_BUILD_EXCLUDES }}"
-          if [ -n "${{ inputs.build-excludes }}" ]; then
-            EXCLUDES+=",${{ inputs.build-excludes }}"
+          EXCLUDES="${DEFAULT_BUILD_EXCLUDES}"
+          if [ -n "${BUILD_EXCLUDES_INPUT}" ]; then
+            EXCLUDES+=",${BUILD_EXCLUDES_INPUT}"
           fi
 
-          if [ -n "${{ inputs.tag }}" ]; then
-            echo "🔖 Tag '${{ inputs.tag }}' provided — skipping hash computation."
-            IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${{ inputs.tag }}"
-            TAG="${{ inputs.tag }}"
+          if [ -n "${TAG_INPUT}" ]; then
+            echo "🔖 Tag '${TAG_INPUT}' provided — skipping hash computation."
+            IMAGE="${REGISTRY_INPUT}/${PROJECT_INPUT}/${REPOSITORY_ENV}/${IMAGE_INPUT}:${TAG_INPUT}"
+            TAG="${TAG_INPUT}"
             EXISTS="false" # Assume not built yet — can still be checked later if desired
           else
             # Enable extended globbing and recursive globs (**)
@@ -289,7 +292,7 @@
             # Compute deterministic content-based hash
             TAG=$("${FIND_CMD[@]}" -exec sha256sum {} \; | sort | sha256sum | cut -d' ' -f1)
 
-            IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${TAG}"
+            IMAGE="${REGISTRY_INPUT}/${PROJECT_INPUT}/${REPOSITORY_ENV}/${IMAGE_INPUT}:${TAG}"
 
             # Check if image exists in registry
             if docker manifest inspect "$IMAGE" >/dev/null 2>&1; then
EOF
@@ -260,18 +260,26 @@

- name: Compute hash and check if image exists
id: compute_hash
env:
REGISTRY_INPUT: ${{ inputs.registry }}
PROJECT_INPUT: ${{ inputs.project }}
REPOSITORY_ENV: ${{ env.REPOSITORY }}
IMAGE_INPUT: ${{ inputs.image }}
TAG_INPUT: ${{ inputs.tag }}
BUILD_EXCLUDES_INPUT: ${{ inputs.build-excludes }}
DEFAULT_BUILD_EXCLUDES: ${{ env.DEFAULT_BUILD_EXCLUDES }}
run: |
#!/usr/bin/env bash
set -euo pipefail
EXCLUDES="${{ env.DEFAULT_BUILD_EXCLUDES }}"
if [ -n "${{ inputs.build-excludes }}" ]; then
EXCLUDES+=",${{ inputs.build-excludes }}"
EXCLUDES="${DEFAULT_BUILD_EXCLUDES}"
if [ -n "${BUILD_EXCLUDES_INPUT}" ]; then
EXCLUDES+=",${BUILD_EXCLUDES_INPUT}"
fi

if [ -n "${{ inputs.tag }}" ]; then
echo "🔖 Tag '${{ inputs.tag }}' provided — skipping hash computation."
IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${{ inputs.tag }}"
TAG="${{ inputs.tag }}"
if [ -n "${TAG_INPUT}" ]; then
echo "🔖 Tag '${TAG_INPUT}' provided — skipping hash computation."
IMAGE="${REGISTRY_INPUT}/${PROJECT_INPUT}/${REPOSITORY_ENV}/${IMAGE_INPUT}:${TAG_INPUT}"
TAG="${TAG_INPUT}"
EXISTS="false" # Assume not built yet — can still be checked later if desired
else
# Enable extended globbing and recursive globs (**)
@@ -289,7 +292,7 @@
# Compute deterministic content-based hash
TAG=$("${FIND_CMD[@]}" -exec sha256sum {} \; | sort | sha256sum | cut -d' ' -f1)

IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${TAG}"
IMAGE="${REGISTRY_INPUT}/${PROJECT_INPUT}/${REPOSITORY_ENV}/${IMAGE_INPUT}:${TAG}"

# Check if image exists in registry
if docker manifest inspect "$IMAGE" >/dev/null 2>&1; then
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ inputs.tag }
, which may be controlled by an external user.

Copilot Autofix

AI 4 months ago

To fix this issue, the interpolation of the user-controlled ${{ inputs.tag }} (and similarly any other untrusted input variables) in the shell commands within the workflow should be replaced by passing these values as environment variables to the shell, then using proper shell variable syntax ("$TAG" instead of ${{ ... }}) in the script. This prevents interpretation of malicious shell content by the shell, mitigating injection attacks.

Specifically:

  • On line 273 and possibly other lines inside this workflow step, instead of writing IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${{ inputs.tag }}" directly in the shell, define all untrusted inputs (e.g., inputs.tag, etc.) as step-level environment variables.
  • Reference these env variables using shell syntax ($TAG, $REGISTRY, etc.) within the script.
  • Edit the affected step, rearranging the environment variables as needed.

You only need to update the block for the affected step. You may also need to update related lines inside the same shell block to use the new env variable names if other untrusted inputs are interpolated directly.


Suggested changeset 1
.github/workflows/docker.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -260,18 +260,26 @@
 
       - name: Compute hash and check if image exists
         id: compute_hash
+        env:
+          REGISTRY: ${{ inputs.registry }}
+          PROJECT: ${{ inputs.project }}
+          REPOSITORY: ${{ env.REPOSITORY }}
+          IMAGE_NAME: ${{ inputs.image }}
+          TAG_INPUT: ${{ inputs.tag }}
+          DEFAULT_BUILD_EXCLUDES: ${{ env.DEFAULT_BUILD_EXCLUDES }}
+          BUILD_EXCLUDES: ${{ inputs.build-excludes }}
         run: |
           #!/usr/bin/env bash
           set -euo pipefail
-          EXCLUDES="${{ env.DEFAULT_BUILD_EXCLUDES }}"
-          if [ -n "${{ inputs.build-excludes }}" ]; then
-            EXCLUDES+=",${{ inputs.build-excludes }}"
+          EXCLUDES="$DEFAULT_BUILD_EXCLUDES"
+          if [ -n "$BUILD_EXCLUDES" ]; then
+            EXCLUDES+=",$BUILD_EXCLUDES"
           fi
 
-          if [ -n "${{ inputs.tag }}" ]; then
-            echo "🔖 Tag '${{ inputs.tag }}' provided — skipping hash computation."
-            IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${{ inputs.tag }}"
-            TAG="${{ inputs.tag }}"
+          if [ -n "$TAG_INPUT" ]; then
+            echo "🔖 Tag '$TAG_INPUT' provided — skipping hash computation."
+            IMAGE="$REGISTRY/$PROJECT/$REPOSITORY/$IMAGE_NAME:$TAG_INPUT"
+            TAG="$TAG_INPUT"
             EXISTS="false" # Assume not built yet — can still be checked later if desired
           else
             # Enable extended globbing and recursive globs (**)
@@ -289,7 +292,7 @@
             # Compute deterministic content-based hash
             TAG=$("${FIND_CMD[@]}" -exec sha256sum {} \; | sort | sha256sum | cut -d' ' -f1)
 
-            IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${TAG}"
+            IMAGE="$REGISTRY/$PROJECT/$REPOSITORY/$IMAGE_NAME:$TAG"
 
             # Check if image exists in registry
             if docker manifest inspect "$IMAGE" >/dev/null 2>&1; then
EOF
@@ -260,18 +260,26 @@

- name: Compute hash and check if image exists
id: compute_hash
env:
REGISTRY: ${{ inputs.registry }}
PROJECT: ${{ inputs.project }}
REPOSITORY: ${{ env.REPOSITORY }}
IMAGE_NAME: ${{ inputs.image }}
TAG_INPUT: ${{ inputs.tag }}
DEFAULT_BUILD_EXCLUDES: ${{ env.DEFAULT_BUILD_EXCLUDES }}
BUILD_EXCLUDES: ${{ inputs.build-excludes }}
run: |
#!/usr/bin/env bash
set -euo pipefail
EXCLUDES="${{ env.DEFAULT_BUILD_EXCLUDES }}"
if [ -n "${{ inputs.build-excludes }}" ]; then
EXCLUDES+=",${{ inputs.build-excludes }}"
EXCLUDES="$DEFAULT_BUILD_EXCLUDES"
if [ -n "$BUILD_EXCLUDES" ]; then
EXCLUDES+=",$BUILD_EXCLUDES"
fi

if [ -n "${{ inputs.tag }}" ]; then
echo "🔖 Tag '${{ inputs.tag }}' provided — skipping hash computation."
IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${{ inputs.tag }}"
TAG="${{ inputs.tag }}"
if [ -n "$TAG_INPUT" ]; then
echo "🔖 Tag '$TAG_INPUT' provided — skipping hash computation."
IMAGE="$REGISTRY/$PROJECT/$REPOSITORY/$IMAGE_NAME:$TAG_INPUT"
TAG="$TAG_INPUT"
EXISTS="false" # Assume not built yet — can still be checked later if desired
else
# Enable extended globbing and recursive globs (**)
@@ -289,7 +292,7 @@
# Compute deterministic content-based hash
TAG=$("${FIND_CMD[@]}" -exec sha256sum {} \; | sort | sha256sum | cut -d' ' -f1)

IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${TAG}"
IMAGE="$REGISTRY/$PROJECT/$REPOSITORY/$IMAGE_NAME:$TAG"

# Check if image exists in registry
if docker manifest inspect "$IMAGE" >/dev/null 2>&1; then
Copilot is powered by AI and may make mistakes. Always verify output.
TAG="${{ inputs.tag }}"

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ inputs.tag }
, which may be controlled by an external user.

Copilot Autofix

AI 4 months ago

To fix the code injection vulnerability, do not interpolate untrusted values (like ${{ inputs.tag }}) directly into shell variable assignments in the script block. The safe approach is to set the value as an environment variable (using the env: key in the workflow step), and reference the variable using shell-native syntax ($TAG) within the script instead of GHA expression syntax. Specifically, in the step "Compute hash and check if image exists", set an environment variable named TAG to ${{ inputs.tag }} and reference it using $TAG in the script. Apply the same fix for other interpolated untrusted input variables as needed. Edit the relevant lines within the .github/workflows/docker.yml workflow; add the env: field to the affected step and update the script block to use the environment variable.

Suggested changeset 1
.github/workflows/docker.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -260,6 +260,8 @@
 
       - name: Compute hash and check if image exists
         id: compute_hash
+        env:
+          INPUTS_TAG: ${{ inputs.tag }}
         run: |
           #!/usr/bin/env bash
           set -euo pipefail
@@ -268,10 +270,10 @@
             EXCLUDES+=",${{ inputs.build-excludes }}"
           fi
 
-          if [ -n "${{ inputs.tag }}" ]; then
-            echo "🔖 Tag '${{ inputs.tag }}' provided — skipping hash computation."
-            IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${{ inputs.tag }}"
-            TAG="${{ inputs.tag }}"
+          if [ -n "$INPUTS_TAG" ]; then
+            echo "🔖 Tag '$INPUTS_TAG' provided — skipping hash computation."
+            IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:$INPUTS_TAG"
+            TAG="$INPUTS_TAG"
             EXISTS="false" # Assume not built yet — can still be checked later if desired
           else
             # Enable extended globbing and recursive globs (**)
EOF
@@ -260,6 +260,8 @@

- name: Compute hash and check if image exists
id: compute_hash
env:
INPUTS_TAG: ${{ inputs.tag }}
run: |
#!/usr/bin/env bash
set -euo pipefail
@@ -268,10 +270,10 @@
EXCLUDES+=",${{ inputs.build-excludes }}"
fi

if [ -n "${{ inputs.tag }}" ]; then
echo "🔖 Tag '${{ inputs.tag }}' provided — skipping hash computation."
IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${{ inputs.tag }}"
TAG="${{ inputs.tag }}"
if [ -n "$INPUTS_TAG" ]; then
echo "🔖 Tag '$INPUTS_TAG' provided — skipping hash computation."
IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:$INPUTS_TAG"
TAG="$INPUTS_TAG"
EXISTS="false" # Assume not built yet — can still be checked later if desired
else
# Enable extended globbing and recursive globs (**)
Copilot is powered by AI and may make mistakes. Always verify output.
EXISTS="false" # Assume not built yet — can still be checked later if desired
else
# Enable extended globbing and recursive globs (**)
shopt -s globstar extglob nullglob

# Build find command dynamically
FIND_CMD=(find . -type f)

IFS=',' read -ra PATTERNS <<<"$EXCLUDES"
for pattern in "${PATTERNS[@]}"; do
pattern=$(echo "$pattern" | xargs)
[[ -n $pattern ]] && FIND_CMD+=(! -path "./$pattern")
done

# Compute deterministic content-based hash
TAG=$("${FIND_CMD[@]}" -exec sha256sum {} \; | sort | sha256sum | cut -d' ' -f1)

IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${TAG}"

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ inputs.registry }
, which may be controlled by an external user.

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ inputs.project }
, which may be controlled by an external user.

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ env.REPOSITORY }
, which may be controlled by an external user.
Potential code injection in
${ env.REPOSITORY }
, which may be controlled by an external user.
Potential code injection in
${ env.REPOSITORY }
, which may be controlled by an external user.

Copilot Autofix

AI 4 months ago

The safest and most robust fix is to avoid injecting untrusted input with ${{ ... }} syntax inside any shell commands, as this can enable code injection.
Instead, use environment variables for all untrusted inputs:

  • In the YAML step, place the untrusted input value into an environment variable via the env: key.
  • Inside the shell script, use shell native syntax ($REPOSITORY) for variable expansion, not ${{ env.REPOSITORY }}.
  • Update line 292 in the workflow, replacing ${{ env.REPOSITORY }} with $REPOSITORY.

To implement:

  • In .github/workflows/docker.yml, edit line 292 so that the shell assignment to IMAGE uses $REPOSITORY instead of ${{ env.REPOSITORY }}.
  • No new imports, just edit inside the shell script block.

Suggested changeset 1
.github/workflows/docker.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -289,7 +289,7 @@
             # Compute deterministic content-based hash
             TAG=$("${FIND_CMD[@]}" -exec sha256sum {} \; | sort | sha256sum | cut -d' ' -f1)
 
-            IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${TAG}"
+            IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${REPOSITORY}/${{ inputs.image }}:${TAG}"
 
             # Check if image exists in registry
             if docker manifest inspect "$IMAGE" >/dev/null 2>&1; then
EOF
@@ -289,7 +289,7 @@
# Compute deterministic content-based hash
TAG=$("${FIND_CMD[@]}" -exec sha256sum {} \; | sort | sha256sum | cut -d' ' -f1)

IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${TAG}"
IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${REPOSITORY}/${{ inputs.image }}:${TAG}"

# Check if image exists in registry
if docker manifest inspect "$IMAGE" >/dev/null 2>&1; then
Copilot is powered by AI and may make mistakes. Always verify output.

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ inputs.image }
, which may be controlled by an external user.

Copilot Autofix

AI 4 months ago

To fix this code injection vulnerability, the workflow should avoid injecting untrusted input directly into shell commands or variables using the ${{ ... }} expression. Instead, set the value to an environment variable in the env: section, and expand that environment variable using shell-native syntax ("$IMAGE" rather than "${{ inputs.image }}").

In detail:

  • Set each external/untrusted input (specifically, registry, project, image, and tag) to environment variables in the env: block of the corresponding shell step.
  • Use the environment variable references in shell ($IMAGE, $REGISTRY, $PROJECT, $TAG) rather than the ${{ ... }} expressions within the run script.
  • Refactor lines where their values are currently being interpolated using ${{ ... }} to use these environment variables.
  • This change should occur for all interpolations of those inputs within the script (not just line 292).
  • No imports are needed—this is pure GitHub Actions YAML/shell.

Suggested changeset 1
.github/workflows/docker.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -260,18 +260,24 @@
 
       - name: Compute hash and check if image exists
         id: compute_hash
+        env:
+          REGISTRY: ${{ inputs.registry }}
+          PROJECT: ${{ inputs.project }}
+          IMAGE: ${{ inputs.image }}
+          TAG_INPUT: ${{ inputs.tag }}
+          BUILD_EXCLUDES: ${{ inputs.build-excludes }}
         run: |
           #!/usr/bin/env bash
           set -euo pipefail
           EXCLUDES="${{ env.DEFAULT_BUILD_EXCLUDES }}"
-          if [ -n "${{ inputs.build-excludes }}" ]; then
-            EXCLUDES+=",${{ inputs.build-excludes }}"
+          if [ -n "$BUILD_EXCLUDES" ]; then
+            EXCLUDES+=",${BUILD_EXCLUDES}"
           fi
 
-          if [ -n "${{ inputs.tag }}" ]; then
-            echo "🔖 Tag '${{ inputs.tag }}' provided — skipping hash computation."
-            IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${{ inputs.tag }}"
-            TAG="${{ inputs.tag }}"
+          if [ -n "$TAG_INPUT" ]; then
+            echo "🔖 Tag '$TAG_INPUT' provided — skipping hash computation."
+            IMAGE_PATH="$REGISTRY/$PROJECT/${{ env.REPOSITORY }}/$IMAGE:$TAG_INPUT"
+            TAG="$TAG_INPUT"
             EXISTS="false" # Assume not built yet — can still be checked later if desired
           else
             # Enable extended globbing and recursive globs (**)
@@ -289,29 +289,29 @@
             # Compute deterministic content-based hash
             TAG=$("${FIND_CMD[@]}" -exec sha256sum {} \; | sort | sha256sum | cut -d' ' -f1)
 
-            IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${TAG}"
+            IMAGE_PATH="$REGISTRY/$PROJECT/${{ env.REPOSITORY }}/$IMAGE:$TAG"
 
             # Check if image exists in registry
-            if docker manifest inspect "$IMAGE" >/dev/null 2>&1; then
-              echo "✅ Image $IMAGE already exists - skipping build"
+            if docker manifest inspect "$IMAGE_PATH" >/dev/null 2>&1; then
+              echo "✅ Image $IMAGE_PATH already exists - skipping build"
               EXISTS="true"
             else
-              echo "🚀 Image $IMAGE not found — proceed to build"
+              echo "🚀 Image $IMAGE_PATH not found — proceed to build"
               EXISTS="false"
             fi
           fi
 
           # Export values for GitHub Actions
           {
-            echo "image=${IMAGE}"
+            echo "image=${IMAGE_PATH}"
             echo "image_exists=${EXISTS}"
             echo "tag=${TAG}"
           } >> "$GITHUB_ENV"
 
-          echo "image=${IMAGE}" >> "$GITHUB_OUTPUT"
+          echo "image=${IMAGE_PATH}" >> "$GITHUB_OUTPUT"
 
           # Print for debugging
-          echo "IMAGE=${IMAGE}"
+          echo "IMAGE=${IMAGE_PATH}"
           echo "EXISTS=${EXISTS}"
 
       - name: Print results
EOF
@@ -260,18 +260,24 @@

- name: Compute hash and check if image exists
id: compute_hash
env:
REGISTRY: ${{ inputs.registry }}
PROJECT: ${{ inputs.project }}
IMAGE: ${{ inputs.image }}
TAG_INPUT: ${{ inputs.tag }}
BUILD_EXCLUDES: ${{ inputs.build-excludes }}
run: |
#!/usr/bin/env bash
set -euo pipefail
EXCLUDES="${{ env.DEFAULT_BUILD_EXCLUDES }}"
if [ -n "${{ inputs.build-excludes }}" ]; then
EXCLUDES+=",${{ inputs.build-excludes }}"
if [ -n "$BUILD_EXCLUDES" ]; then
EXCLUDES+=",${BUILD_EXCLUDES}"
fi

if [ -n "${{ inputs.tag }}" ]; then
echo "🔖 Tag '${{ inputs.tag }}' provided — skipping hash computation."
IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${{ inputs.tag }}"
TAG="${{ inputs.tag }}"
if [ -n "$TAG_INPUT" ]; then
echo "🔖 Tag '$TAG_INPUT' provided — skipping hash computation."
IMAGE_PATH="$REGISTRY/$PROJECT/${{ env.REPOSITORY }}/$IMAGE:$TAG_INPUT"
TAG="$TAG_INPUT"
EXISTS="false" # Assume not built yet — can still be checked later if desired
else
# Enable extended globbing and recursive globs (**)
@@ -289,29 +289,29 @@
# Compute deterministic content-based hash
TAG=$("${FIND_CMD[@]}" -exec sha256sum {} \; | sort | sha256sum | cut -d' ' -f1)

IMAGE="${{ inputs.registry }}/${{ inputs.project }}/${{ env.REPOSITORY }}/${{ inputs.image }}:${TAG}"
IMAGE_PATH="$REGISTRY/$PROJECT/${{ env.REPOSITORY }}/$IMAGE:$TAG"

# Check if image exists in registry
if docker manifest inspect "$IMAGE" >/dev/null 2>&1; then
echo "✅ Image $IMAGE already exists - skipping build"
if docker manifest inspect "$IMAGE_PATH" >/dev/null 2>&1; then
echo "✅ Image $IMAGE_PATH already exists - skipping build"
EXISTS="true"
else
echo "🚀 Image $IMAGE not found — proceed to build"
echo "🚀 Image $IMAGE_PATH not found — proceed to build"
EXISTS="false"
fi
fi

# Export values for GitHub Actions
{
echo "image=${IMAGE}"
echo "image=${IMAGE_PATH}"
echo "image_exists=${EXISTS}"
echo "tag=${TAG}"
} >> "$GITHUB_ENV"

echo "image=${IMAGE}" >> "$GITHUB_OUTPUT"
echo "image=${IMAGE_PATH}" >> "$GITHUB_OUTPUT"

# Print for debugging
echo "IMAGE=${IMAGE}"
echo "IMAGE=${IMAGE_PATH}"
echo "EXISTS=${EXISTS}"

- name: Print results
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated

# Check if image exists in registry
if docker manifest inspect "$IMAGE" >/dev/null 2>&1; then
echo "✅ Image $IMAGE already exists - skipping build"
EXISTS="true"
else
echo "🚀 Image $IMAGE not found — proceed to build"
EXISTS="false"
fi
fi

# Export values for GitHub Actions
{
echo "image=${IMAGE}"
echo "image_exists=${EXISTS}"
echo "tag=${TAG}"
} >> "$GITHUB_ENV"

echo "image=${IMAGE}" >> "$GITHUB_OUTPUT"

# Print for debugging
echo "IMAGE=${IMAGE}"
echo "EXISTS=${EXISTS}"

- name: Print results
run: |
echo "Computed tag: ${{ env.image }}"

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ env.image }
, which may be controlled by an external user.

Copilot Autofix

AI 4 months ago

To fix the potential code injection vulnerability, we should assign the value to an environment variable using the env: property of the step, and then reference that variable in the shell using the proper shell syntax ("$image"), not via GitHub Actions expression syntax. In this case, for the 'Print results' step, we will move ${{ env.image }} and ${{ env.image_exists }} into environment variables (e.g., IMAGE and IMAGE_EXISTS) using the env: key, and inside the shell script, reference them as "$IMAGE" and "$IMAGE_EXISTS". This prevents shell injection even if those values contain special characters.

Only the 'Print results' step (lines 317–321) needs updates: add an env: mapping, and change the script to use shell variables instead of ${{ env. ... }}.


Suggested changeset 1
.github/workflows/docker.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -315,9 +315,12 @@
           echo "EXISTS=${EXISTS}"
 
       - name: Print results
+        env:
+          IMAGE: ${{ env.image }}
+          IMAGE_EXISTS: ${{ env.image_exists }}
         run: |
-          echo "Computed tag: ${{ env.image }}"
-          echo "Image exists: ${{ env.image_exists }}"
+          echo "Computed tag: $IMAGE"
+          echo "Image exists: $IMAGE_EXISTS"
 
       - name: Extract metadata (tags, labels) for Docker
         id: meta
EOF
@@ -315,9 +315,12 @@
echo "EXISTS=${EXISTS}"

- name: Print results
env:
IMAGE: ${{ env.image }}
IMAGE_EXISTS: ${{ env.image_exists }}
run: |
echo "Computed tag: ${{ env.image }}"
echo "Image exists: ${{ env.image_exists }}"
echo "Computed tag: $IMAGE"
echo "Image exists: $IMAGE_EXISTS"

- name: Extract metadata (tags, labels) for Docker
id: meta
Copilot is powered by AI and may make mistakes. Always verify output.
echo "Image exists: ${{ env.image_exists }}"

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ env.image_exists }
, which may be controlled by an external user.

Copilot Autofix

AI 4 months ago

To fix the code injection risk, the variable ${{ env.image_exists }} should not be interpolated directly using expression syntax in the run: block. Instead, pass the value as an environment variable and then reference it via shell-native variable expansion (i.e., $image_exists). Specifically, in the .github/workflows/docker.yml file, modify the relevant step ("Print results") to set an environment variable, then use the shell's $image_exists syntax when echoing the value. No behavioral change is introduced; the fix simply ensures that any injected meta-characters cannot be interpreted by the shell.


Suggested changeset 1
.github/workflows/docker.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -315,9 +315,11 @@
           echo "EXISTS=${EXISTS}"
 
       - name: Print results
+        env:
+          IMAGE_EXISTS: ${{ env.image_exists }}
         run: |
           echo "Computed tag: ${{ env.image }}"
-          echo "Image exists: ${{ env.image_exists }}"
+          echo "Image exists: $IMAGE_EXISTS"
 
       - name: Extract metadata (tags, labels) for Docker
         id: meta
EOF
@@ -315,9 +315,11 @@
echo "EXISTS=${EXISTS}"

- name: Print results
env:
IMAGE_EXISTS: ${{ env.image_exists }}
run: |
echo "Computed tag: ${{ env.image }}"
echo "Image exists: ${{ env.image_exists }}"
echo "Image exists: $IMAGE_EXISTS"

- name: Extract metadata (tags, labels) for Docker
id: meta
Copilot is powered by AI and may make mistakes. Always verify output.

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
Expand All @@ -262,6 +330,7 @@

- name: Build (and push) Docker image
uses: docker/build-push-action@v5
if: env.image_exists == 'false'
with:
context: ${{ inputs.context }}
push: ${{ inputs.push }}
Expand All @@ -275,7 +344,9 @@
BUILD_COMMIT=${{ github.sha }}
BUILD_REPO=${{ github.event.repository.name }}
BUILD_ID=${{ github.run_id }}
tags: ${{ steps.meta.outputs.tags }}
tags: |
${{ steps.meta.outputs.tags }}
${{ env.image }}
labels: ${{ steps.meta.outputs.labels }}
target: ${{ inputs.target }}
ssh: default
Expand Down