Prevent shell command injection in psql --options#4204
Open
tas50 wants to merge 1 commit into
Open
Conversation
The psql command built a single command string and ran it with
`exec cmd`. Because the string contained the user-supplied --options
value and was passed to exec as one string, Ruby executed it through a
shell, so shell metacharacters in --options were interpreted. For
example:
chef-server-ctl psql opscode_chef --options '; <command>'
would run the injected command instead of treating it as a psql option.
Build an explicit argument vector and call exec(*cmd) so no shell is
involved. The --options value is tokenized with Shellwords.split and
each token is passed to psql as a literal argument, preserving the
ability to pass real psql options without allowing shell interpretation.
Signed-off-by: Tim Smith <tsmith84@proton.me>
👷 Deploy Preview for chef-server processing.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The
psqlcommand insrc/chef-server-ctl/plugins/psql.rbbuilds a single command string and executes it withexec cmd:When
execis given a single string that contains shell metacharacters, Ruby runs it through/bin/sh. The user-supplied--optionsvalue is interpolated into that string unescaped, so it is interpreted by the shell. For example:executes the injected command rather than passing it to psql as an option.
Fix
Build an explicit argument vector and call
exec(*cmd). With multiple arguments Ruby does not invoke a shell, so arguments are passed to psql verbatim. The--optionsvalue is tokenized withShellwords.split(honoring shell-style quoting) and each token becomes a literal argv element, preserving the ability to pass real psql options without allowing shell interpretation:Note: the chef-server-ctl gem bundle targets Ruby 3.1 and could not be installed in my local environment (Ruby 4.x), so I verified the change with
ruby -cand am relying on CI for the rspec suite.