Skip to content

Fix encoding bug, command injection, and $-expansion in profile path#3

Closed
Copilot wants to merge 4 commits intomainfrom
copilot/click-pwsh-2-fix-sub-command-issue
Closed

Fix encoding bug, command injection, and $-expansion in profile path#3
Copilot wants to merge 4 commits intomainfrom
copilot/click-pwsh-2-fix-sub-command-issue

Conversation

Copy link
Copy Markdown

Copilot AI commented Mar 15, 2026

Three correctness and security issues in click_pwsh/__main__.py identified during review of the space-in-path fix.

Changes

  • get_current_encoding() fix — iterating bytes yields ints, so byte not in (b'\r', b'\n') was always True and CR/LF could leak into the returned encoding string. Replaced with stdout.decode("utf-8").strip().

  • Command injection guardcommand was interpolated directly into the PowerShell -c string with no validation, allowing arbitrary PS execution (e.g. foo; Remove-Item ...). Added _validate_command() enforcing ^[A-Za-z0-9][A-Za-z0-9_-]*$ before any sp.run() call.

  • $-safe profile invocation — the line appended to the user's profile was & "path" (double-quoted), so any $ in the filename would be expanded at profile load time. Changed to single-quoted & 'path' via _pwsh_escape():

# Before — $-unsafe, completion_profile unescaped
"echo '& \"{}\"' >> '{}'".format(str(completion_profile), _pwsh_escape(str(profile)))

# After — $-safe, both paths escaped
"echo '& ''{0}''' >> '{1}'".format(
    _pwsh_escape(str(completion_profile)),
    _pwsh_escape(str(profile)),
)
# PowerShell evaluates '& ''path''' as the literal string: & 'path'
Original prompt

修正 click-pwsh#2 所提到的問題,你要注意的是,他所謂空格導致錯誤的解法,主要是受到 sub command 使用上的問題,我希望你的 command line 使用 list of string 儲存 使得 shell=False. 不過你要注意一下這樣的修改方法是否需要額外指定 shell 必須是誰 (至少要是 PowerShell).


🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

…alls

- Convert all sp.run(string, shell=True) to sp.run([list], shell=False)
  using ["pwsh", "-c", "..."] so PowerShell is explicitly targeted and
  no OS-level shell expansion occurs (fixes paths with spaces)
- Fix get_current_encoding() which already had shell=False but still
  passed a string (incorrect); now passes a proper list
- Add _pwsh_escape() helper to escape single quotes in paths when
  embedding them in PowerShell single-quoted strings
- Change profile-append command from '\"path\" | Invoke-Expression'
  to '& \"path\"' syntax, which correctly handles paths with spaces
- Quote all paths in PowerShell commands with single quotes

Fixes #2

Co-authored-by: StephLin <20769958+StephLin@users.noreply.github.com>
Copilot AI changed the title [WIP] [click-pwsh#2] Fix issues with space causing command errors Fix space-in-path breakage in install/update by using shell=False with list-based subprocess calls Mar 15, 2026
Copilot AI requested a review from StephLin March 15, 2026 07:37
@StephLin StephLin requested review from Copilot and removed request for StephLin March 15, 2026 07:51
@StephLin StephLin self-requested a review March 15, 2026 07:53
@StephLin StephLin changed the title Fix space-in-path breakage in install/update by using shell=False with list-based subprocess calls Fix space-in-path breakage in install/update scripts Mar 15, 2026
@StephLin StephLin marked this pull request as ready for review March 15, 2026 07:54
Copy link
Copy Markdown

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 updates click_pwsh’s install/update flows to be robust to PowerShell profile paths containing spaces by avoiding shell=True string commands and improving PowerShell-side path quoting.

Changes:

  • Switch all subprocess.run() invocations to list-based args with shell=False (directly executing pwsh).
  • Add _pwsh_escape() and wrap redirected file paths in single quotes inside PowerShell commands.
  • Replace Invoke-Expression-based script invocation with the PowerShell call operator (&).

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

You can also share your feedback on Copilot code review. Take the survey.

Comment thread click_pwsh/__main__.py
Comment thread click_pwsh/__main__.py Outdated
Comment on lines 28 to 33
encoding = sp.run(
["pwsh", "-c", "(chcp | Out-String).Split(' ')[-1].Trim()"],
shell=False,
capture_output=True,
)
encoding = ''.join(chr(byte) for byte in encoding.stdout if byte not in (b'\r', b'\n'))
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

@copilot This should be an irrelevant issue though it’s important. Please open another PR to target this issue.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I'm unable to open new PRs. Please open a new issue or PR to track this — the fix would be to replace the byte-by-byte iteration with encoding.stdout.decode("ascii").strip() (or "utf-8") in get_current_encoding(), since chcp output is always ASCII.

Comment thread click_pwsh/__main__.py
Comment on lines +57 to +62
"$env:{0} = 'pwsh_source'; {1} > '{2}'; $env:{0} = $null".format(
completion_varname,
command,
_pwsh_escape(str(completion_profile)),
),
],
Comment thread click_pwsh/__main__.py Outdated
Comment on lines +69 to +70
"echo '& \"{}\"' >> '{}'".format(
str(completion_profile),
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: StephLin <20769958+StephLin@users.noreply.github.com>
Copilot AI changed the title Fix space-in-path breakage in install/update scripts Fix encoding bug, command injection, and $-expansion in profile path Mar 15, 2026
@StephLin StephLin closed this Apr 4, 2026
@StephLin StephLin deleted the copilot/click-pwsh-2-fix-sub-command-issue branch April 4, 2026 06:22
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.

3 participants