{"record":{"id":"60ef49ce6714c36b","repo":"ruby/ruby","slug":"nul-character","errorCode":null,"errorMessage":"NUL character","messagePattern":"NUL character","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/shellwords.rb","lineNumber":165,"sourceCode":"  #       file, lineno, matched_line = line.split(':', 3)\n  #       # ...\n  #     }\n  #   }\n  #\n  # It is the caller's responsibility to encode the string in the right\n  # encoding for the shell environment where this string is used.\n  #\n  # Multibyte characters are treated as multibyte characters, not as bytes.\n  #\n  # Returns an empty quoted String if +str+ has a length of zero.\n  def shellescape(str)\n    str = str.to_s\n\n    # An empty argument will be skipped, so return empty quotes.\n    return \"''\".dup if str.empty?\n\n    # Shellwords cannot contain NUL characters.\n    raise ArgumentError, \"NUL character\" if str.index(\"\\0\")\n\n    str = str.dup\n\n    # Treat multibyte characters as is.  It is the caller's responsibility\n    # to encode the string in the right encoding for the shell\n    # environment.\n    str.gsub!(/[^A-Za-z0-9_\\-.,:+\\/@\\n]/, \"\\\\\\\\\\\\&\")\n\n    # A LF cannot be escaped with a backslash because a backslash + LF\n    # combo is regarded as a line continuation and simply ignored.\n    str.gsub!(/\\n/, \"'\\n'\")\n\n    return str\n  end\n\n  module_function :shellescape\n\n  class << self","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/ruby/ruby/blob/0e5b888e1c355f3f728f2659f085820937dada48/lib/shellwords.rb#L147-L183","documentation":"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.","triggerScenarios":"shellescape(\"a\\0b\"); shellescape(File.binread(some_file)); escaping a filename or pattern that came from untrusted input and contains an embedded NUL.","commonSituations":"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.","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"],"exampleFix":"# before\nsystem(\"grep #{pattern.shellescape} log\")   # pattern has a NUL -> raises\n\n# after\nraise ArgumentError, \"invalid pattern\" if pattern.include?(\"\\0\")\nsystem(\"grep\", pattern, \"log\")               # argv form, no shell","handlingStrategy":"validation","validationCode":"raise ArgumentError, \"NUL not allowed in #{name}\" if value.include?(\"\\0\")\nshellescape(value)","typeGuard":"value.is_a?(String) && !value.include?(\"\\0\")","tryCatchPattern":"begin\n  shellescape(str)\nrescue ArgumentError\n  raise ArgumentError, \"rejected NUL-bearing input\" \nend","preventionTips":["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"],"tags":["ruby","shellwords","escaping","nul-byte","security"],"backgroundTag":"nul-character-in-string","analyzedSha":"0e5b888e1c355f3f728f2659f085820937dada48","analyzedAt":"2026-08-21T14:25:43.473Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}