Ruby: Model remote input for ActionMailbox

This commit is contained in:
Harry Maclean
2022-11-23 12:57:06 +13:00
parent 375403fb9d
commit eac5aa26ee
5 changed files with 110 additions and 0 deletions

View File

@@ -7,6 +7,7 @@ private import codeql.ruby.frameworks.ActionCable
private import codeql.ruby.frameworks.ActionController
private import codeql.ruby.frameworks.ActiveJob
private import codeql.ruby.frameworks.ActionMailer
private import codeql.ruby.frameworks.ActionMailbox
private import codeql.ruby.frameworks.ActiveRecord
private import codeql.ruby.frameworks.ActiveResource
private import codeql.ruby.frameworks.ActiveStorage

View File

@@ -0,0 +1,66 @@
/**
* Models the `ActionMailbox` library, which is part of Rails.
* Version: 7.0.4.
*/
private import codeql.ruby.AST
private import codeql.ruby.Concepts
private import codeql.ruby.DataFlow
private import codeql.ruby.dataflow.RemoteFlowSources
/**
* Models the `ActionMailbox` library, which is part of Rails.
* Version: 7.0.4.
*/
module ActionMailbox {
private DataFlow::ClassNode controller() {
result = DataFlow::getConstant("ActionMailbox").getConstant("Base").getADescendentModule()
}
/**
* A method in a mailbox which receives incoming mail.
*/
class Process extends DataFlow::MethodNode {
Process() { this = controller().getAnInstanceMethod() and this.getMethodName() = "process" }
}
/**
* A call to `ActionMailbox::Base#mail`, which is equivalent to calling `inbound_mail.mail`.
* The returned object contains data from the incoming mail.
*/
class MailCall extends DataFlow::CallNode, Mail::Message::Range {
MailCall() { this = controller().getAnInstanceSelf().getAMethodCall("mail") }
}
/**
* Models classes from the `mail` library.
* Version: 2.7.1.
*/
module Mail {
/**
* An instance of `Mail::Message`.
*/
class Message extends DataFlow::Node instanceof Message::Range { }
module Message {
abstract class Range extends DataFlow::Node { }
}
/**
* A method call on a `Mail::Message` object which may return data from a remote source.
*/
class RemoteContent extends DataFlow::CallNode, RemoteFlowSource::Range {
RemoteContent() {
this.getReceiver() instanceof Message and
this.getMethodName() =
[
"body", "to", "from", "raw_source", "subject", "from_address", "recipients_addresses",
"cc_addresses", "bcc_addresses", "in_reply_to", "references", "reply_to",
"raw_envelope", "to_s", "encoded", "header", "bcc", "cc", "text_part", "html_part"
]
}
override string getSourceType() { result = "ActionMailbox" }
}
}
}

View File

@@ -0,0 +1,13 @@
processMethods
| action_mailbox.rb:2:3:5:5 | process |
| action_mailbox.rb:13:5:15:7 | process |
messageInstances
| action_mailbox.rb:3:5:3:8 | call to mail |
| action_mailbox.rb:4:5:4:8 | call to mail |
| action_mailbox.rb:8:5:8:8 | call to mail |
| action_mailbox.rb:14:9:14:12 | call to mail |
remoteContent
| action_mailbox.rb:3:5:3:13 | call to body |
| action_mailbox.rb:4:5:4:11 | call to to |
| action_mailbox.rb:8:5:8:18 | call to text_part |
| action_mailbox.rb:14:9:14:23 | call to raw_source |

View File

@@ -0,0 +1,8 @@
private import codeql.ruby.frameworks.ActionMailbox
private import codeql.ruby.DataFlow
query predicate processMethods(ActionMailbox::Process p) { any() }
query predicate messageInstances(ActionMailbox::Mail::Message c) { any() }
query predicate remoteContent(ActionMailbox::Mail::RemoteContent r) { any() }

View File

@@ -0,0 +1,22 @@
class A < ActionMailbox::Base
def process
mail.body
mail.to
end
def other_method
mail.text_part
end
end
class B < A
def process
mail.raw_source
end
end
class C # not a mailbox class
def process
mail.subject
end
end