Skip to content
Draft
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
82 changes: 74 additions & 8 deletions .github/workflows/go-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,74 @@
runs-on: ${{ inputs.os }}
steps:
- uses: actions/checkout@v4

- name: Get changed files
id: changed
uses: tj-actions/changed-files@v45

Check warning

Code scanning / CodeQL

Unpinned tag for a non-immutable Action in workflow Medium

Unpinned 3rd party Action 'Go checks' step
Uses Step: changed
uses 'tj-actions/changed-files' with ref 'v45', not a pinned commit hash
with:
separator: "\n"

- name: Check if only irrelevant files changed
id: check
run: |
#!/usr/bin/env bash
set -euo pipefail

# Enable extended and recursive globbing for better matching
shopt -s globstar extglob nullglob

# Define files or glob patterns considered "irrelevant"
EXCLUDED_PATTERNS=(
"nomad.hcl"
"Dockerfile"
"**.md"
"nomad.hcl"
"*nomad.variables.hcl"
"Dockerfile"
)
echo "🔍 Changed files:"
echo "${{ steps.changed.outputs.all_changed_files }}"

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ steps.changed.outputs.all_changed_files }
, which may be controlled by an external user.

Copilot Autofix

AI 4 months ago

To fix this code injection vulnerability, we should avoid placing ${{ steps.changed.outputs.all_changed_files }} directly inside shell commands. Instead, we should pass the value as an environment variable and reference it using native shell syntax ($ALL_CHANGED_FILES). Specifically, in the affected step, set up an env mapping:

env:
  ALL_CHANGED_FILES: ${{ steps.changed.outputs.all_changed_files }}

and then refer to $ALL_CHANGED_FILES in the shell script. This change should be made in the step named "Check if only irrelevant files changed," covering all uses of steps.changed.outputs.all_changed_files inside the run block.

The affected lines are:

  • 100: echo "${{ steps.changed.outputs.all_changed_files }}"
  • 123: done <<< "$(echo "${{ steps.changed.outputs.all_changed_files }}" | tr ',' '\n')"

These should both refer to the environment variable using the shell-native form:

  • On line 100, change to echo "$ALL_CHANGED_FILES"
  • On line 123, change to done <<< "$(echo "$ALL_CHANGED_FILES" | tr ',' '\n')"

We will also add the appropriate env mapping in the step definition.

Suggested changeset 1
.github/workflows/go-checks.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/go-checks.yml b/.github/workflows/go-checks.yml
--- a/.github/workflows/go-checks.yml
+++ b/.github/workflows/go-checks.yml
@@ -80,6 +80,8 @@
 
       - name: Check if only irrelevant files changed
         id: check
+        env:
+          ALL_CHANGED_FILES: ${{ steps.changed.outputs.all_changed_files }}
         run: |
           #!/usr/bin/env bash
           set -euo pipefail
@@ -97,7 +99,7 @@
              "Dockerfile"
           )
           echo "🔍 Changed files:"
-          echo "${{ steps.changed.outputs.all_changed_files }}"
+          echo "$ALL_CHANGED_FILES"
           echo
 
           ONLY_IRRELEVANT=true
@@ -120,7 +122,7 @@
               ONLY_IRRELEVANT=false
               break
             fi
-          done <<< "$(echo "${{ steps.changed.outputs.all_changed_files }}" | tr ',' '\n')"
+          done <<< "$(echo "$ALL_CHANGED_FILES" | tr ',' '\n')"
 
           echo "🔎 Result: only_irrelevant=$ONLY_IRRELEVANT"
           echo "only_irrelevant=$ONLY_IRRELEVANT" >> "$GITHUB_OUTPUT"
EOF
@@ -80,6 +80,8 @@

- name: Check if only irrelevant files changed
id: check
env:
ALL_CHANGED_FILES: ${{ steps.changed.outputs.all_changed_files }}
run: |
#!/usr/bin/env bash
set -euo pipefail
@@ -97,7 +99,7 @@
"Dockerfile"
)
echo "🔍 Changed files:"
echo "${{ steps.changed.outputs.all_changed_files }}"
echo "$ALL_CHANGED_FILES"
echo

ONLY_IRRELEVANT=true
@@ -120,7 +122,7 @@
ONLY_IRRELEVANT=false
break
fi
done <<< "$(echo "${{ steps.changed.outputs.all_changed_files }}" | tr ',' '\n')"
done <<< "$(echo "$ALL_CHANGED_FILES" | tr ',' '\n')"

echo "🔎 Result: only_irrelevant=$ONLY_IRRELEVANT"
echo "only_irrelevant=$ONLY_IRRELEVANT" >> "$GITHUB_OUTPUT"
Copilot is powered by AI and may make mistakes. Always verify output.
echo

ONLY_IRRELEVANT=true

# Normalize output: split on commas or newlines
while IFS= read -r FILE; do
FILE=$(echo "$FILE" | xargs) # trim whitespace
[[ -z "$FILE" ]] && continue

MATCHED=false
for PATTERN in "${EXCLUDED_PATTERNS[@]}"; do
if [[ "$FILE" == "$PATTERN" ]]; then
MATCHED=true
break
fi
done

if [[ "$MATCHED" == false ]]; then
echo "✅ Relevant file detected: $FILE"
ONLY_IRRELEVANT=false
break
fi
done <<< "$(echo "${{ steps.changed.outputs.all_changed_files }}" | tr ',' '\n')"

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ steps.changed.outputs.all_changed_files }
, which may be controlled by an external user.

Copilot Autofix

AI 4 months ago

To fix the issue, we need to avoid interpolating the untrusted input using ${{ ... }} directly in the shell context inside the run: block. The best practice is to pass the value to the shell via an intermediate environment variable (set via env:), and then reference it using $VARIABLE.

Steps to fix:

  • In the affected step (Check if only irrelevant files changed), under env:, add a variable like ALL_CHANGED_FILES: ${{ steps.changed.outputs.all_changed_files }}.
  • In the shell script, replace direct usage of ${{ steps.changed.outputs.all_changed_files }} with $ALL_CHANGED_FILES.
  • Specifically, the line:
    done <<< "$(echo "${{ steps.changed.outputs.all_changed_files }}" | tr ',' '\n')"
    
    should become:
    done <<< "$(echo "$ALL_CHANGED_FILES" | tr ',' '\n')"
    
  • Also, any other echo or usage of the same variable via ${{ ... }} should be updated to $ALL_CHANGED_FILES for consistency and safety.

No additional libraries are needed. You only need to add the environment variable definition and reference it using the shell’s $ syntax inside the script.


Suggested changeset 1
.github/workflows/go-checks.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/go-checks.yml b/.github/workflows/go-checks.yml
--- a/.github/workflows/go-checks.yml
+++ b/.github/workflows/go-checks.yml
@@ -80,6 +80,8 @@
 
       - name: Check if only irrelevant files changed
         id: check
+        env:
+          ALL_CHANGED_FILES: ${{ steps.changed.outputs.all_changed_files }}
         run: |
           #!/usr/bin/env bash
           set -euo pipefail
@@ -97,7 +99,7 @@
              "Dockerfile"
           )
           echo "🔍 Changed files:"
-          echo "${{ steps.changed.outputs.all_changed_files }}"
+          echo "$ALL_CHANGED_FILES"
           echo
 
           ONLY_IRRELEVANT=true
@@ -120,7 +122,7 @@
               ONLY_IRRELEVANT=false
               break
             fi
-          done <<< "$(echo "${{ steps.changed.outputs.all_changed_files }}" | tr ',' '\n')"
+          done <<< "$(echo "$ALL_CHANGED_FILES" | tr ',' '\n')"
 
           echo "🔎 Result: only_irrelevant=$ONLY_IRRELEVANT"
           echo "only_irrelevant=$ONLY_IRRELEVANT" >> "$GITHUB_OUTPUT"
EOF
@@ -80,6 +80,8 @@

- name: Check if only irrelevant files changed
id: check
env:
ALL_CHANGED_FILES: ${{ steps.changed.outputs.all_changed_files }}
run: |
#!/usr/bin/env bash
set -euo pipefail
@@ -97,7 +99,7 @@
"Dockerfile"
)
echo "🔍 Changed files:"
echo "${{ steps.changed.outputs.all_changed_files }}"
echo "$ALL_CHANGED_FILES"
echo

ONLY_IRRELEVANT=true
@@ -120,7 +122,7 @@
ONLY_IRRELEVANT=false
break
fi
done <<< "$(echo "${{ steps.changed.outputs.all_changed_files }}" | tr ',' '\n')"
done <<< "$(echo "$ALL_CHANGED_FILES" | tr ',' '\n')"

echo "🔎 Result: only_irrelevant=$ONLY_IRRELEVANT"
echo "only_irrelevant=$ONLY_IRRELEVANT" >> "$GITHUB_OUTPUT"
Copilot is powered by AI and may make mistakes. Always verify output.

echo "🔎 Result: only_irrelevant=$ONLY_IRRELEVANT"
echo "only_irrelevant=$ONLY_IRRELEVANT" >> "$GITHUB_OUTPUT"

- name: Skip if only irrelevant files changed
if: steps.check.outputs.only_irrelevant == 'true'
run: |
echo "🟡 Only README.md and/or nomad.hcl changed. Skipping workflow."

- run: echo "GO_VERSION=$(grep '^go ' < go.mod | awk '{print $2}')" >> "$GITHUB_ENV"
if: steps.check.outputs.only_irrelevant != 'true'
- uses: actions/setup-python@v5
if: steps.check.outputs.only_irrelevant != 'true'
- name: Setup pre-commit
run: python -m pip install pre-commit
if: steps.check.outputs.only_irrelevant != 'true'
- name: go modules cache
if: steps.check.outputs.only_irrelevant != 'true'
uses: actions/cache@v4
with:
path: |
Expand All @@ -85,6 +148,7 @@
restore-keys: |
${{ runner.os }}-go-mod-${{ github.job }}-
- name: go tools cache
if: steps.check.outputs.only_irrelevant != 'true'
uses: actions/cache@v4
with:
path: |
Expand All @@ -93,33 +157,35 @@
restore-keys: |
${{ runner.os }}-go-tools-${{ inputs.golang_version || env.GO_VERSION }}-${{ github.job }}
- uses: actions/setup-go@v5
if: steps.check.outputs.only_irrelevant != 'true'
with:
go-version: ${{ inputs.golang_version || env.GO_VERSION }}
- uses: ruby/setup-ruby@v1
with:
bundler-cache: true
ruby-version: "${{ inputs.lint-gen-ruby-version }}"
if: "${{ !inputs.no-lint-gen && inputs.lint-gen-ruby-version != '' }}"
if: "${{ !inputs.no-lint-gen && inputs.lint-gen-ruby-version != '' && steps.check.outputs.only_irrelevant != 'true'}}"

- uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: "${{ secrets.ssh_key }}"
if: "${{ inputs.goprivate != '' }}"
if: "${{ inputs.goprivate != ''&& steps.check.outputs.only_irrelevant != 'true' }}"

- name: Update Git config
run: |
curl -L https://api.github.com/meta | jq -r '.ssh_keys | .[]' | sed -e 's/^/github.com /' >> ~/.ssh/known_hosts
git config --global url."git@github.com:".insteadOf "https://github.com/"
if: "${{ inputs.goprivate != '' }}"
if: "${{ inputs.goprivate != '' && steps.check.outputs.only_irrelevant != 'true' }}"

- run: make ${{ inputs.lint-target }}
if: "${{ inputs.no-lint-gen }}"
if: "${{ inputs.no-lint-gen && steps.check.outputs.only_irrelevant != 'true' }}"
- run: make gen && git diff --exit-code --name-only HEAD
if: "${{ !inputs.no-lint-gen }}"
if: "${{ !inputs.no-lint-gen && steps.check.outputs.only_irrelevant != 'true' }}"
- run: 'docker compose -f "${{ inputs.compose-file }}" up -d --build && sleep ${{ inputs.compose-wait }}'
if: "${{ !inputs.no-compose && hashFiles(inputs.compose-file) != '' }}"
if: "${{ !inputs.no-compose && hashFiles(inputs.compose-file) != '' && steps.check.outputs.only_irrelevant != 'true' }}"
- run: make test-nocache
if: "${{ steps.check.outputs.only_irrelevant != 'true' && steps.check.outputs.only_irrelevant != 'true' }}"
- run: make race-nocache
if: "${{ !inputs.no-race }}"
if: "${{ !inputs.no-race && steps.check.outputs.only_irrelevant != 'true' }}"
- run: 'docker compose -f "${{ inputs.compose-file }}" down'
if: "${{ always() && !inputs.no-compose && hashFiles(inputs.compose-file) != '' }}"
if: "${{ always() && !inputs.no-compose && hashFiles(inputs.compose-file) != '' && steps.check.outputs.only_irrelevant != 'true' }}"