Skip to content

Commit 6c8896d

Browse files
authored
Merge pull request github#11337 from hmac/actionmailbox
Ruby: Model ActionMailbox
2 parents d5acd31 + e3def7c commit 6c8896d

File tree

6 files changed

+102
-0
lines changed

6 files changed

+102
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Calls to `mail` and `inbound_mail` in `ActionMailbox` controllers are now considered sources of remote input.

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: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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 call to `mail` on the return value of
22+
* `ActionMailbox::Base#inbound_email`, or a direct call to
23+
* `ActionMailbox::Base#mail`, which is equivalent. The returned object
24+
* contains data from the incoming email.
25+
*/
26+
class Mail extends DataFlow::CallNode {
27+
Mail() {
28+
this =
29+
[
30+
controller().getAnInstanceSelf().getAMethodCall("inbound_email").getAMethodCall("mail"),
31+
controller().getAnInstanceSelf().getAMethodCall("mail")
32+
]
33+
}
34+
}
35+
36+
/**
37+
* A method call on a `Mail::Message` object which may return data from a remote source.
38+
*/
39+
private class RemoteContent extends DataFlow::CallNode, RemoteFlowSource::Range {
40+
RemoteContent() {
41+
this =
42+
any(Mail m)
43+
.(DataFlow::LocalSourceNode)
44+
.getAMethodCall([
45+
"body", "to", "from", "raw_source", "subject", "from_address",
46+
"recipients_addresses", "cc_addresses", "bcc_addresses", "in_reply_to",
47+
"references", "reply_to", "raw_envelope", "to_s", "encoded", "header", "bcc", "cc",
48+
"text_part", "html_part"
49+
])
50+
}
51+
52+
override string getSourceType() { result = "ActionMailbox" }
53+
}
54+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
messageInstances
2+
| action_mailbox.rb:3:5:3:8 | call to mail |
3+
| action_mailbox.rb:4:5:4:8 | call to mail |
4+
| action_mailbox.rb:6:5:6:10 | call to mail |
5+
| action_mailbox.rb:10:5:10:8 | call to mail |
6+
| action_mailbox.rb:16:9:16:12 | call to mail |
7+
remoteFlowSources
8+
| action_mailbox.rb:3:5:3:13 | call to body |
9+
| action_mailbox.rb:4:5:4:11 | call to to |
10+
| action_mailbox.rb:6:5:6:13 | call to to |
11+
| action_mailbox.rb:10:5:10:18 | call to text_part |
12+
| action_mailbox.rb:16:9:16:23 | call to raw_source |
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
private import codeql.ruby.frameworks.ActionMailbox
2+
private import codeql.ruby.DataFlow
3+
private import codeql.ruby.dataflow.RemoteFlowSources
4+
5+
query predicate messageInstances(ActionMailbox::Mail c) { any() }
6+
7+
query predicate remoteFlowSources(RemoteFlowSource r) { any() }
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
class A < ActionMailbox::Base
2+
def process
3+
mail.body
4+
mail.to
5+
m = inbound_email
6+
m.mail.to
7+
end
8+
9+
def other_method
10+
mail.text_part
11+
end
12+
end
13+
14+
class B < A
15+
def process
16+
mail.raw_source
17+
end
18+
end
19+
20+
class C # not a mailbox class
21+
def process
22+
mail.subject
23+
end
24+
end

0 commit comments

Comments
 (0)