Skip to content

🔒 fix command injection in prepare-release.py#3717

Open
jkowall wants to merge 3 commits intojaegertracing:mainfrom
jkowall:fix-command-injection-prepare-release-15644608474505552789
Open

🔒 fix command injection in prepare-release.py#3717
jkowall wants to merge 3 commits intojaegertracing:mainfrom
jkowall:fix-command-injection-prepare-release-15644608474505552789

Conversation

@jkowall
Copy link
Copy Markdown
Contributor

@jkowall jkowall commented Apr 10, 2026

Summary

Fixes a command injection vulnerability in scripts/prepare-release.py.

Reference: earlier fork PR jkowall/jaeger-ui-F#24 is now closed in favor of this upstream draft.

What Changed

  • switched subprocess.run() usage from shell=True string commands to shell=False argument lists
  • enforced sequence input in run_command() to prevent future regressions
  • replaced bare except: handlers with targeted subprocess exceptions
  • suppressed stdout/stderr echoing for the secret-bearing gh auth token call
  • resolved the merge with main by keeping the new run_fmt() helper while preserving the security hardening

Why

The previous implementation built shell commands from interpolated strings, which allowed malicious input such as a crafted version string or commit message to trigger arbitrary command execution.

Validation

  • python3 -m py_compile scripts/prepare-release.py
  • npm run lint could not complete in this environment after merging main because the branch now expects vp
  • npm test could not complete in this environment because vitest is not installed
  • npm run build could not complete in this environment because merged main currently lacks required Zustand/Vitest dependencies here

google-labs-jules bot and others added 3 commits April 10, 2026 05:51
Refactor `run_command` in `scripts/prepare-release.py` to use
`shell=False` and pass arguments as a list to `subprocess.run`.
This prevents command injection vulnerabilities where shell characters
in variables like commit messages or branch names could be interpreted
by the shell.

All call sites of `run_command` have been updated accordingly.

Co-authored-by: jkowall <1859948+jkowall@users.noreply.github.com>
Signed-off-by: Jonah Kowall <jkowall@kowall.net>
…-prepare-release-15644608474505552789

# Conflicts:
#	scripts/prepare-release.py
jkowall added a commit to jkowall/jaeger-ui-F that referenced this pull request Apr 10, 2026
Acknowledged that this PR is being closed in favor of jaegertracing#3717.

Co-authored-by: jkowall <1859948+jkowall@users.noreply.github.com>
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.21%. Comparing base (6f319e2) to head (e344e94).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3717   +/-   ##
=======================================
  Coverage   89.21%   89.21%           
=======================================
  Files         330      330           
  Lines        9889     9889           
  Branches     2568     2568           
=======================================
  Hits         8822     8822           
  Misses        925      925           
  Partials      142      142           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jkowall jkowall added the changelog:bugfix-or-minor-feature 🐞 Bug fixes, Minor Improvements label Apr 10, 2026
@jkowall jkowall marked this pull request as ready for review April 10, 2026 06:56
@jkowall jkowall requested a review from a team as a code owner April 10, 2026 06:56
Copilot AI review requested due to automatic review settings April 10, 2026 06:56
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 scripts/prepare-release.py against command injection by removing shell-based command execution and tightening how commands are constructed/executed.

Changes:

  • Replaced subprocess.run(..., shell=True) string commands with shell=False argument lists throughout.
  • Added run_command() validation to require a sequence-of-args input to prevent regressions.
  • Narrowed exception handling around subprocess calls and introduced a sensitive flag to suppress stdout/stderr echoing on failures.

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

Comment on lines +46 to 48
return run_command(["gh", "auth", "token"], sensitive=True)
except (subprocess.CalledProcessError, FileNotFoundError):
print("Error: Could not retrieve GitHub token using 'gh auth token'. Please login via 'gh auth login'.")
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

get_gh_token() still executes gh auth token and captures the token into Python memory (and returns it) even though the script no longer uses the value. This increases the blast radius for accidental secret exposure (e.g., future logging/tracebacks) and is unnecessary if the goal is only to validate auth. Consider replacing this with a non-secret-bearing check like gh auth status (or a minimal gh api user call), or adjust run_command()/get_gh_token() so sensitive commands don’t return/capture the secret unless explicitly needed.

Suggested change
return run_command(["gh", "auth", "token"], sensitive=True)
except (subprocess.CalledProcessError, FileNotFoundError):
print("Error: Could not retrieve GitHub token using 'gh auth token'. Please login via 'gh auth login'.")
run_command(
["gh", "auth", "status"],
capture_stdout=False,
capture_stderr=False,
sensitive=True
)
return ""
except (subprocess.CalledProcessError, FileNotFoundError):
print("Error: GitHub CLI is not authenticated. Please login via 'gh auth login'.")

Copilot uses AI. Check for mistakes.
# check_git_status() # Optional: strict check, but might be annoying in dev. Uncomment if needed.
validate_version(version)
token = get_gh_token()
get_gh_token()
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

The return value of get_gh_token() is ignored here, but the call still retrieves (and internally captures) a GitHub token. If this is intended only as an auth preflight, prefer a tokenless command (e.g., gh auth status) to avoid handling secrets unnecessarily; otherwise, use the returned token for something concrete so it’s clear why it’s being fetched.

Suggested change
get_gh_token()
run_command(["gh", "auth", "status"], capture_stdout=False)

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog:bugfix-or-minor-feature 🐞 Bug fixes, Minor Improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants