VYPR
Critical severityNVD Advisory· Published Jun 30, 2022· Updated Aug 6, 2024

CVE-2014-0156

CVE-2014-0156

Description

AwesomeSpawn Ruby gem had an OS command injection vulnerability allowing arbitrary command execution via unsanitized parameters.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

AwesomeSpawn Ruby gem had an OS command injection vulnerability allowing arbitrary command execution via unsanitized parameters.

Vulnerability

Overview

The awesome_spawn Ruby gem, which provides a wrapper around Kernel.spawn, contained an OS command injection vulnerability in its build_command_line method. The method failed to properly sanitize user-supplied parameters, allowing an attacker to inject arbitrary shell commands. The fix involved separating command line building and sanitizing into its own class, as seen in commit e524f85 [1].

Exploitation

An attacker could exploit this flaw by passing specially crafted parameters to commands executed via AwesomeSpawn.run. For example, passing {'-l' => ";touch haxored"} as parameters would result in the execution of the injected command after the intended ls -l command [4]. No authentication is required if the attacker controls the input passed to the gem.

Impact

Successful exploitation allows an attacker to execute arbitrary OS commands with the privileges of the Ruby process. This could lead to full system compromise, data exfiltration, or further lateral movement within the affected environment [2][4].

Mitigation

The vulnerability is patched in awesome_spawn versions >= 1.3.0 and ~> 1.2.0. Users are advised to upgrade to a patched version immediately. No workarounds are available [1][4].

AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
awesome_spawnRubyGems
< 1.2.01.2.0

Affected products

2

Patches

1
e524f85f1c6e

Separate command line building and sanitizing into its own class.

https://github.com/ManageIQ/awesome_spawnJason FreyJun 7, 2014via ghsa
4 files changed · +150 117
  • lib/awesome_spawn/command_line_builder.rb+59 0 added
    @@ -0,0 +1,59 @@
    +require "shellwords"
    +
    +module AwesomeSpawn
    +  class CommandLineBuilder
    +    # Build the full command line.
    +    #
    +    # @param [String] command The command to run
    +    # @param [Hash,Array] params Optional command line parameters. They can
    +    #   be passed as a Hash or associative Array. The values are sanitized to
    +    #   prevent command line injection.  Keys as symbols are prefixed with `--`,
    +    #   and `_` is replaced with `-`.
    +    #
    +    #   - `{:key => "value"}`            generates `--key value`
    +    #   - `{"--key" => "value"}`         generates `--key value`
    +    #   - `{:key= => "value"}`           generates `--key=value`
    +    #   - `{"--key=" => "value"}`        generates `--key=value`
    +    #   - `{:key_name => "value"}`       generates `--key-name value`
    +    #   - `{:key => nil}`                generates `--key`
    +    #   - `{"-f" => ["file1", "file2"]}` generates `-f file1 file2`
    +    #   - `{nil => ["file1", "file2"]}`  generates `file1 file2`
    +    #
    +    # @return [String] The full command line
    +    def build(command, params = nil)
    +      return command.to_s if params.nil? || params.empty?
    +      "#{command} #{assemble_params(sanitize(params))}"
    +    end
    +
    +    private
    +
    +    def sanitize(params)
    +      return [] if params.nil? || params.empty?
    +      params.collect do |k, v|
    +        [sanitize_key(k), sanitize_value(v)]
    +      end
    +    end
    +
    +    def sanitize_key(key)
    +      case key
    +      when Symbol then "--#{key.to_s.tr("_", "-")}"
    +      else             key
    +      end
    +    end
    +
    +    def sanitize_value(value)
    +      case value
    +      when Array    then value.collect { |i| i.to_s.shellescape }
    +      when NilClass then value
    +      else               value.to_s.shellescape
    +      end
    +    end
    +
    +    def assemble_params(sanitized_params)
    +      sanitized_params.collect do |pair|
    +        pair_joiner = pair.first.to_s.end_with?("=") ? "" : " "
    +        pair.flatten.compact.join(pair_joiner)
    +      end.join(" ")
    +    end
    +  end
    +end
    
  • lib/awesome_spawn.rb+3 50 modified
    @@ -1,9 +1,9 @@
     require "awesome_spawn/version"
    +require "awesome_spawn/command_line_builder"
     require "awesome_spawn/command_result"
     require "awesome_spawn/command_result_error"
     require "awesome_spawn/no_such_file_error"
     
    -require "shellwords"
     require "open3"
     
     module AwesomeSpawn
    @@ -100,60 +100,13 @@ def run!(command, options = {})
         command_result
       end
     
    -  # Build the full command line.
    -  #
    -  # @param [String] command The command to run
    -  # @param [Hash,Array] params Optional command line parameters. They can
    -  #   be passed as a Hash or associative Array. The values are sanitized to
    -  #   prevent command line injection.  Keys as symbols are prefixed with `--`,
    -  #   and `_` is replaced with `-`.
    -  #
    -  #   - `{:key => "value"}`            generates `--key value`
    -  #   - `{"--key" => "value"}`         generates `--key value`
    -  #   - `{:key= => "value"}`           generates `--key=value`
    -  #   - `{"--key=" => "value"}`        generates `--key=value`
    -  #   - `{:key_name => "value"}`       generates `--key-name value`
    -  #   - `{:key => nil}`                generates `--key`
    -  #   - `{"-f" => ["file1", "file2"]}` generates `-f file1 file2`
    -  #   - `{nil => ["file1", "file2"]}`  generates `file1 file2`
    -  #
    -  # @return [String] The full command line
    +  # (see CommandLineBuilder#build)
       def build_command_line(command, params = nil)
    -    return command.to_s if params.nil? || params.empty?
    -    "#{command} #{assemble_params(sanitize(params))}"
    +    CommandLineBuilder.new.build(command, params)
       end
     
       private
     
    -  def sanitize(params)
    -    return [] if params.nil? || params.empty?
    -    params.collect do |k, v|
    -      [sanitize_key(k), sanitize_value(v)]
    -    end
    -  end
    -
    -  def sanitize_key(key)
    -    case key
    -    when Symbol then "--#{key.to_s.tr("_", "-")}"
    -    else             key
    -    end
    -  end
    -
    -  def sanitize_value(value)
    -    case value
    -    when Array    then value.collect { |i| i.to_s.shellescape }
    -    when NilClass then value
    -    else               value.to_s.shellescape
    -    end
    -  end
    -
    -  def assemble_params(sanitized_params)
    -    sanitized_params.collect do |pair|
    -      pair_joiner = pair.first.to_s.end_with?("=") ? "" : " "
    -      pair.flatten.compact.join(pair_joiner)
    -    end.join(" ")
    -  end
    -
       def launch(command, in_data, spawn_options = {})
         spawn_options = spawn_options.merge(:stdin_data => in_data) if in_data
         output, error, status = Open3.capture3(command, spawn_options)
    
  • spec/awesome_spawn_spec.rb+0 67 modified
    @@ -128,71 +128,4 @@
           let(:run_method) {"run!"}
         end
       end
    -
    -  context ".build_command_line" do
    -    it "sanitizes crazy params" do
    -      cl = subject.build_command_line("true", modified_params)
    -      expect(cl).to eq "true --user bob --pass P@\\$sw0\\^\\&\\ \\|\\<\\>/-\\+\\*d\\% --db --desc=Some\\ Description --symkey --symkey-dash pkg1 some\\ pkg --pool 123 --pool 456"
    -    end
    -
    -    it "handles Symbol keys" do
    -      cl = subject.build_command_line("true", :abc => "def")
    -      expect(cl).to eq "true --abc def"
    -    end
    -
    -    it "handles Symbol keys with tailing '='" do
    -      cl = subject.build_command_line("true", :abc= => "def")
    -      expect(cl).to eq "true --abc=def"
    -    end
    -
    -    it "handles Symbol keys with underscore" do
    -      cl = subject.build_command_line("true", :abc_def => "ghi")
    -      expect(cl).to eq "true --abc-def ghi"
    -    end
    -
    -    it "handles Symbol keys with underscore and tailing '='" do
    -      cl = subject.build_command_line("true", :abc_def= => "ghi")
    -      expect(cl).to eq "true --abc-def=ghi"
    -    end
    -
    -    it "sanitizes Fixnum array param value" do
    -      cl = subject.build_command_line("true", nil => [1])
    -      expect(cl).to eq "true 1"
    -    end
    -
    -    it "sanitizes Pathname param value" do
    -      cl = subject.build_command_line("true", nil => [Pathname.new("/usr/bin/ruby")])
    -      expect(cl).to eq "true /usr/bin/ruby"
    -    end
    -
    -    it "sanitizes Pathname param key" do
    -      cl = subject.build_command_line("true", Pathname.new("/usr/bin/ruby") => nil)
    -      expect(cl).to eq "true /usr/bin/ruby"
    -    end
    -
    -    it "with params as empty Hash" do
    -      cl = subject.build_command_line("true", {})
    -      expect(cl).to eq "true"
    -    end
    -
    -    it "with params as nil" do
    -      cl = subject.build_command_line("true", nil)
    -      expect(cl).to eq "true"
    -    end
    -
    -    it "without params" do
    -      cl = subject.build_command_line("true")
    -      expect(cl).to eq "true"
    -    end
    -
    -    it "with Pathname command" do
    -      cl = subject.build_command_line(Pathname.new("/usr/bin/ruby"))
    -      expect(cl).to eq "/usr/bin/ruby"
    -    end
    -
    -    it "with Pathname command and params" do
    -      cl = subject.build_command_line(Pathname.new("/usr/bin/ruby"), "-v" => nil)
    -      expect(cl).to eq "/usr/bin/ruby -v"
    -    end
    -  end
     end
    
  • spec/command_line_builder_spec.rb+88 0 added
    @@ -0,0 +1,88 @@
    +require 'spec_helper'
    +
    +describe AwesomeSpawn::CommandLineBuilder do
    +  subject { described_class.new }
    +
    +  let(:params) do
    +    {
    +      "--user"     => "bob",
    +      "--pass"     => "P@$sw0^& |<>/-+*d%",
    +      "--db"       => nil,
    +      "--desc="    => "Some Description",
    +      :symkey      => nil,
    +      :symkey_dash => nil,
    +      nil          => ["pkg1", "some pkg"]
    +    }
    +  end
    +
    +  let (:modified_params) do
    +    params.to_a + [123, 456].collect {|pool| ["--pool", pool]}
    +  end
    +
    +  context "#build" do
    +    it "sanitizes crazy params" do
    +      cl = subject.build("true", modified_params)
    +      expect(cl).to eq "true --user bob --pass P@\\$sw0\\^\\&\\ \\|\\<\\>/-\\+\\*d\\% --db --desc=Some\\ Description --symkey --symkey-dash pkg1 some\\ pkg --pool 123 --pool 456"
    +    end
    +
    +    it "handles Symbol keys" do
    +      cl = subject.build("true", :abc => "def")
    +      expect(cl).to eq "true --abc def"
    +    end
    +
    +    it "handles Symbol keys with tailing '='" do
    +      cl = subject.build("true", :abc= => "def")
    +      expect(cl).to eq "true --abc=def"
    +    end
    +
    +    it "handles Symbol keys with underscore" do
    +      cl = subject.build("true", :abc_def => "ghi")
    +      expect(cl).to eq "true --abc-def ghi"
    +    end
    +
    +    it "handles Symbol keys with underscore and tailing '='" do
    +      cl = subject.build("true", :abc_def= => "ghi")
    +      expect(cl).to eq "true --abc-def=ghi"
    +    end
    +
    +    it "sanitizes Fixnum array param value" do
    +      cl = subject.build("true", nil => [1])
    +      expect(cl).to eq "true 1"
    +    end
    +
    +    it "sanitizes Pathname param value" do
    +      cl = subject.build("true", nil => [Pathname.new("/usr/bin/ruby")])
    +      expect(cl).to eq "true /usr/bin/ruby"
    +    end
    +
    +    it "sanitizes Pathname param key" do
    +      cl = subject.build("true", Pathname.new("/usr/bin/ruby") => nil)
    +      expect(cl).to eq "true /usr/bin/ruby"
    +    end
    +
    +    it "with params as empty Hash" do
    +      cl = subject.build("true", {})
    +      expect(cl).to eq "true"
    +    end
    +
    +    it "with params as nil" do
    +      cl = subject.build("true", nil)
    +      expect(cl).to eq "true"
    +    end
    +
    +    it "without params" do
    +      cl = subject.build("true")
    +      expect(cl).to eq "true"
    +    end
    +
    +    it "with Pathname command" do
    +      cl = subject.build(Pathname.new("/usr/bin/ruby"))
    +      expect(cl).to eq "/usr/bin/ruby"
    +    end
    +
    +    it "with Pathname command and params" do
    +      cl = subject.build(Pathname.new("/usr/bin/ruby"), "-v" => nil)
    +      expect(cl).to eq "/usr/bin/ruby -v"
    +    end
    +  end
    +end
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.