Skip to content

Commit eac5aa2

Browse files
committed
Ruby: Model remote input for ActionMailbox
1 parent 375403f commit eac5aa2

File tree

5 files changed

+110
-0
lines changed

5 files changed

+110
-0
lines changed

ruby/ql/lib/codeql/ruby/Frameworks.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ private import codeql.ruby.frameworks.ActionCable
77
private import codeql.ruby.frameworks.ActionController
88
private import codeql.ruby.frameworks.ActiveJob
99
private import codeql.ruby.frameworks.ActionMailer
10+
private import codeql.ruby.frameworks.ActionMailbox
1011
private import codeql.ruby.frameworks.ActiveRecord
1112
private import codeql.ruby.frameworks.ActiveResource
1213
private import codeql.ruby.frameworks.ActiveStorage
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/**
2+
* Models the `ActionMailbox` library, which is part of Rails.
3+
* Version: 7.0.4.
4+
*/
5+
6+
private import codeql.ruby.AST
7+
private import codeql.ruby.Concepts
8+
private import codeql.ruby.DataFlow
9+
private import codeql.ruby.dataflow.RemoteFlowSources
10+
11+
/**
12+
* Models the `ActionMailbox` library, which is part of Rails.
13+
* Version: 7.0.4.
14+
*/
15+
module ActionMailbox {
16+
private DataFlow::ClassNode controller() {
17+
result = DataFlow::getConstant("ActionMailbox").getConstant("Base").getADescendentModule()
18+
}
19+
20+
/**
21+
* A method in a mailbox which receives incoming mail.
22+
*/
23+
class Process extends DataFlow::MethodNode {
24+
Process() { this = controller().getAnInstanceMethod() and this.getMethodName() = "process" }
25+
}
26+
27+
/**
28+
* A call to `ActionMailbox::Base#mail`, which is equivalent to calling `inbound_mail.mail`.
29+
* The returned object contains data from the incoming mail.
30+
*/
31+
class MailCall extends DataFlow::CallNode, Mail::Message::Range {
32+
MailCall() { this = controller().getAnInstanceSelf().getAMethodCall("mail") }
33+
}
34+
35+
/**
36+
* Models classes from the `mail` library.
37+
* Version: 2.7.1.
38+
*/
39+
module Mail {
40+
/**
41+
* An instance of `Mail::Message`.
42+
*/
43+
class Message extends DataFlow::Node instanceof Message::Range { }
44+
45+
module Message {
46+
abstract class Range extends DataFlow::Node { }
47+
}
48+
49+
/**
50+
* A method call on a `Mail::Message` object which may return data from a remote source.
51+
*/
52+
class RemoteContent extends DataFlow::CallNode, RemoteFlowSource::Range {
53+
RemoteContent() {
54+
this.getReceiver() instanceof Message and
55+
this.getMethodName() =
56+
[
57+
"body", "to", "from", "raw_source", "subject", "from_address", "recipients_addresses",
58+
"cc_addresses", "bcc_addresses", "in_reply_to", "references", "reply_to",
59+
"raw_envelope", "to_s", "encoded", "header", "bcc", "cc", "text_part", "html_part"
60+
]
61+
}
62+
63+
override string getSourceType() { result = "ActionMailbox" }
64+
}
65+
}
66+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
processMethods
2+
| action_mailbox.rb:2:3:5:5 | process |
3+
| action_mailbox.rb:13:5:15:7 | process |
4+
messageInstances
5+
| action_mailbox.rb:3:5:3:8 | call to mail |
6+
| action_mailbox.rb:4:5:4:8 | call to mail |
7+
| action_mailbox.rb:8:5:8:8 | call to mail |
8+
| action_mailbox.rb:14:9:14:12 | call to mail |
9+
remoteContent
10+
| action_mailbox.rb:3:5:3:13 | call to body |
11+
| action_mailbox.rb:4:5:4:11 | call to to |
12+
| action_mailbox.rb:8:5:8:18 | call to text_part |
13+
| action_mailbox.rb:14:9:14:23 | call to raw_source |
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
private import codeql.ruby.frameworks.ActionMailbox
2+
private import codeql.ruby.DataFlow
3+
4+
query predicate processMethods(ActionMailbox::Process p) { any() }
5+
6+
query predicate messageInstances(ActionMailbox::Mail::Message c) { any() }
7+
8+
query predicate remoteContent(ActionMailbox::Mail::RemoteContent r) { any() }
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
class A < ActionMailbox::Base
2+
def process
3+
mail.body
4+
mail.to
5+
end
6+
7+
def other_method
8+
mail.text_part
9+
end
10+
end
11+
12+
class B < A
13+
def process
14+
mail.raw_source
15+
end
16+
end
17+
18+
class C # not a mailbox class
19+
def process
20+
mail.subject
21+
end
22+
end

0 commit comments

Comments
 (0)