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 << selfView on GitHub (pinned to 0e5b888e1c)
Solutions
- Reject such input early with your own clear error: raise if str.include?("\0")
- If NULs are noise (e.g. UTF-16 remnants), scrub first: str.delete("\0") or str.scrub
- Treat NUL-bearing filenames as invalid paths — no such file can exist on POSIX
- 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
- Reject NUL bytes at input validation, before command construction
- Scrub binary-sourced strings (delete("\0") or .scrub) when NULs are noise
- Prefer argv-array process invocation over shell strings
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
- multipart boundary cannot include CR/LF
- field content type cannot include CR/LF
- multipart field name or filename cannot include CR/LF
- A Request-Line must not contain CR or LF
- header #{key} has field value #{value.inspect}, this cannot
AI-assisted analysis of ruby/ruby@0e5b888e1c (2026-08-21).
Data as JSON: /api/errors/60ef49ce6714c36b.
Report an issue: GitHub.