1

Does Ruby ship with a function/method to run a command and capture it's output without risking command injection.

For example:

out = `ls #{directory}`

would capture the output I want, but is insecure.

system("ls", directory)

is safer (as far as I know), but I can't capture it's output.

Is there some equivalent to Python's out = call(['ls', directory])?

Edit for @Eric Duminil

irb(main):001:0> RUBY_DESCRIPTION
=> "ruby 2.1.8p440 (2015-12-16 revision 53160) [x86_64-linux]"
irb(main):002:0> Shellwords
NameError: uninitialized constant Shellwords
        from (irb):2
        from /apollo/env/SDETools/ruby2.1.x/bin/irb:15:in `<main>'
irb(main):003:0> require "shellwords"
=> true
irb(main):004:0> Shellwords
=> Shellword
1
  • Kernel#system accepts the same options as Kernel#spawn you can specify an IO object for the output See Docs Commented Jul 17, 2017 at 20:39

1 Answer 1

1

You can escape the argument with Shellwords#shellescape:

Escapes a string so that it can be safely used in a Bourne shell command line. str can be a non-string object that responds to to_s.

Note that a resulted string should be used unquoted and is not intended for use in double quotes nor in single quotes.

require 'shellwords' # <- Only needed for Ruby 1.9
"ls %s" % Shellwords.escape("test.txt && whoami")
# => "ls test.txt\\ \\&\\&\\ whoami"
system("ls %s" % Shellwords.escape("test.txt && whoami"))
# ls: cannot access test.txt && whoami: No such file or directory

As mentioned by @engineersmnky in the comments, you could simply use system with multiple arguments:

system("ls", "test.txt && whoami")
# ls: cannot access test.txt && whoami: No such file or directory
Sign up to request clarification or add additional context in comments.

6 Comments

I'd like to mark your answer as correct, but (in the version of Ruby I'm using) system doesn't return a command's output, just its return code. EDIT: or for that matter, Shellwords (unless I need a `require statement).
Oh, I was missing a require "Shellwords"
@jones sorry, it's only needed for ruby 1.9. I didnt think about that.
Are you sure about that? I'm using Ruby 2.1
@Jones I just tried it on 2.1.5, it worked fine without require.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.