Skip to content

Commit 8e40899

Browse files
authored
Merge pull request github#7419 from github/hmac/const-get
2 parents 2fa1880 + 43ddc54 commit 8e40899

File tree

6 files changed

+69
-0
lines changed

6 files changed

+69
-0
lines changed

ruby/ql/lib/codeql/ruby/frameworks/StandardLibrary.qll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,18 @@ class ModuleEvalCallCodeExecution extends CodeExecution::Range, DataFlow::CallNo
335335
override DataFlow::Node getCode() { result = this.getArgument(0) }
336336
}
337337

338+
/**
339+
* A call to `Module#const_get`, which interprets its argument as a Ruby constant.
340+
* Passing user input to this method may result in instantiation of arbitrary Ruby classes.
341+
*/
342+
class ModuleConstGetCallCodeExecution extends CodeExecution::Range, DataFlow::CallNode {
343+
ModuleConstGetCallCodeExecution() {
344+
this.asExpr().getExpr().(UnknownMethodCall).getMethodName() = "const_get"
345+
}
346+
347+
override DataFlow::Node getCode() { result = this.getArgument(0) }
348+
}
349+
338350
/** Flow summary for `Regexp.escape` and its alias, `Regexp.quote`. */
339351
class RegexpEscapeSummary extends SummarizedCallable {
340352
RegexpEscapeSummary() { this = "Regexp.escape" }

ruby/ql/test/library-tests/frameworks/StandardLibrary.expected

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,10 @@ loggerLoggingCallInputs
102102
| Logging.rb:73:5:73:63 | call to log | Logging.rb:73:36:73:45 | "message1" |
103103
| Logging.rb:74:5:74:76 | call to log | Logging.rb:74:36:74:45 | "message2" |
104104
| Logging.rb:74:5:74:76 | call to log | Logging.rb:74:48:74:58 | "progname2" |
105+
moduleConstGetCallCodeExecutions
106+
| const_get.rb:1:1:1:24 | call to const_get | const_get.rb:1:18:1:23 | "Math" |
107+
| const_get.rb:2:1:2:28 | call to const_get | const_get.rb:2:22:2:27 | "Math" |
108+
| const_get.rb:3:1:3:20 | call to const_get | const_get.rb:3:16:3:19 | "PI" |
109+
| const_get.rb:4:1:4:19 | call to const_get | const_get.rb:4:16:4:18 | :PI |
110+
| const_get.rb:22:1:22:33 | call to const_get | const_get.rb:22:18:22:32 | "Foo::Baz::VAL" |
111+
| const_get.rb:23:1:23:25 | call to const_get | const_get.rb:23:15:23:24 | "Bar::VAL" |

ruby/ql/test/library-tests/frameworks/StandardLibrary.ql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,7 @@ query DataFlow::Node moduleEvalCallCodeExecutions(ModuleEvalCallCodeExecution e)
3232
}
3333

3434
query DataFlow::Node loggerLoggingCallInputs(LoggerLoggingCall c) { result = c.getAnInput() }
35+
36+
query DataFlow::Node moduleConstGetCallCodeExecutions(ModuleConstGetCallCodeExecution e) {
37+
result = e.getCode()
38+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
Object.const_get("Math")
2+
self.class.const_get("Math")
3+
Math.const_get("PI")
4+
Math.const_get(:PI)
5+
6+
module Foo
7+
class Bar
8+
VAL = 10
9+
10+
def const_get(x)
11+
"my custom const_get method"
12+
end
13+
end
14+
15+
class Baz < Bar
16+
def self.const_get(x)
17+
"another custom const_get method"
18+
end
19+
end
20+
end
21+
22+
Object.const_get("Foo::Baz::VAL")
23+
Foo.const_get("Bar::VAL")
24+
25+
# Should not be identified as a use of Module#const_get
26+
Foo::Bar.new.const_get 5
27+
Foo::Baz.const_get 5

ruby/ql/test/query-tests/security/cwe-094/CodeInjection.expected

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,22 @@ edges
33
| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:6:10:6:13 | code |
44
| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:18:20:18:23 | code |
55
| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:21:21:21:24 | code |
6+
| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:27:15:27:18 | code |
7+
| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:30:19:30:22 | code |
68
nodes
79
| CodeInjection.rb:3:12:3:17 | call to params : | semmle.label | call to params : |
810
| CodeInjection.rb:3:12:3:24 | ...[...] : | semmle.label | ...[...] : |
911
| CodeInjection.rb:6:10:6:13 | code | semmle.label | code |
1012
| CodeInjection.rb:9:10:9:15 | call to params | semmle.label | call to params |
1113
| CodeInjection.rb:18:20:18:23 | code | semmle.label | code |
1214
| CodeInjection.rb:21:21:21:24 | code | semmle.label | code |
15+
| CodeInjection.rb:27:15:27:18 | code | semmle.label | code |
16+
| CodeInjection.rb:30:19:30:22 | code | semmle.label | code |
1317
subpaths
1418
#select
1519
| CodeInjection.rb:6:10:6:13 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:6:10:6:13 | code | This code execution depends on $@. | CodeInjection.rb:3:12:3:17 | call to params | a user-provided value |
1620
| CodeInjection.rb:9:10:9:15 | call to params | CodeInjection.rb:9:10:9:15 | call to params | CodeInjection.rb:9:10:9:15 | call to params | This code execution depends on $@. | CodeInjection.rb:9:10:9:15 | call to params | a user-provided value |
1721
| CodeInjection.rb:18:20:18:23 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:18:20:18:23 | code | This code execution depends on $@. | CodeInjection.rb:3:12:3:17 | call to params | a user-provided value |
1822
| CodeInjection.rb:21:21:21:24 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:21:21:21:24 | code | This code execution depends on $@. | CodeInjection.rb:3:12:3:17 | call to params | a user-provided value |
23+
| CodeInjection.rb:27:15:27:18 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:27:15:27:18 | code | This code execution depends on $@. | CodeInjection.rb:3:12:3:17 | call to params | a user-provided value |
24+
| CodeInjection.rb:30:19:30:22 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:30:19:30:22 | code | This code execution depends on $@. | CodeInjection.rb:3:12:3:17 | call to params | a user-provided value |

ruby/ql/test/query-tests/security/cwe-094/CodeInjection.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@ def create
2222

2323
# GOOD
2424
Bar.class_eval(code)
25+
26+
# BAD
27+
const_get(code)
28+
29+
# BAD
30+
Foo.const_get(code)
31+
32+
# GOOD
33+
Bar.const_get(code)
2534
end
2635

2736
def update
@@ -50,4 +59,8 @@ class Bar
5059
def self.class_eval(x)
5160
true
5261
end
62+
63+
def self.const_get(x)
64+
true
65+
end
5366
end

0 commit comments

Comments
 (0)