Use of externally-controlled format string¶
ID: rb/tainted-format-string
Kind: path-problem
Security severity: 7.3
Severity: warning
Precision: high
Tags:
- security
- external/cwe/cwe-134
Query suites:
- ruby-code-scanning.qls
- ruby-security-extended.qls
- ruby-security-and-quality.qls
Click to see the query in the CodeQL repository
Methods like Kernel.printf
accept a format string that is used to format the remaining arguments by providing inline format specifiers. If the format string contains unsanitized input from an untrusted source, then that string may contain unexpected format specifiers that cause garbled output or throw an exception.
Recommendation¶
Either sanitize the input before including it in the format string, or use a %s
specifier in the format string, and pass the untrusted data as corresponding argument.
Example¶
The following program snippet logs information about an unauthorized access attempt. The log message includes the user name, and the user’s IP address is passed as an additional argument to Kernel.printf
to be appended to the message:
class UsersController < ActionController::Base
def index
printf("Unauthorised access attempt by #{params[:user]}: %s", request.ip)
end
end
However, if a malicious user provides a format specified such as %s
as their user name, Kernel.printf
will throw an exception as there are too few arguments to satisfy the format. This can result in denial of service or leaking of internal information to the attacker via a stack trace.
Instead, the user name should be included using the %s
specifier:
class UsersController < ActionController::Base
def index
printf("Unauthorised access attempt by %s: %s", params[:user], request.ip)
end
end
Alternatively, string interpolation should be used exclusively:
class UsersController < ActionController::Base
def index
puts "Unauthorised access attempt by #{params[:user]}: #{request.ip}"
end
end
References¶
Ruby documentation for format strings.
Common Weakness Enumeration: CWE-134.