Skip to content

Commit 5a98f66

Browse files
committed
simplify the modeling of html_safe. Any call to html_safe is now considered an XSS sink
1 parent 19bcd28 commit 5a98f66

File tree

7 files changed

+16
-20
lines changed

7 files changed

+16
-20
lines changed

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

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -311,14 +311,6 @@ private class ActionControllerRenderToCall extends ActionControllerContextCall,
311311
ActionControllerRenderToCall() { this.getMethodName() = ["render_to_body", "render_to_string"] }
312312
}
313313

314-
/** A call to `html_safe` from within a controller. */
315-
private class ActionControllerHtmlSafeCall extends HtmlSafeCallImpl {
316-
ActionControllerHtmlSafeCall() {
317-
this.getMethodName() = "html_safe" and
318-
this.getEnclosingModule() instanceof ActionControllerControllerClass
319-
}
320-
}
321-
322314
/** A call to `html_escape` from within a controller. */
323315
private class ActionControllerHtmlEscapeCall extends HtmlEscapeCallImpl {
324316
ActionControllerHtmlEscapeCall() {

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,6 @@ predicate inActionViewContext(AstNode n) {
3939
n.getLocation().getFile() instanceof ErbFile
4040
}
4141

42-
/** A call to `html_safe` from within a template. */
43-
private class ActionViewHtmlSafeCall extends HtmlSafeCallImpl {
44-
ActionViewHtmlSafeCall() { this.getMethodName() = "html_safe" and inActionViewContext(this) }
45-
}
46-
4742
/**
4843
* A call to a Rails method that escapes HTML.
4944
*/

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@ private import codeql.ruby.security.OpenSSL
1616
*/
1717
module Rails {
1818
/**
19+
* DEPRECATED: Any call to `html_safe` is considered an XSS sink.
1920
* A method call on a string to mark it as HTML safe for Rails. Strings marked
2021
* as such will not be automatically escaped when inserted into HTML.
2122
*/
22-
class HtmlSafeCall extends MethodCall instanceof HtmlSafeCallImpl { }
23+
deprecated class HtmlSafeCall extends MethodCall {
24+
HtmlSafeCall() { this.getMethodName() = "html_safe" }
25+
}
2326

2427
/** A call to a Rails method to escape HTML. */
2528
class HtmlEscapeCall extends MethodCall instanceof HtmlEscapeCallImpl { }

ruby/ql/lib/codeql/ruby/frameworks/internal/Rails.qll

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
private import codeql.ruby.AST
22

3-
abstract class HtmlSafeCallImpl extends MethodCall { }
4-
53
abstract class HtmlEscapeCallImpl extends MethodCall { }
64

75
abstract class RenderCallImpl extends MethodCall { }

ruby/ql/lib/codeql/ruby/security/XSS.qll

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,7 @@ private module Shared {
6262
*/
6363
class HtmlSafeCallAsSink extends Sink {
6464
HtmlSafeCallAsSink() {
65-
exists(Rails::HtmlSafeCall c, ErbOutputDirective d |
66-
this.asExpr().getExpr() = c.getReceiver() and
67-
c = d.getTerminalStmt()
68-
)
65+
this = any(DataFlow::CallNode call | call.getMethodName() = "html_safe").getReceiver()
6966
}
7067
}
7168

ruby/ql/test/query-tests/security/cwe-079/ReflectedXSS.expected

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ edges
1919
| app/controllers/foo/bars_controller.rb:26:53:26:54 | dt : | app/views/foo/bars/show.html.erb:12:9:12:26 | ...[...] |
2020
| app/controllers/foo/bars_controller.rb:26:53:26:54 | dt : | app/views/foo/bars/show.html.erb:36:3:36:14 | call to display_text |
2121
| app/controllers/foo/bars_controller.rb:26:53:26:54 | dt : | app/views/foo/bars/show.html.erb:44:76:44:87 | call to display_text : |
22+
| app/controllers/foo/bars_controller.rb:30:11:30:16 | call to params : | app/controllers/foo/bars_controller.rb:30:11:30:28 | ...[...] : |
23+
| app/controllers/foo/bars_controller.rb:30:11:30:28 | ...[...] : | app/controllers/foo/bars_controller.rb:31:5:31:7 | str |
2224
| app/views/foo/bars/show.html.erb:44:64:44:87 | ... + ... : | app/views/foo/bars/_widget.html.erb:5:9:5:20 | call to display_text |
2325
| app/views/foo/bars/show.html.erb:44:64:44:87 | ... + ... : | app/views/foo/bars/_widget.html.erb:8:9:8:36 | ...[...] |
2426
| app/views/foo/bars/show.html.erb:44:76:44:87 | call to display_text : | app/views/foo/bars/show.html.erb:44:64:44:87 | ... + ... : |
@@ -41,6 +43,9 @@ nodes
4143
| app/controllers/foo/bars_controller.rb:24:39:24:59 | ... = ... | semmle.label | ... = ... |
4244
| app/controllers/foo/bars_controller.rb:24:39:24:59 | ...[...] : | semmle.label | ...[...] : |
4345
| app/controllers/foo/bars_controller.rb:26:53:26:54 | dt : | semmle.label | dt : |
46+
| app/controllers/foo/bars_controller.rb:30:11:30:16 | call to params : | semmle.label | call to params : |
47+
| app/controllers/foo/bars_controller.rb:30:11:30:28 | ...[...] : | semmle.label | ...[...] : |
48+
| app/controllers/foo/bars_controller.rb:31:5:31:7 | str | semmle.label | str |
4449
| app/views/foo/bars/_widget.html.erb:5:9:5:20 | call to display_text | semmle.label | call to display_text |
4550
| app/views/foo/bars/_widget.html.erb:8:9:8:36 | ...[...] | semmle.label | ...[...] |
4651
| app/views/foo/bars/show.html.erb:2:18:2:30 | @user_website | semmle.label | @user_website |
@@ -64,6 +69,7 @@ nodes
6469
subpaths
6570
#select
6671
| app/controllers/foo/bars_controller.rb:24:39:24:59 | ... = ... | app/controllers/foo/bars_controller.rb:24:39:24:44 | call to params : | app/controllers/foo/bars_controller.rb:24:39:24:59 | ... = ... | Cross-site scripting vulnerability due to a $@. | app/controllers/foo/bars_controller.rb:24:39:24:44 | call to params | user-provided value |
72+
| app/controllers/foo/bars_controller.rb:31:5:31:7 | str | app/controllers/foo/bars_controller.rb:30:11:30:16 | call to params : | app/controllers/foo/bars_controller.rb:31:5:31:7 | str | Cross-site scripting vulnerability due to a $@. | app/controllers/foo/bars_controller.rb:30:11:30:16 | call to params | user-provided value |
6773
| app/views/foo/bars/_widget.html.erb:5:9:5:20 | call to display_text | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/_widget.html.erb:5:9:5:20 | call to display_text | Cross-site scripting vulnerability due to a $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | user-provided value |
6874
| app/views/foo/bars/_widget.html.erb:8:9:8:36 | ...[...] | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/_widget.html.erb:8:9:8:36 | ...[...] | Cross-site scripting vulnerability due to a $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | user-provided value |
6975
| app/views/foo/bars/show.html.erb:2:18:2:30 | @user_website | app/controllers/foo/bars_controller.rb:17:21:17:26 | call to params : | app/views/foo/bars/show.html.erb:2:18:2:30 | @user_website | Cross-site scripting vulnerability due to a $@. | app/controllers/foo/bars_controller.rb:17:21:17:26 | call to params | user-provided value |

ruby/ql/test/query-tests/security/cwe-079/app/controllers/foo/bars_controller.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,9 @@ def show
2525
response.header["x-customer-header"] = params[:bar] # OK - header not relevant to XSS
2626
render "foo/bars/show", locals: { display_text: dt, safe_text: "hello" }
2727
end
28+
29+
def make_safe_html
30+
str = params[:user_name]
31+
str.html_safe
32+
end
2833
end

0 commit comments

Comments
 (0)