mirror of
https://github.com/github/codeql.git
synced 2026-04-27 01:35:13 +02:00
Merge pull request #9574 from hmac/hmac/action-cable-logger
Ruby: More Rails modeling
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
private import codeql.ruby.frameworks.Core
|
||||
private import codeql.ruby.frameworks.ActionCable
|
||||
private import codeql.ruby.frameworks.ActionController
|
||||
private import codeql.ruby.frameworks.ActiveRecord
|
||||
private import codeql.ruby.frameworks.ActiveStorage
|
||||
@@ -11,6 +12,7 @@ private import codeql.ruby.frameworks.ActiveSupport
|
||||
private import codeql.ruby.frameworks.Archive
|
||||
private import codeql.ruby.frameworks.GraphQL
|
||||
private import codeql.ruby.frameworks.Rails
|
||||
private import codeql.ruby.frameworks.Railties
|
||||
private import codeql.ruby.frameworks.Stdlib
|
||||
private import codeql.ruby.frameworks.Files
|
||||
private import codeql.ruby.frameworks.HttpClients
|
||||
|
||||
29
ruby/ql/lib/codeql/ruby/frameworks/ActionCable.qll
Normal file
29
ruby/ql/lib/codeql/ruby/frameworks/ActionCable.qll
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Modeling for `ActionCable`, which is a websocket gem that ships with Rails.
|
||||
* https://rubygems.org/gems/actioncable
|
||||
*/
|
||||
|
||||
private import ruby
|
||||
private import codeql.ruby.Concepts
|
||||
private import codeql.ruby.ApiGraphs
|
||||
private import codeql.ruby.frameworks.stdlib.Logger::Logger as StdlibLogger
|
||||
|
||||
/**
|
||||
* Modeling for `ActionCable`.
|
||||
*/
|
||||
module ActionCable {
|
||||
/**
|
||||
* `ActionCable::Connection::TaggedLoggerProxy`
|
||||
*/
|
||||
module Logger {
|
||||
private class ActionCableLoggerInstantiation extends StdlibLogger::LoggerInstantiation {
|
||||
ActionCableLoggerInstantiation() {
|
||||
this =
|
||||
API::getTopLevelMember("ActionCable")
|
||||
.getMember("Connection")
|
||||
.getMember("TaggedLoggerProxy")
|
||||
.getAnInstantiation()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -180,18 +180,31 @@ private class ActionControllerHtmlEscapeCall extends HtmlEscapeCall {
|
||||
* specific URL/path or to a different action in this controller.
|
||||
*/
|
||||
class RedirectToCall extends ActionControllerContextCall {
|
||||
RedirectToCall() { this.getMethodName() = "redirect_to" }
|
||||
RedirectToCall() {
|
||||
this.getMethodName() = ["redirect_to", "redirect_back", "redirect_back_or_to"]
|
||||
}
|
||||
|
||||
/** Gets the `Expr` representing the URL to redirect to, if any */
|
||||
Expr getRedirectUrl() { result = this.getArgument(0) }
|
||||
Expr getRedirectUrl() {
|
||||
this.getMethodName() = "redirect_back" and result = this.getKeywordArgument("fallback_location")
|
||||
or
|
||||
this.getMethodName() = ["redirect_to", "redirect_back_or_to"] and result = this.getArgument(0)
|
||||
}
|
||||
|
||||
/** Gets the `ActionControllerActionMethod` to redirect to, if any */
|
||||
ActionControllerActionMethod getRedirectActionMethod() {
|
||||
exists(string methodName |
|
||||
this.getKeywordArgument("action").getConstantValue().isStringlikeValue(methodName) and
|
||||
methodName = result.getName() and
|
||||
result.getEnclosingModule() = this.getControllerClass()
|
||||
)
|
||||
this.getKeywordArgument("action").getConstantValue().isStringlikeValue(result.getName()) and
|
||||
result.getEnclosingModule() = this.getControllerClass()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this method call allows a redirect to an external host.
|
||||
*/
|
||||
predicate allowsExternalRedirect() {
|
||||
// Unless the option allow_other_host is explicitly set to false, assume that external redirects are allowed.
|
||||
// TODO: Take into account `config.action_controller.raise_on_open_redirects`.
|
||||
// TODO: Take into account that this option defaults to false in Rails 7.
|
||||
not this.getKeywordArgument("allow_other_host").getConstantValue().isBoolean(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -359,7 +359,7 @@ private module Persistence {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `call` has a keyword argument of with value `value`.
|
||||
* Holds if `call` has a keyword argument with value `value`.
|
||||
*/
|
||||
private predicate keywordArgumentWithValue(DataFlow::CallNode call, DataFlow::ExprNode value) {
|
||||
exists(ExprNodes::PairCfgNode pair | pair = call.getArgument(_).asExpr() |
|
||||
@@ -412,6 +412,28 @@ private module Persistence {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `ActiveRecord::Relation#touch_all`, which updates the `updated_at`
|
||||
* attribute on all records in the relation, setting it to the current time or
|
||||
* the time specified. If passed additional attribute names, they will also be
|
||||
* updated with the time.
|
||||
* Examples:
|
||||
* ```rb
|
||||
* Person.all.touch_all
|
||||
* Person.where(name: "David").touch_all
|
||||
* Person.all.touch_all(:created_at)
|
||||
* Person.all.touch_all(time: Time.new(2020, 5, 16, 0, 0, 0))
|
||||
* ```
|
||||
*/
|
||||
private class TouchAllCall extends DataFlow::CallNode, PersistentWriteAccess::Range {
|
||||
TouchAllCall() {
|
||||
exists(this.asExpr().getExpr().(ActiveRecordModelClassMethodCall).getReceiverClass()) and
|
||||
this.getMethodName() = "touch_all"
|
||||
}
|
||||
|
||||
override DataFlow::Node getValue() { result = this.getKeywordArgument("time") }
|
||||
}
|
||||
|
||||
/** A call to e.g. `User.insert_all([{name: "foo"}, {name: "bar"}])` */
|
||||
private class InsertAllLikeCall extends DataFlow::CallNode, PersistentWriteAccess::Range {
|
||||
private ExprNodes::ArrayLiteralCfgNode arr;
|
||||
|
||||
@@ -7,7 +7,6 @@ private import ruby
|
||||
private import codeql.ruby.Concepts
|
||||
private import codeql.ruby.DataFlow
|
||||
private import codeql.ruby.dataflow.FlowSummary
|
||||
private import codeql.ruby.Concepts
|
||||
private import codeql.ruby.ApiGraphs
|
||||
private import codeql.ruby.frameworks.stdlib.Logger::Logger as StdlibLogger
|
||||
|
||||
|
||||
62
ruby/ql/lib/codeql/ruby/frameworks/Railties.qll
Normal file
62
ruby/ql/lib/codeql/ruby/frameworks/Railties.qll
Normal file
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Modeling for `railties`, which is a gem containing various internals and utilities for the Rails framework.
|
||||
* https://rubygems.org/gems/railties
|
||||
*/
|
||||
|
||||
private import ruby
|
||||
private import codeql.ruby.Concepts
|
||||
private import codeql.ruby.ApiGraphs
|
||||
private import codeql.ruby.DataFlow
|
||||
private import codeql.ruby.ast.internal.Module
|
||||
|
||||
/**
|
||||
* Modeling for `railties`.
|
||||
*/
|
||||
module Railties {
|
||||
/**
|
||||
* A class which `include`s `Rails::Generators::Actions`.
|
||||
*/
|
||||
private class GeneratorsActionsContext extends ClassDeclaration {
|
||||
GeneratorsActionsContext() {
|
||||
exists(IncludeOrPrependCall i |
|
||||
i.getEnclosingModule() = this and
|
||||
i.getArgument(0) =
|
||||
API::getTopLevelMember("Rails")
|
||||
.getMember("Generators")
|
||||
.getMember("Actions")
|
||||
.getAUse()
|
||||
.asExpr()
|
||||
.getExpr()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `Rails::Generators::Actions#execute_command`.
|
||||
* This method concatenates its first and second arguments and executes the result as a shell command.
|
||||
*/
|
||||
private class ExecuteCommandCall extends SystemCommandExecution::Range, DataFlow::CallNode {
|
||||
ExecuteCommandCall() {
|
||||
this.asExpr().getExpr().getEnclosingModule() instanceof GeneratorsActionsContext and
|
||||
this.getMethodName() = "execute_command"
|
||||
}
|
||||
|
||||
override DataFlow::Node getAnArgument() { result = this.getArgument([0, 1]) }
|
||||
|
||||
override predicate isShellInterpreted(DataFlow::Node arg) { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to a method in `Rails::Generators::Actions` which delegates to `execute_command`.
|
||||
*/
|
||||
private class ExecuteCommandWrapperCall extends SystemCommandExecution::Range, DataFlow::CallNode {
|
||||
ExecuteCommandWrapperCall() {
|
||||
this.asExpr().getExpr().getEnclosingModule() instanceof GeneratorsActionsContext and
|
||||
this.getMethodName() = ["rake", "rails_command", "git"]
|
||||
}
|
||||
|
||||
override DataFlow::Node getAnArgument() { result = this.getArgument(0) }
|
||||
|
||||
override predicate isShellInterpreted(DataFlow::Node arg) { any() }
|
||||
}
|
||||
}
|
||||
@@ -137,7 +137,7 @@ class IOOrFileWriteMethodCall extends IOOrFileMethodCall {
|
||||
receiverKind = "class" and
|
||||
api = ["IO", "File"] and
|
||||
this = API::getTopLevelMember(api).getAMethodCall(methodName) and
|
||||
methodName = ["binwrite", "write"] and
|
||||
methodName = ["binwrite", "write", "atomic_write"] and
|
||||
dataNode = this.getArgument(1)
|
||||
or
|
||||
// e.g. `{IO,File}.new("foo.txt", "a+).puts("hello")`
|
||||
|
||||
@@ -71,7 +71,9 @@ module UrlRedirect {
|
||||
// We exclude any handlers with names containing create/update/destroy, as these are not likely to handle GET requests.
|
||||
not exists(method.(ActionControllerActionMethod).getARoute()) and
|
||||
not method.getName().regexpMatch(".*(create|update|destroy).*")
|
||||
)
|
||||
) and
|
||||
// If this redirect is an ActionController method call, it is only vulnerable if it allows external redirects.
|
||||
forall(RedirectToCall c | c = e.asExpr().getExpr() | c.allowsExternalRedirect())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
| app/controllers/users_controller.rb:20:7:20:57 | call to update_attributes | app/controllers/users_controller.rb:20:49:20:55 | call to get_uid |
|
||||
| app/controllers/users_controller.rb:23:7:23:42 | call to update_attribute | app/controllers/users_controller.rb:23:37:23:41 | "U13" |
|
||||
| app/controllers/users_controller.rb:26:19:26:23 | ... = ... | app/controllers/users_controller.rb:26:19:26:23 | "U14" |
|
||||
| app/controllers/users_controller.rb:31:7:31:32 | call to touch_all | app/controllers/users_controller.rb:31:28:31:31 | call to time |
|
||||
| app/models/user.rb:4:5:4:28 | call to update | app/models/user.rb:4:23:4:27 | "U15" |
|
||||
| app/models/user.rb:5:5:5:23 | call to update | app/models/user.rb:5:18:5:22 | "U16" |
|
||||
| app/models/user.rb:6:5:6:56 | call to update_attributes | app/models/user.rb:6:35:6:39 | "U17" |
|
||||
|
||||
@@ -25,6 +25,10 @@ module Users
|
||||
# AssignAttributeCall
|
||||
user.name = "U14"
|
||||
user.save
|
||||
|
||||
# TouchAllCall
|
||||
User.touch_all
|
||||
User.touch_all(time: time)
|
||||
end
|
||||
|
||||
def get_uid
|
||||
|
||||
@@ -3,7 +3,7 @@ actionControllerControllerClasses
|
||||
| ActiveRecord.rb:41:1:64:3 | BarController |
|
||||
| ActiveRecord.rb:66:1:70:3 | BazController |
|
||||
| app/controllers/comments_controller.rb:1:1:7:3 | CommentsController |
|
||||
| app/controllers/foo/bars_controller.rb:3:1:31:3 | BarsController |
|
||||
| app/controllers/foo/bars_controller.rb:3:1:39:3 | BarsController |
|
||||
| app/controllers/photos_controller.rb:1:1:4:3 | PhotosController |
|
||||
| app/controllers/posts_controller.rb:1:1:10:3 | PostsController |
|
||||
| app/controllers/users/notifications_controller.rb:2:3:5:5 | NotificationsController |
|
||||
@@ -17,6 +17,8 @@ actionControllerActionMethods
|
||||
| app/controllers/foo/bars_controller.rb:5:3:7:5 | index |
|
||||
| app/controllers/foo/bars_controller.rb:9:3:18:5 | show_debug |
|
||||
| app/controllers/foo/bars_controller.rb:20:3:24:5 | show |
|
||||
| app/controllers/foo/bars_controller.rb:26:3:28:5 | go_back |
|
||||
| app/controllers/foo/bars_controller.rb:30:3:32:5 | go_back_2 |
|
||||
| app/controllers/photos_controller.rb:2:3:3:5 | show |
|
||||
| app/controllers/posts_controller.rb:2:3:3:5 | index |
|
||||
| app/controllers/posts_controller.rb:5:3:6:5 | show |
|
||||
@@ -66,10 +68,12 @@ cookiesSources
|
||||
| app/controllers/foo/bars_controller.rb:10:27:10:33 | call to cookies |
|
||||
redirectToCalls
|
||||
| app/controllers/foo/bars_controller.rb:17:5:17:30 | call to redirect_to |
|
||||
| app/controllers/foo/bars_controller.rb:27:5:27:39 | call to redirect_back_or_to |
|
||||
| app/controllers/foo/bars_controller.rb:31:5:31:56 | call to redirect_back |
|
||||
actionControllerHelperMethods
|
||||
getAssociatedControllerClasses
|
||||
| app/controllers/foo/bars_controller.rb:3:1:31:3 | BarsController | app/views/foo/bars/_widget.html.erb:0:0:0:0 | app/views/foo/bars/_widget.html.erb |
|
||||
| app/controllers/foo/bars_controller.rb:3:1:31:3 | BarsController | app/views/foo/bars/show.html.erb:0:0:0:0 | app/views/foo/bars/show.html.erb |
|
||||
| app/controllers/foo/bars_controller.rb:3:1:39:3 | BarsController | app/views/foo/bars/_widget.html.erb:0:0:0:0 | app/views/foo/bars/_widget.html.erb |
|
||||
| app/controllers/foo/bars_controller.rb:3:1:39:3 | BarsController | app/views/foo/bars/show.html.erb:0:0:0:0 | app/views/foo/bars/show.html.erb |
|
||||
controllerTemplateFiles
|
||||
| app/controllers/foo/bars_controller.rb:3:1:31:3 | BarsController | app/views/foo/bars/_widget.html.erb:0:0:0:0 | app/views/foo/bars/_widget.html.erb |
|
||||
| app/controllers/foo/bars_controller.rb:3:1:31:3 | BarsController | app/views/foo/bars/show.html.erb:0:0:0:0 | app/views/foo/bars/show.html.erb |
|
||||
| app/controllers/foo/bars_controller.rb:3:1:39:3 | BarsController | app/views/foo/bars/_widget.html.erb:0:0:0:0 | app/views/foo/bars/_widget.html.erb |
|
||||
| app/controllers/foo/bars_controller.rb:3:1:39:3 | BarsController | app/views/foo/bars/show.html.erb:0:0:0:0 | app/views/foo/bars/show.html.erb |
|
||||
|
||||
@@ -14,7 +14,7 @@ rawCalls
|
||||
renderCalls
|
||||
| app/controllers/foo/bars_controller.rb:6:5:6:37 | call to render |
|
||||
| app/controllers/foo/bars_controller.rb:23:5:23:76 | call to render |
|
||||
| app/controllers/foo/bars_controller.rb:29:5:29:17 | call to render |
|
||||
| app/controllers/foo/bars_controller.rb:37:5:37:17 | call to render |
|
||||
| app/views/foo/bars/show.html.erb:31:5:31:89 | call to render |
|
||||
renderToCalls
|
||||
| app/controllers/foo/bars_controller.rb:15:16:15:97 | call to render_to_string |
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
| action_cable.rb:1:1:1:54 | call to new |
|
||||
@@ -0,0 +1,4 @@
|
||||
import codeql.ruby.frameworks.ActionCable
|
||||
import codeql.ruby.frameworks.stdlib.Logger
|
||||
|
||||
query predicate loggerInstantiations(Logger::LoggerInstantiation l) { any() }
|
||||
@@ -0,0 +1 @@
|
||||
ActionCable::Connection::TaggedLoggerProxy.new(logger)
|
||||
@@ -23,6 +23,14 @@ class BarsController < ApplicationController
|
||||
render "foo/bars/show", locals: { display_text: dt, safe_text: "hello" }
|
||||
end
|
||||
|
||||
def go_back
|
||||
redirect_back_or_to action: "index"
|
||||
end
|
||||
|
||||
def go_back_2
|
||||
redirect_back fallback_location: { action: "index" }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def unreachable_action
|
||||
|
||||
@@ -76,6 +76,8 @@ fileSystemAccesses
|
||||
| Files.rb:41:1:41:26 | call to open |
|
||||
| Files.rb:41:1:41:43 | call to write |
|
||||
| Files.rb:48:1:48:40 | call to printf |
|
||||
| Files.rb:49:1:49:30 | call to write |
|
||||
| Files.rb:50:1:50:37 | call to atomic_write |
|
||||
fileNameSources
|
||||
| Files.rb:10:6:10:18 | call to path |
|
||||
| Files.rb:11:6:11:21 | call to to_path |
|
||||
@@ -86,7 +88,11 @@ fileWriters
|
||||
| Files.rb:40:1:40:22 | call to puts |
|
||||
| Files.rb:41:1:41:43 | call to write |
|
||||
| Files.rb:48:1:48:40 | call to printf |
|
||||
| Files.rb:49:1:49:30 | call to write |
|
||||
| Files.rb:50:1:50:37 | call to atomic_write |
|
||||
fileSystemWriteAccesses
|
||||
| Files.rb:40:1:40:22 | call to puts |
|
||||
| Files.rb:41:1:41:43 | call to write |
|
||||
| Files.rb:48:1:48:40 | call to printf |
|
||||
| Files.rb:49:1:49:30 | call to write |
|
||||
| Files.rb:50:1:50:37 | call to atomic_write |
|
||||
|
||||
@@ -46,3 +46,5 @@ str_1 = "hello"
|
||||
int_1 = 123
|
||||
# File/IO write
|
||||
io_file.printf("%s: %d\n", str_1, int_1)
|
||||
File.write("foo.txt", "hello")
|
||||
File.atomic_write("foo.txt", "hello")
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
| Railties.rb:5:5:5:34 | call to execute_command |
|
||||
| Railties.rb:6:5:6:37 | call to execute_command |
|
||||
| Railties.rb:8:5:8:16 | call to rake |
|
||||
| Railties.rb:10:5:10:27 | call to rails_command |
|
||||
| Railties.rb:12:5:12:17 | call to git |
|
||||
@@ -0,0 +1,5 @@
|
||||
private import ruby
|
||||
private import codeql.ruby.Concepts
|
||||
private import codeql.ruby.frameworks.Railties
|
||||
|
||||
query predicate systemCommandExecutions(SystemCommandExecution e) { any() }
|
||||
14
ruby/ql/test/library-tests/frameworks/railties/Railties.rb
Normal file
14
ruby/ql/test/library-tests/frameworks/railties/Railties.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
class Foo
|
||||
include Rails::Generators::Actions
|
||||
|
||||
def foo
|
||||
execute_command(:rake, "test")
|
||||
execute_command(:rails, "server")
|
||||
|
||||
rake("test")
|
||||
|
||||
rails_command("server")
|
||||
|
||||
git("status")
|
||||
end
|
||||
end
|
||||
@@ -3,11 +3,14 @@ edges
|
||||
| UrlRedirect.rb:14:17:14:22 | call to params : | UrlRedirect.rb:14:17:14:43 | call to fetch |
|
||||
| UrlRedirect.rb:19:17:19:22 | call to params : | UrlRedirect.rb:19:17:19:37 | call to to_unsafe_hash |
|
||||
| UrlRedirect.rb:24:31:24:36 | call to params : | UrlRedirect.rb:24:17:24:37 | call to filter_params |
|
||||
| UrlRedirect.rb:24:31:24:36 | call to params : | UrlRedirect.rb:63:21:63:32 | input_params : |
|
||||
| UrlRedirect.rb:24:31:24:36 | call to params : | UrlRedirect.rb:88:21:88:32 | input_params : |
|
||||
| UrlRedirect.rb:34:20:34:25 | call to params : | UrlRedirect.rb:34:20:34:31 | ...[...] : |
|
||||
| UrlRedirect.rb:34:20:34:31 | ...[...] : | UrlRedirect.rb:34:17:34:37 | "#{...}/foo" |
|
||||
| UrlRedirect.rb:58:17:58:22 | call to params : | UrlRedirect.rb:58:17:58:28 | ...[...] |
|
||||
| UrlRedirect.rb:63:21:63:32 | input_params : | UrlRedirect.rb:64:5:64:29 | call to permit : |
|
||||
| UrlRedirect.rb:63:38:63:43 | call to params : | UrlRedirect.rb:63:38:63:49 | ...[...] |
|
||||
| UrlRedirect.rb:68:38:68:43 | call to params : | UrlRedirect.rb:68:38:68:49 | ...[...] |
|
||||
| UrlRedirect.rb:73:25:73:30 | call to params : | UrlRedirect.rb:73:25:73:36 | ...[...] |
|
||||
| UrlRedirect.rb:88:21:88:32 | input_params : | UrlRedirect.rb:89:5:89:29 | call to permit : |
|
||||
nodes
|
||||
| UrlRedirect.rb:4:17:4:22 | call to params | semmle.label | call to params |
|
||||
| UrlRedirect.rb:9:17:9:22 | call to params : | semmle.label | call to params : |
|
||||
@@ -23,10 +26,16 @@ nodes
|
||||
| UrlRedirect.rb:34:20:34:31 | ...[...] : | semmle.label | ...[...] : |
|
||||
| UrlRedirect.rb:58:17:58:22 | call to params : | semmle.label | call to params : |
|
||||
| UrlRedirect.rb:58:17:58:28 | ...[...] | semmle.label | ...[...] |
|
||||
| UrlRedirect.rb:63:21:63:32 | input_params : | semmle.label | input_params : |
|
||||
| UrlRedirect.rb:64:5:64:29 | call to permit : | semmle.label | call to permit : |
|
||||
| UrlRedirect.rb:63:38:63:43 | call to params : | semmle.label | call to params : |
|
||||
| UrlRedirect.rb:63:38:63:49 | ...[...] | semmle.label | ...[...] |
|
||||
| UrlRedirect.rb:68:38:68:43 | call to params : | semmle.label | call to params : |
|
||||
| UrlRedirect.rb:68:38:68:49 | ...[...] | semmle.label | ...[...] |
|
||||
| UrlRedirect.rb:73:25:73:30 | call to params : | semmle.label | call to params : |
|
||||
| UrlRedirect.rb:73:25:73:36 | ...[...] | semmle.label | ...[...] |
|
||||
| UrlRedirect.rb:88:21:88:32 | input_params : | semmle.label | input_params : |
|
||||
| UrlRedirect.rb:89:5:89:29 | call to permit : | semmle.label | call to permit : |
|
||||
subpaths
|
||||
| UrlRedirect.rb:24:31:24:36 | call to params : | UrlRedirect.rb:63:21:63:32 | input_params : | UrlRedirect.rb:64:5:64:29 | call to permit : | UrlRedirect.rb:24:17:24:37 | call to filter_params |
|
||||
| UrlRedirect.rb:24:31:24:36 | call to params : | UrlRedirect.rb:88:21:88:32 | input_params : | UrlRedirect.rb:89:5:89:29 | call to permit : | UrlRedirect.rb:24:17:24:37 | call to filter_params |
|
||||
#select
|
||||
| UrlRedirect.rb:4:17:4:22 | call to params | UrlRedirect.rb:4:17:4:22 | call to params | UrlRedirect.rb:4:17:4:22 | call to params | Untrusted URL redirection due to $@. | UrlRedirect.rb:4:17:4:22 | call to params | a user-provided value |
|
||||
| UrlRedirect.rb:9:17:9:28 | ...[...] | UrlRedirect.rb:9:17:9:22 | call to params : | UrlRedirect.rb:9:17:9:28 | ...[...] | Untrusted URL redirection due to $@. | UrlRedirect.rb:9:17:9:22 | call to params | a user-provided value |
|
||||
@@ -35,3 +44,6 @@ subpaths
|
||||
| UrlRedirect.rb:24:17:24:37 | call to filter_params | UrlRedirect.rb:24:31:24:36 | call to params : | UrlRedirect.rb:24:17:24:37 | call to filter_params | Untrusted URL redirection due to $@. | UrlRedirect.rb:24:31:24:36 | call to params | a user-provided value |
|
||||
| UrlRedirect.rb:34:17:34:37 | "#{...}/foo" | UrlRedirect.rb:34:20:34:25 | call to params : | UrlRedirect.rb:34:17:34:37 | "#{...}/foo" | Untrusted URL redirection due to $@. | UrlRedirect.rb:34:20:34:25 | call to params | a user-provided value |
|
||||
| UrlRedirect.rb:58:17:58:28 | ...[...] | UrlRedirect.rb:58:17:58:22 | call to params : | UrlRedirect.rb:58:17:58:28 | ...[...] | Untrusted URL redirection due to $@. | UrlRedirect.rb:58:17:58:22 | call to params | a user-provided value |
|
||||
| UrlRedirect.rb:63:38:63:49 | ...[...] | UrlRedirect.rb:63:38:63:43 | call to params : | UrlRedirect.rb:63:38:63:49 | ...[...] | Untrusted URL redirection due to $@. | UrlRedirect.rb:63:38:63:43 | call to params | a user-provided value |
|
||||
| UrlRedirect.rb:68:38:68:49 | ...[...] | UrlRedirect.rb:68:38:68:43 | call to params : | UrlRedirect.rb:68:38:68:49 | ...[...] | Untrusted URL redirection due to $@. | UrlRedirect.rb:68:38:68:43 | call to params | a user-provided value |
|
||||
| UrlRedirect.rb:73:25:73:36 | ...[...] | UrlRedirect.rb:73:25:73:30 | call to params : | UrlRedirect.rb:73:25:73:36 | ...[...] | Untrusted URL redirection due to $@. | UrlRedirect.rb:73:25:73:30 | call to params | a user-provided value |
|
||||
|
||||
@@ -53,11 +53,36 @@ class UsersController < ActionController::Base
|
||||
|
||||
# BAD
|
||||
# The same as `create1` but this is reachable via a GET request, as configured
|
||||
# by the routes at the top of this file.
|
||||
# by the routes at the bottom of this file.
|
||||
def route9
|
||||
redirect_to params[:key]
|
||||
end
|
||||
|
||||
# BAD
|
||||
def route10
|
||||
redirect_back fallback_location: params[:key]
|
||||
end
|
||||
|
||||
# BAD
|
||||
def route11
|
||||
redirect_back fallback_location: params[:key], allow_other_host: true
|
||||
end
|
||||
|
||||
# BAD
|
||||
def route12
|
||||
redirect_back_or_to params[:key]
|
||||
end
|
||||
|
||||
# GOOD
|
||||
def route13
|
||||
redirect_back fallback_location: params[:key], allow_other_host: false
|
||||
end
|
||||
|
||||
# GOOD
|
||||
def route14
|
||||
redirect_back_or_to params[:key], allow_other_host: false
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def filter_params(input_params)
|
||||
|
||||
Reference in New Issue
Block a user