Skip to content

Security: fix script injection via untrusted PR contexts in GitHub Actions workflows - #7658

Merged
nvuillam merged 4 commits into
mainfrom
copilot/fix-github-actions-script-injection
Apr 30, 2026
Merged

Security: fix script injection via untrusted PR contexts in GitHub Actions workflows#7658
nvuillam merged 4 commits into
mainfrom
copilot/fix-github-actions-script-injection

Conversation

Copilot AI commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

Untrusted user-controlled contexts (github.event.pull_request.title, github.head_ref, github.event.pull_request.head.repo.full_name) were interpolated directly into run: shell steps via ${{ }}, allowing arbitrary command execution via a crafted branch name or PR title.

Fix

Moved all untrusted contexts into env: blocks so GitHub assigns them as data before the shell runs, preventing injection regardless of content.

Before:

run: |
  GITHUB_BRANCH=$([ "${{ github.event_name }}" == "pull_request" ] && echo "${{ github.head_ref }}" || echo "${{ github.ref_name }}")

After:

env:
  EVENT_NAME: ${{ github.event_name }}
  HEAD_REF: ${{ github.head_ref }}
  REF_NAME: ${{ github.ref_name }}
run: |
  GITHUB_BRANCH=$([ "$EVENT_NAME" == "pull_request" ] && echo "$HEAD_REF" || echo "$REF_NAME")

Affected locations

  • deploy-DEV-linters.ymlget-title step (github.event.pull_request.title) and Run Test Cases step (github.head_ref)
  • deploy-DEV.ymlRun Test Cases step (github.head_ref)
  • deploy-RELEASE-linters.ymlRun Test Cases step (github.head_ref)
  • deploy-BETA-linters.ymlRun Test Cases step (github.head_ref)

Copilot AI changed the title [WIP] Fix GitHub Actions script injection vulnerability in workflows Security: fix script injection via untrusted PR contexts in GitHub Actions workflows Apr 30, 2026
Copilot AI requested a review from nvuillam April 30, 2026 05:06
@nvuillam
nvuillam marked this pull request as ready for review April 30, 2026 05:24
@nvuillam
nvuillam requested a review from Copilot April 30, 2026 05:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens multiple GitHub Actions workflows against shell-script injection by avoiding direct interpolation of untrusted PR-controlled contexts in run: steps and instead passing them via env:.

Changes:

  • Moved github.* PR contexts (e.g., github.head_ref, PR head repo, PR title) from inline ${{ }} usage in shell scripts into env: variables.
  • Updated branch/repo selection logic in “Run Test Cases” steps to use the new environment variables.
  • Updated the “Get PR title or commit message” step to use env-provided values.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

File Description
.github/workflows/deploy-RELEASE-linters.yml Moves PR-related contexts into env: for the test step to avoid inline expression interpolation in bash.
.github/workflows/deploy-DEV.yml Moves PR-related contexts into env: for the test step; currently introduces a duplicate env: key in the same step.
.github/workflows/deploy-DEV-linters.yml Moves PR title/commit message contexts into env: and updates the test step similarly.
.github/workflows/deploy-BETA-linters.yml Moves PR-related contexts into env: for the test step to avoid inline expression interpolation in bash.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/deploy-RELEASE-linters.yml
Comment thread .github/workflows/deploy-DEV.yml
Comment thread .github/workflows/deploy-DEV.yml
Comment thread .github/workflows/deploy-DEV-linters.yml
Comment thread .github/workflows/deploy-BETA-linters.yml
@github-actions

github-actions Bot commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

⚠️MegaLinter analysis: Success with warnings

⚠️ PYTHON / bandit - 83 errors
124:4
123	    )
124	    assert os.path.isdir(config.get(request_id, "DEFAULT_WORKSPACE")), (
125	        "DEFAULT_WORKSPACE "
126	        + config.get(request_id, "DEFAULT_WORKSPACE")
127	        + " is not a valid folder"
128	    )
129	

--------------------------------------------------
>> Issue: [B101:assert_used] Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
   Severity: Low   Confidence: High
   CWE: CWE-703 (https://cwe.mitre.org/data/definitions/703.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b101_assert_used.html
   Location: ./megalinter/utilstest.py:172:4
171	    tmp_report_folder = tempfile.gettempdir() + os.path.sep + str(uuid.uuid4())
172	    assert os.path.isdir(workspace), f"Test folder {workspace} is not existing"
173	    linter_name = linter.linter_name

--------------------------------------------------
>> Issue: [B101:assert_used] Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
   Severity: Low   Confidence: High
   CWE: CWE-703 (https://cwe.mitre.org/data/definitions/703.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b101_assert_used.html
   Location: ./megalinter/utilstest.py:238:4
237	    tmp_report_folder = tempfile.gettempdir() + os.path.sep + str(uuid.uuid4())
238	    assert os.path.isdir(workspace), f"Test folder {workspace} is not existing"
239	    if os.path.isfile(workspace + os.path.sep + "no_test_failure"):

--------------------------------------------------
>> Issue: [B101:assert_used] Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
   Severity: Low   Confidence: High
   CWE: CWE-703 (https://cwe.mitre.org/data/definitions/703.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b101_assert_used.html
   Location: ./megalinter/utilstest.py:487:4
486	    )
487	    assert os.path.isdir(workspace), f"Test folder {workspace} is not existing"
488	    expected_file_name = ""

--------------------------------------------------
>> Issue: [B101:assert_used] Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
   Severity: Low   Confidence: High
   CWE: CWE-703 (https://cwe.mitre.org/data/definitions/703.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b101_assert_used.html
   Location: ./megalinter/utilstest.py:587:4
586	        workspace += os.path.sep + "bad"
587	    assert os.path.isdir(workspace), f"Test folder {workspace} is not existing"
588	    # Call linter

--------------------------------------------------
>> Issue: [B101:assert_used] Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
   Severity: Low   Confidence: High
   CWE: CWE-703 (https://cwe.mitre.org/data/definitions/703.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b101_assert_used.html
   Location: ./megalinter/utilstest.py:676:4
675	        workspace = workspace + os.path.sep + "fix"
676	    assert os.path.isdir(workspace), f"Test folder {workspace} is not existing"
677	

--------------------------------------------------
>> Issue: [B101:assert_used] Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
   Severity: Low   Confidence: High
   CWE: CWE-703 (https://cwe.mitre.org/data/definitions/703.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b101_assert_used.html
   Location: ./megalinter/utilstest.py:782:12
781	            ]
782	            assert (len(list(diffs))) > 0, f"No changes in the {file} file"
783	

--------------------------------------------------
>> Issue: [B108:hardcoded_tmp_directory] Probable insecure usage of temp file/directory.
   Severity: Medium   Confidence: Medium
   CWE: CWE-377 (https://cwe.mitre.org/data/definitions/377.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b108_hardcoded_tmp_directory.html
   Location: ./server/server.py:81:42
80	    if item.fileUploadId:
81	        uploaded_file_path = os.path.join("/tmp/server-files", item.fileUploadId)
82	        if not os.path.isdir(uploaded_file_path):

--------------------------------------------------
>> Issue: [B108:hardcoded_tmp_directory] Probable insecure usage of temp file/directory.
   Severity: Medium   Confidence: Medium
   CWE: CWE-377 (https://cwe.mitre.org/data/definitions/377.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b108_hardcoded_tmp_directory.html
   Location: ./server/server.py:103:38
102	    file_upload_id = "FILE_" + str(uuid1())
103	    uploaded_file_path = os.path.join("/tmp/server-files", file_upload_id)
104	    os.makedirs(uploaded_file_path)

--------------------------------------------------
>> Issue: [B108:hardcoded_tmp_directory] Probable insecure usage of temp file/directory.
   Severity: Medium   Confidence: Medium
   CWE: CWE-377 (https://cwe.mitre.org/data/definitions/377.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b108_hardcoded_tmp_directory.html
   Location: ./server/server_worker.py:98:34
97	        temp_dir = self.create_temp_dir()
98	        upload_dir = os.path.join("/tmp/server-files", file_upload_id)
99	        if os.path.exists(upload_dir):

--------------------------------------------------

Code scanned:
	Total lines of code: 18021
	Total lines skipped (#nosec): 0
	Total potential issues skipped due to specifically being disabled (e.g., #nosec BXXX): 0

Run metrics:
	Total issues (by severity):
		Undefined: 0
		Low: 50
		Medium: 24
		High: 9
	Total issues (by confidence):
		Undefined: 0
		Low: 16
		Medium: 20
		High: 47
Files skipped (0):

(Truncated to last 5714 characters out of 59007)
⚠️ BASH / bash-exec - 1 error
Results of bash-exec linter (version 5.3.3)
See documentation on https://megalinter.io/beta/descriptors/bash_bash_exec/
-----------------------------------------------

✅ [SUCCESS] .automation/build_schemas_doc.sh
✅ [SUCCESS] .automation/format-tables.sh
✅ [SUCCESS] .vscode/testlinter.sh
✅ [SUCCESS] build.sh
✅ [SUCCESS] entrypoint.sh
❌ [ERROR] sh/megalinter_exec
    Error: File:[sh/megalinter_exec] is not executable
⚠️ REPOSITORY / grype - 15 errors
[0000]  WARN no explicit name and version provided for directory source, deriving artifact ID from the given path (which is not ideal) from=syft
NAME       INSTALLED  FIXED IN  TYPE    VULNERABILITY        SEVERITY  EPSS          RISK   
minimatch  3.0.4      3.0.5     npm     GHSA-f8q6-p94x-37v3  High      0.5% (65th)   0.4    
minimatch  3.0.4      3.1.3     npm     GHSA-7r86-cg39-jmmj  High      < 0.1% (7th)  < 0.1  
minimatch  3.1.2      3.1.3     npm     GHSA-7r86-cg39-jmmj  High      < 0.1% (7th)  < 0.1  
minimatch  5.1.6      5.1.8     npm     GHSA-7r86-cg39-jmmj  High      < 0.1% (7th)  < 0.1  
minimatch  9.0.5      9.0.7     npm     GHSA-7r86-cg39-jmmj  High      < 0.1% (7th)  < 0.1  
minimatch  3.0.4      3.1.3     npm     GHSA-3ppc-4f35-3m26  High      < 0.1% (6th)  < 0.1  
minimatch  3.1.2      3.1.3     npm     GHSA-3ppc-4f35-3m26  High      < 0.1% (6th)  < 0.1  
minimatch  5.1.6      5.1.7     npm     GHSA-3ppc-4f35-3m26  High      < 0.1% (6th)  < 0.1  
minimatch  9.0.5      9.0.6     npm     GHSA-3ppc-4f35-3m26  High      < 0.1% (6th)  < 0.1  
minimatch  3.0.4      3.1.4     npm     GHSA-23c5-xmqv-rm74  High      < 0.1% (6th)  < 0.1  
minimatch  3.1.2      3.1.4     npm     GHSA-23c5-xmqv-rm74  High      < 0.1% (6th)  < 0.1  
minimatch  5.1.6      5.1.8     npm     GHSA-23c5-xmqv-rm74  High      < 0.1% (6th)  < 0.1  
minimatch  9.0.5      9.0.7     npm     GHSA-23c5-xmqv-rm74  High      < 0.1% (6th)  < 0.1  
gitpython  3.1.46     3.1.47    python  GHSA-rpm5-65cw-6hj4  High      N/A           N/A    
gitpython  3.1.46     3.1.47    python  GHSA-x2qx-6953-8485  High      N/A           N/A
[0070] ERROR discovered vulnerabilities at or above the severity threshold
⚠️ SPELL / lychee - 1 error
[ERROR] Error while loading config: Cannot load configuration file `.github/linters/lychee.toml`: Failed to parse configuration file

Caused by:
    TOML parse error at line 59, column 1
       |
    59 | exclude_mail = true
       | ^^^^^^^^^^^^
    unknown field `exclude_mail`, expected one of `files_from`, `verbose`, `no_progress`, `host_stats`, `extensions`, `default_extension`, `cache`, `max_cache_age`, `cache_exclude_status`, `dump`, `dump_inputs`, `archive`, `suggest`, `max_redirects`, `max_retries`, `min_tls`, `max_concurrency`, `host_concurrency`, `host_request_interval`, `threads`, `user_agent`, `insecure`, `scheme`, `offline`, `include`, `exclude`, `exclude_file`, `exclude_path`, `exclude_all_private`, `exclude_private`, `exclude_link_local`, `exclude_loopback`, `include_mail`, `remap`, `fallback_extensions`, `index_files`, `header`, `accept`, `include_fragments`, `timeout`, `retry_wait_time`, `method`, `base_url`, `root_dir`, `basic_auth`, `github_token`, `skip_missing`, `no_ignore`, `hidden`, `include_verbatim`, `glob_ignore_case`, `output`, `mode`, `format`, `generate`, `require_https`, `cookie_jar`, `include_wikilinks`, `preprocess`, `hosts`
    
See: https://github.com/lycheeverse/lychee/blob/lychee-v0.23.0/lychee.example.toml
⚠️ MARKDOWN / markdownlint - 333 errors
ngle-h1 Multiple top-level headings in the same document [Context: "IDE Configuration Reporter"]
docs/reporters/ConsoleReporter.md:5 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Console Reporter"]
docs/reporters/EmailReporter.md:5 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "E-mail Reporter"]
docs/reporters/FileIoReporter.md:5 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "File.io Reporter"]
docs/reporters/GitHubCommentReporter.md:6 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "GitHub Comment Reporter"]
docs/reporters/GitHubCommentReporter.md:27:196 error MD056/table-column-count Table column count [Expected: 4; Actual: 3; Too few cells, row will be missing data]
docs/reporters/GitHubCommentReporter.md:27:46 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubCommentReporter.md:27:174 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubCommentReporter.md:27:196 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubCommentReporter.md:28:179 error MD056/table-column-count Table column count [Expected: 4; Actual: 3; Too few cells, row will be missing data]
docs/reporters/GitHubCommentReporter.md:28:46 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubCommentReporter.md:28:160 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubCommentReporter.md:28:179 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubCommentReporter.md:29:159 error MD056/table-column-count Table column count [Expected: 4; Actual: 3; Too few cells, row will be missing data]
docs/reporters/GitHubCommentReporter.md:29:48 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubCommentReporter.md:29:143 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubCommentReporter.md:29:159 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubCommentReporter.md:30:171 error MD056/table-column-count Table column count [Expected: 4; Actual: 3; Too few cells, row will be missing data]
docs/reporters/GitHubCommentReporter.md:30:46 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubCommentReporter.md:30:152 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubCommentReporter.md:30:171 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/reporters/GitHubStatusReporter.md:6 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "GitHub Status Reporter"]
docs/reporters/GitlabCommentReporter.md:6 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Gitlab Comment Reporter"]
docs/reporters/JsonReporter.md:5 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "JSON Reporter"]
docs/reporters/MarkdownSummaryReporter.md:6 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Markdown Summary Reporter"]
docs/reporters/SarifReporter.md:6 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "SARIF Reporter (beta)"]
docs/reporters/TapReporter.md:5 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "TAP Reporter"]
docs/reporters/TextReporter.md:5 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Text Reporter"]
docs/reporters/UpdatedSourcesReporter.md:5 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Updated Sources Reporter"]
docs/special-thanks.md:9 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Special thanks"]
docs/special-thanks.md:23:3 error MD045/no-alt-text Images should have alternate text (alt text)
docs/sponsor.md:5 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Sponsoring"]
docs/supported-linters.md:9 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Supported Linters"]
mega-linter-runner/generators/mega-linter-custom-flavor/templates/README.md:63 error MD024/no-duplicate-heading Multiple headings with the same content [Context: "How to use the custom flavor"]
mega-linter-runner/README.md:27:274 error MD051/link-fragments Link fragments should be valid [Context: "[**apply formatting and auto-fixes**](#apply-fixes)"]
mega-linter-runner/README.md:27:217 error MD051/link-fragments Link fragments should be valid [Context: "[**reports in several formats**](#reports)"]
README.md:190:127 error MD051/link-fragments Link fragments should be valid [Context: "[many additional features](#mega-linter-vs-super-linter)"]
README.md:1807:3 error MD045/no-alt-text Images should have alternate text (alt text)

(Truncated to last 5714 characters out of 43699)
⚠️ YAML / prettier - 6 errors
codecov.yml 1ms (unchanged)
mega-linter-runner/.eslintrc.yml 6ms (unchanged)
mega-linter-runner/.mega-linter.yml 13ms (unchanged)
mega-linter-runner/generators/mega-linter-custom-flavor/templates/action.yml 8ms (unchanged)
mega-linter-runner/generators/mega-linter-custom-flavor/templates/check-new-megalinter-version.yml 16ms (unchanged)
mega-linter-runner/generators/mega-linter-custom-flavor/templates/megalinter-custom-flavor-builder.yml 26ms (unchanged)
[error] mega-linter-runner/generators/mega-linter-custom-flavor/templates/megalinter-custom-flavor.yml: SyntaxError: Implicit map keys need to be followed by map values (6:1)
[error]   4 | label: <%= CUSTOM_FLAVOR_LABEL %>
[error]   5 | linters:
[error] > 6 | <%= CUSTOM_FLAVOR_LINTERS %>
[error]     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error]   7 |
mega-linter-runner/generators/mega-linter/templates/.drone.yml 5ms (unchanged)
mega-linter-runner/generators/mega-linter/templates/.gitlab-ci.yml 9ms (unchanged)
mega-linter-runner/generators/mega-linter/templates/azure-pipelines.yml 8ms (unchanged)
mega-linter-runner/generators/mega-linter/templates/bitbucket-pipelines.yml 4ms (unchanged)
mega-linter-runner/generators/mega-linter/templates/concourse-task.yml 6ms (unchanged)
mega-linter-runner/generators/mega-linter/templates/mega-linter.yml 20ms (unchanged)
megalinter/descriptors/action.megalinter-descriptor.yml 6ms (unchanged)
megalinter/descriptors/ansible.megalinter-descriptor.yml 9ms (unchanged)
megalinter/descriptors/api.megalinter-descriptor.yml 10ms (unchanged)
megalinter/descriptors/arm.megalinter-descriptor.yml 9ms (unchanged)
megalinter/descriptors/bash.megalinter-descriptor.yml 37ms (unchanged)
megalinter/descriptors/bicep.megalinter-descriptor.yml 4ms (unchanged)
megalinter/descriptors/c.megalinter-descriptor.yml 9ms (unchanged)
megalinter/descriptors/clojure.megalinter-descriptor.yml 13ms (unchanged)
megalinter/descriptors/cloudformation.megalinter-descriptor.yml 6ms (unchanged)
megalinter/descriptors/coffee.megalinter-descriptor.yml 6ms (unchanged)
megalinter/descriptors/copypaste.megalinter-descriptor.yml 6ms (unchanged)
megalinter/descriptors/cpp.megalinter-descriptor.yml 19ms (unchanged)
megalinter/descriptors/csharp.megalinter-descriptor.yml 18ms (unchanged)
megalinter/descriptors/css.megalinter-descriptor.yml 8ms (unchanged)
megalinter/descriptors/dart.megalinter-descriptor.yml 7ms (unchanged)
megalinter/descriptors/dockerfile.megalinter-descriptor.yml 13ms (unchanged)
megalinter/descriptors/editorconfig.megalinter-descriptor.yml 9ms (unchanged)
megalinter/descriptors/env.megalinter-descriptor.yml 5ms (unchanged)
megalinter/descriptors/gherkin.megalinter-descriptor.yml 6ms (unchanged)
megalinter/descriptors/go.megalinter-descriptor.yml 19ms (unchanged)
megalinter/descriptors/graphql.megalinter-descriptor.yml 6ms (unchanged)
megalinter/descriptors/groovy.megalinter-descriptor.yml 5ms (unchanged)
megalinter/descriptors/html.megalinter-descriptor.yml 13ms (unchanged)
megalinter/descriptors/java.megalinter-descriptor.yml 14ms (unchanged)
megalinter/descriptors/javascript.megalinter-descriptor.yml 38ms (unchanged)
megalinter/descriptors/json.megalinter-descriptor.yml 68ms (unchanged)
megalinter/descriptors/jsx.megalinter-descriptor.yml 16ms (unchanged)
megalinter/descriptors/kotlin.megalinter-descriptor.yml 6ms (unchanged)
megalinter/descriptors/kubernetes.megalinter-descriptor.yml 7ms (unchanged)
megalinter/descriptors/latex.megalinter-descriptor.yml 7ms (unchanged)
megalinter/descriptors/lua.megalinter-descriptor.yml 19ms (unchanged)
megalinter/descriptors/makefile.megalinter-descriptor.yml 4ms (unchanged)
megalinter/descriptors/markdown.megalinter-descriptor.yml 24ms (unchanged)
megalinter/descriptors/perl.megalinter-descriptor.yml 7ms (unchanged)
megalinter/descriptors/php.megalinter-descriptor.yml 42ms (unchanged)
megalinter/descriptors/powershell.megalinter-descriptor.yml 16ms (unchanged)
megalinter/descriptors/protobuf.megalinter-descriptor.yml 11ms (unchanged)
megalinter/descriptors/puppet.megalinter-descriptor.yml 10ms (unchanged)
megalinter/descriptors/python.megalinter-descriptor.yml 59ms (unchanged)
megalinter/descriptors/r.megalinter-descriptor.yml 11ms (unchanged)
megalinter/descriptors/raku.megalinter-descriptor.yml 7ms (unchanged)
megalinter/descriptors/repository.megalinter-descriptor.yml 89ms (unchanged)
megalinter/descriptors/robotframework.megalinter-descriptor.yml 8ms (unchanged)
megalinter/descriptors/rst.megalinter-descriptor.yml 17ms (unchanged)
megalinter/descriptors/ruby.megalinter-descriptor.yml 9ms (unchanged)
megalinter/descriptors/rust.megalinter-descriptor.yml 9ms (unchanged)
megalinter/descriptors/salesforce.megalinter-descriptor.yml 64ms (unchanged)
megalinter/descriptors/scala.megalinter-descriptor.yml 6ms (unchanged)
megalinter/descriptors/snakemake.megalinter-descriptor.yml 12ms (unchanged)
megalinter/descriptors/spell.megalinter-descriptor.yml 40ms (unchanged)
megalinter/descriptors/sql.megalinter-descriptor.yml 6ms (unchanged)
megalinter/descriptors/swift.megalinter-descriptor.yml 6ms (unchanged)
megalinter/descriptors/tekton.megalinter-descriptor.yml 9ms (unchanged)
megalinter/descriptors/terraform.megalinter-descriptor.yml 17ms (unchanged)
megalinter/descriptors/tsx.megalinter-descriptor.yml 12ms (unchanged)
megalinter/descriptors/typescript.megalinter-descriptor.yml 32ms (unchanged)
megalinter/descriptors/vbdotnet.megalinter-descriptor.yml 5ms (unchanged)
megalinter/descriptors/xml.megalinter-descriptor.yml 9ms (unchanged)
megalinter/descriptors/yaml.megalinter-descriptor.yml 32ms (unchanged)
server/docker-compose-dev.yml 7ms (unchanged)
server/docker-compose.yml 9ms (unchanged)
trivy-secret.yaml 1ms (unchanged)

(Truncated to last 5714 characters out of 11509)
⚠️ YAML / yamllint - 31 errors
mega-linter-runner/.eslintrc.yml
  11:9      warning  too few spaces inside empty braces  (braces)

mega-linter-runner/generators/mega-linter-custom-flavor/templates/megalinter-custom-flavor.yml
  7:1       error    syntax error: could not find expected ':' (syntax)

megalinter/descriptors/copypaste.megalinter-descriptor.yml
  18:301    warning  line too long (313 > 300 characters)  (line-length)

megalinter/descriptors/javascript.megalinter-descriptor.yml
  234:301   warning  line too long (307 > 300 characters)  (line-length)

megalinter/descriptors/markdown.megalinter-descriptor.yml
  74:301    warning  line too long (366 > 300 characters)  (line-length)

megalinter/descriptors/perl.megalinter-descriptor.yml
  26:301    warning  line too long (310 > 300 characters)  (line-length)

megalinter/descriptors/php.megalinter-descriptor.yml
  149:301   warning  line too long (389 > 300 characters)  (line-length)
  163:301   warning  line too long (302 > 300 characters)  (line-length)

megalinter/descriptors/repository.megalinter-descriptor.yml
  155:301   warning  line too long (408 > 300 characters)  (line-length)
  271:301   warning  line too long (306 > 300 characters)  (line-length)
  276:301   warning  line too long (321 > 300 characters)  (line-length)
  455:301   warning  line too long (338 > 300 characters)  (line-length)
  523:301   warning  line too long (306 > 300 characters)  (line-length)
  635:301   warning  line too long (316 > 300 characters)  (line-length)
  887:301   warning  line too long (1263 > 300 characters)  (line-length)
  954:301   warning  line too long (879 > 300 characters)  (line-length)
  968:301   warning  line too long (358 > 300 characters)  (line-length)
  1024:301  warning  line too long (346 > 300 characters)  (line-length)
  1031:301  warning  line too long (307 > 300 characters)  (line-length)

megalinter/descriptors/salesforce.megalinter-descriptor.yml
  51:301    warning  line too long (359 > 300 characters)  (line-length)
  310:301   warning  line too long (359 > 300 characters)  (line-length)

megalinter/descriptors/spell.megalinter-descriptor.yml
  149:301   warning  line too long (315 > 300 characters)  (line-length)

megalinter/descriptors/sql.megalinter-descriptor.yml
  64:301    warning  line too long (319 > 300 characters)  (line-length)

megalinter/descriptors/terraform.megalinter-descriptor.yml
  27:301    warning  line too long (330 > 300 characters)  (line-length)
  86:301    warning  line too long (391 > 300 characters)  (line-length)
  142:301   warning  line too long (346 > 300 characters)  (line-length)
  199:301   warning  line too long (328 > 300 characters)  (line-length)

megalinter/descriptors/typescript.megalinter-descriptor.yml
  225:301   warning  line too long (314 > 300 characters)  (line-length)

mkdocs.yml
  8:301     warning  line too long (552 > 300 characters)  (line-length)
  66:5      warning  wrong indentation: expected 6 but found 4  (indentation)
  78:5      warning  wrong indentation: expected 6 but found 4  (indentation)

✅ Linters with no issues

black, checkov, cspell, flake8, git_diff, hadolint, isort, jscpd, jsonlint, markdown-table-formatter, mypy, npm-groovy-lint, osv-scanner, pylint, ruff, secretlint, shellcheck, shfmt, syft, trufflehog, v8r, v8r, xmllint

See detailed reports in MegaLinter artifacts

MegaLinter is graciously provided by OX Security
Show us your support by starring ⭐ the repository

@nvuillam

Copy link
Copy Markdown
Member

@copilot apply fixes from the pr review comments

…icate env blocks

Agent-Logs-Url: https://github.com/oxsecurity/megalinter/sessions/7cc1c034-9d55-4202-bb60-82458fc46929

Co-authored-by: nvuillam <17500430+nvuillam@users.noreply.github.com>

Copilot AI commented Apr 30, 2026

Copy link
Copy Markdown
Contributor Author

@copilot apply fixes from the pr review comments

Applied in commit af86442:

  • deploy-DEV.yml: Merged the duplicate env: blocks — COMMIT_MSG is now in the same single env: map as the other variables, so all env vars are available to the run: step.
  • All four files: Quoted ${GITHUB_REPOSITORY} and ${GITHUB_BRANCH} in the docker run invocations (e.g., -e GITHUB_REPOSITORY="${GITHUB_REPOSITORY}") to prevent argument-splitting or option-injection if the values contain whitespace or start with -.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Hardens several GitHub Actions workflows against shell command injection by preventing direct interpolation of untrusted PR contexts into run: scripts, and includes minor formatting updates in generated descriptor docs.

Changes:

  • Move untrusted GitHub contexts (github.head_ref, PR head repo, PR title, etc.) into env: and reference them as shell variables inside run: blocks.
  • Quote docker run -e ... values that may contain spaces/special characters (e.g., branch/repo).
  • Adjust some descriptor documentation formatting (autolink URLs, list indentation).

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
.github/workflows/deploy-DEV-linters.yml Uses env: indirection for PR title/head refs and for branch/repo selection in test step.
.github/workflows/deploy-DEV.yml Uses env: indirection for PR head refs and quotes docker run env values.
.github/workflows/deploy-BETA-linters.yml Uses env: indirection for PR head refs and quotes docker run env values.
.github/workflows/deploy-RELEASE-linters.yml Uses env: indirection for PR head refs and quotes docker run env values.
docs/descriptors/repository_trivy_sbom.md Formats disabled-reason URL as an autolink.
docs/descriptors/repository_trivy.md Formats disabled-reason URL as an autolink.
docs/descriptors/repository_kics.md Formats disabled-reason URL as an autolink.
docs/descriptors/lua_selene.md Formats disabled-reason URL as an autolink.
docs/descriptors/repository_gitleaks.md Adjusts list indentation around PR commit-scan env var examples.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +40 to 49
env:
EVENT_NAME: ${{ github.event_name }}
PR_TITLE: ${{ github.event.pull_request.title }}
HEAD_COMMIT_MSG: ${{ github.event.head_commit.message }}
run: |
if [ "${{ github.event_name }}" = "pull_request" ]; then
echo "title=${{ github.event.pull_request.title }}" >> $GITHUB_OUTPUT
if [ "$EVENT_NAME" = "pull_request" ]; then
echo "title=${PR_TITLE}" >> $GITHUB_OUTPUT
else
echo "title=${{ github.event.head_commit.message }}" >> $GITHUB_OUTPUT
echo "title=${HEAD_COMMIT_MSG}" >> $GITHUB_OUTPUT
fi
Comment on lines 16 to 20
_This linter has been disabled in this version_

_Disabled reason: https://github.com/aquasecurity/trivy/discussions/10425_
_Disabled reason: <https://github.com/aquasecurity/trivy/discussions/10425>_

**Trivy** is a comprehensive security scanner that detects vulnerabilities, misconfigurations, secrets, and license issues in container images, filesystems, and git repositories. It serves as an all-in-one security solution for modern development workflows.
Comment on lines 16 to 20
_This linter has been disabled in this version_

_Disabled reason: Supply chain compromise - https://socket.dev/blog/checkmarx-supply-chain-compromise_
_Disabled reason: Supply chain compromise - <https://socket.dev/blog/checkmarx-supply-chain-compromise>_

**KICS** (Keeping Infrastructure as Code Secure) is a comprehensive open-source security scanner that identifies security vulnerabilities, compliance issues, and infrastructure misconfigurations in Infrastructure as Code files. It serves as a critical tool for preventing security risks before deployment to production environments.
Comment on lines 10 to 14
_This linter has been disabled in this version_

_Disabled reason: https://github.com/Kampfkarren/selene/issues/662_
_Disabled reason: <https://github.com/Kampfkarren/selene/issues/662>_

**Selene** is a blazing-fast modern Lua linter written in Rust that provides comprehensive static analysis for Lua code. It offers extensive configurability and can be tailored to specific Lua environments like Roblox, World of Warcraft addons, or standard Lua.
Comment on lines 14 to +18
![disabled](https://shields.io/badge/-disabled-orange) [![GitHub stars](https://img.shields.io/github/stars/aquasecurity/trivy?cacheSeconds=3600)](https://github.com/aquasecurity/trivy) ![sarif](https://shields.io/badge/-SARIF-orange) [![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/aquasecurity/trivy?sort=semver)](https://github.com/aquasecurity/trivy/releases) [![GitHub last commit](https://img.shields.io/github/last-commit/aquasecurity/trivy)](https://github.com/aquasecurity/trivy/commits) [![GitHub commit activity](https://img.shields.io/github/commit-activity/y/aquasecurity/trivy)](https://github.com/aquasecurity/trivy/graphs/commit-activity/) [![GitHub contributors](https://img.shields.io/github/contributors/aquasecurity/trivy)](https://github.com/aquasecurity/trivy/graphs/contributors/)

_This linter has been disabled in this version_

_Disabled reason: https://github.com/aquasecurity/trivy/discussions/10425_
_Disabled reason: <https://github.com/aquasecurity/trivy/discussions/10425>_
Comment on lines +184 to +192
env:
EVENT_NAME: ${{ github.event_name }}
PR_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
GH_REPOSITORY: ${{ github.repository }}
HEAD_REF: ${{ github.head_ref }}
REF_NAME: ${{ github.ref_name }}
run: |
GITHUB_REPOSITORY=$([ "${{ github.event_name }}" == "pull_request" ] && echo "${{ github.event.pull_request.head.repo.full_name }}" || echo "${{ github.repository }}")
GITHUB_BRANCH=$([ "${{ github.event_name }}" == "pull_request" ] && echo "${{ github.head_ref }}" || echo "${{ github.ref_name }}")
GITHUB_REPOSITORY=$([ "$EVENT_NAME" == "pull_request" ] && echo "$PR_HEAD_REPO" || echo "$GH_REPOSITORY")
GITHUB_BRANCH=$([ "$EVENT_NAME" == "pull_request" ] && echo "$HEAD_REF" || echo "$REF_NAME")
Comment on lines 16 to 20
_This linter has been disabled in this version_

_Disabled reason: https://github.com/aquasecurity/trivy/discussions/10425_
_Disabled reason: <https://github.com/aquasecurity/trivy/discussions/10425>_

**Trivy SBOM** is a specialized component of Trivy that generates comprehensive Software Bill of Materials (SBOM) documents for enhanced supply chain security and compliance. It provides detailed inventory management for software components and dependencies.
Comment on lines 41 to 51
Example commands:

- Source commit SHA:
- Source commit SHA:
```bash
git rev-list -n 1 refs/remotes/origin/<source_branch>
```

- Target commit SHA:
- Target commit SHA:
```bash
git rev-parse refs/remotes/origin/<target_branch>
```
Comment on lines +45 to 49
if [ "$EVENT_NAME" = "pull_request" ]; then
echo "title=${PR_TITLE}" >> $GITHUB_OUTPUT
else
echo "title=${{ github.event.head_commit.message }}" >> $GITHUB_OUTPUT
echo "title=${HEAD_COMMIT_MSG}" >> $GITHUB_OUTPUT
fi
@nvuillam
nvuillam merged commit 9aa5d79 into main Apr 30, 2026
138 checks passed
@nvuillam
nvuillam deleted the copilot/fix-github-actions-script-injection branch April 30, 2026 06:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Security: GitHub Actions script injection via untrusted PR contexts

3 participants