ruby/ruby · error · ArgumentError

NUL character

Error message

NUL character

What it means

Shellwords.shellescape raises ArgumentError 'NUL character' when the string contains "\0". Shells pass arguments through execve-style argv arrays that are NUL-terminated, so a NUL can never travel inside a single argument; escaping it would silently truncate the value, so the method refuses instead.

Source

Thrown at lib/shellwords.rb:165

  #       file, lineno, matched_line = line.split(':', 3)
  #       # ...
  #     }
  #   }
  #
  # It is the caller's responsibility to encode the string in the right
  # encoding for the shell environment where this string is used.
  #
  # Multibyte characters are treated as multibyte characters, not as bytes.
  #
  # Returns an empty quoted String if +str+ has a length of zero.
  def shellescape(str)
    str = str.to_s

    # An empty argument will be skipped, so return empty quotes.
    return "''".dup if str.empty?

    # Shellwords cannot contain NUL characters.
    raise ArgumentError, "NUL character" if str.index("\0")

    str = str.dup

    # Treat multibyte characters as is.  It is the caller's responsibility
    # to encode the string in the right encoding for the shell
    # environment.
    str.gsub!(/[^A-Za-z0-9_\-.,:+\/@\n]/, "\\\\\\&")

    # A LF cannot be escaped with a backslash because a backslash + LF
    # combo is regarded as a line continuation and simply ignored.
    str.gsub!(/\n/, "'\n'")

    return str
  end

  module_function :shellescape

  class << self

View on GitHub (pinned to 0e5b888e1c)

Solutions

  1. Reject such input early with your own clear error: raise if str.include?("\0")
  2. If NULs are noise (e.g. UTF-16 remnants), scrub first: str.delete("\0") or str.scrub
  3. Treat NUL-bearing filenames as invalid paths — no such file can exist on POSIX
  4. Prefer argv-array invocation (system, Open3) over building shell strings at all

Example fix

# before
system("grep #{pattern.shellescape} log")   # pattern has a NUL -> raises

# after
raise ArgumentError, "invalid pattern" if pattern.include?("\0")
system("grep", pattern, "log")               # argv form, no shell
Defensive patterns

Strategy: validation

Validate before calling

raise ArgumentError, "NUL not allowed in #{name}" if value.include?("\0")
shellescape(value)

Type guard

value.is_a?(String) && !value.include?("\0")

Try / catch

begin
  shellescape(str)
rescue ArgumentError
  raise ArgumentError, "rejected NUL-bearing input" 
end

Prevention

When it happens

Trigger: shellescape("a\0b"); shellescape(File.binread(some_file)); escaping a filename or pattern that came from untrusted input and contains an embedded NUL.

Common situations: Binary file contents or corrupted network data flowing into shell-command construction; malicious path strings using NUL to confuse earlier path checks; upstream encoding bugs producing NUL-laden strings.

Related errors


AI-assisted analysis of ruby/ruby@0e5b888e1c (2026-08-21). Data as JSON: /api/errors/60ef49ce6714c36b. Report an issue: GitHub.