CodeQL documentation

Use of Kernel.open, IO.read or similar sinks with user-controlled input

ID: rb/kernel-open
Kind: path-problem
Security severity: 9.8
Severity: error
Precision: high
Tags:
   - correctness
   - security
   - external/cwe/cwe-078
   - external/cwe/cwe-088
   - external/cwe/cwe-073
Query suites:
   - ruby-code-scanning.qls
   - ruby-security-extended.qls
   - ruby-security-and-quality.qls

Click to see the query in the CodeQL repository

If Kernel.open is given a file name that starts with a | character, it will execute the remaining string as a shell command. If a malicious user can control the file name, they can execute arbitrary code. The same vulnerability applies to IO.read, IO.write, IO.binread, IO.binwrite, IO.foreach, IO.readlines and URI.open.

Recommendation

Use File.open instead of Kernel.open, as the former does not have this vulnerability. Similarly, use the methods from the File class instead of the IO class e.g. File.read instead of IO.read.

Instead of URI.open use URI(..).open or an HTTP Client.

Example

The following example shows code that calls Kernel.open on a user-supplied file path.

require "open-uri"

class UsersController < ActionController::Base
  def create
    filename = params[:filename]
    open(filename) # BAD

    web_page = params[:web_page]
    URI.open(web_page) # BAD - calls `Kernel.open` internally
  end
end

Instead, File.open should be used, as in the following example.

class UsersController < ActionController::Base
  def create
    filename = params[:filename]
    File.open(filename)

    web_page = params[:web_page]
    Net::HTTP.get(URI.parse(web_page))
  end
end

References

  • © GitHub, Inc.
  • Terms
  • Privacy