Skip to content

add Ruby YAML unsafe_* methods as sink #12301

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 12 commits into from
Closed
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE qhelp SYSTEM "qhelp.dtd">
<qhelp>
<overview>
<p>
Processing an unvalidated user input can allow an attacker to execute arbitrary code in your application.
Unsafe deserializing the malicious serialized yaml document through the Psych (YAML) library, making it possible to execute some code or execute arbitrary code with the help of a complete gadget chain.
</p>
</overview>
<recommendation>
<p>
After Psych(YAML) 4.0.0, the load method is same as safe_load method.
This vulnerability can be prevented by using YAML.load (same as <code>YAML.safe_load</code>), <code>YAML.load_file</code> (same as <code>YAML.safe_load_file</code>) instead of <code>YAML.unsafe_*</code> methods.
Be careful that <code>YAML.load_stream</code> don't use safe_load method, Also Be careful the <code>to_ruby</code> method of Psych get called on a trusted parsed (<code>YAML.parse*</code>) yaml document.
</p>
</recommendation>
<example>
<p>In the example below, you can see safe and unsafe methods get called by a remote user input. You can give correct authorization to users, or you can use safe methods for loading yaml documents.</p>
<sample src="YAMLUnsafeYamlDeserialization.rb" />
</example>
</qhelp>
88 changes: 88 additions & 0 deletions ruby/ql/src/experimental/CWE-502/YAMLUnsafeYamlDeserialization.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
* @name Deserialization of user-controlled data by YAML
* @description Deserializing user-controlled data may allow attackers to
* execute arbitrary code.
* @kind path-problem
* @problem.severity warning
* @security-severity 9.8
* @precision high
* @id rb/YAML-unsafe-deserialization
* @tags security
* experimental
* external/cwe/cwe-502
*/

import codeql.ruby.AST
import codeql.ruby.ApiGraphs
import codeql.ruby.DataFlow
import codeql.ruby.dataflow.RemoteFlowSources
import codeql.ruby.TaintTracking
import DataFlow::PathGraph
import codeql.ruby.security.UnsafeDeserializationCustomizations

abstract class YamlSink extends DataFlow::Node { }

class YamlUnsafeLoadArgument extends YamlSink {
YamlUnsafeLoadArgument() {
this =
API::getTopLevelMember(["YAML", "Psych"])
.getAMethodCall(["unsafe_load_file", "unsafe_load", "load_stream"])
.getArgument(0)
or
this =
API::getTopLevelMember(["YAML", "Psych"])
.getAMethodCall(["unsafe_load", "load_stream"])
.getKeywordArgument("yaml")
or
this =
API::getTopLevelMember(["YAML", "Psych"])
.getAMethodCall("unsafe_load_file")
.getKeywordArgument("filename")
}
}

class Configuration extends TaintTracking::Configuration {
Configuration() { this = "UnsafeDeserialization" }

override predicate isSource(DataFlow::Node source) {
// for detecting The CVE we should uncomment following line instead of current RemoteFlowSource
// source instanceof DataFlow::LocalSourceNode
source instanceof UnsafeDeserialization::Source
}

override predicate isSink(DataFlow::Node sink) {
// for detecting The CVE we should uncomment following line
// sink.getLocation().getFile().toString().matches("%yaml_column%") and
sink instanceof YamlSink or
sink =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you mean to place the sink at the receiver of the call?

Copy link
Contributor Author

@am0o0 am0o0 Feb 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For detecting the mentioned CVE there are a lot of results after that you uncomment source instanceof DataFlow::LocalSourceNode in isSource.
so I just want to filter the results to see the CVE taint path easier than before
that is my mistake I wrote a bad comment for that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make its own YamlSink for this. Would it make sense to add the sink at the reciever of the to_ruby call instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't put the parse_*.to_ruby sinks to YamlSink as I couldn't find a way to do taint step to do following:
for a code like

require 'yaml'
class UsersController < ActionController::Base
  def example
     Psych.parse_stream(params[:yaml_string]).to_ruby
  end
end

I wanted to make to_ruby a Mandatory condition, and also I should have a taint sink like getArgument to be able to connect the chain of parse_*.to_ruby to the taint steps.

so I couldn't use YamlSink and I had to separate parse_*.to_ruby from YamlSink

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and I thought it doesn't have any problem, as we can see the taint steps in vscode, so we can see that the user input first go to parse_* and then the .to_ruby will cause the problem.

API::getTopLevelMember(["YAML", "Psych"])
.getAMethodCall(["parse", "parse_stream", "parse_file"])
.getAMethodCall("to_ruby")
}

override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to add these taint steps as global taint steps?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understood this comment.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The taintsteps defined in the isAdditionalTaintStep of a TaintTracking configuration only apply to that particular configuration. I can imagine untrusted YAML data being parsed and then one of the properties flowing into a different injection sink (eg: SQL injection). In those cases we want to apply the taintsteps to all Tracking configurations. To do that, create a class that extends from AdditionalTaintStep:

private import codeql.ruby.dataflow.FlowSteps

private class YamlParseStep extends AdditionalTaintStep {
  override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
    ...
  }
}

You can see some examples here. You would need to create a Yaml.qll file in ruby/ql/lib/codeql/ruby/frameworks and then import it from https://github.com/github/codeql/blob/main/ruby/ql/lib/codeql/ruby/Frameworks.qll

@hmac @aibaars can you verify we want to do that?

exists(DataFlow::CallNode yaml_parser_methods |
yaml_parser_methods =
API::getTopLevelMember(["YAML", "Psych"]).getAMethodCall(["parse", "parse_stream"]) and
(
nodeFrom = yaml_parser_methods.getArgument(0) or
nodeFrom = yaml_parser_methods.getKeywordArgument("yaml")
) and
nodeTo = yaml_parser_methods.getAMethodCall("to_ruby")
)
or
exists(DataFlow::CallNode yaml_parser_methods |
yaml_parser_methods = API::getTopLevelMember(["YAML", "Psych"]).getAMethodCall("parse_file") and
(
nodeFrom = yaml_parser_methods.getArgument(0) or
nodeFrom = yaml_parser_methods.getKeywordArgument("filename")
) and
nodeTo = yaml_parser_methods.getAMethodCall("to_ruby")
)
}
}

from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "This file extraction depends on a $@.", source.getNode(),
"potentially untrusted source"
20 changes: 20 additions & 0 deletions ruby/ql/src/experimental/CWE-502/YAMLUnsafeYamlDeserialization.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require 'yaml'
class UsersController < ActionController::Base
def example
# safe
Psych.load(params[:yaml_string])
Psych.load_file(params[:yaml_file])
Psych.parse_stream(params[:yaml_string])
Psych.parse(params[:yaml_string])
Psych.parse_file(params[:yaml_file])
# unsafe
Psych.unsafe_load(params[:yaml_string])
Psych.unsafe_load_file(params[:yaml_file])
Psych.load_stream(params[:yaml_string])
Psych.parse_stream(params[:yaml_string]).to_ruby
Psych.parse(params[:yaml_string]).to_ruby
Psych.parse_file(params[:yaml_file]).to_ruby

end
end

Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
edges
| YAMLUnsafeYamlDeserialization.rb:11:23:11:28 | call to params : | YAMLUnsafeYamlDeserialization.rb:11:23:11:42 | ...[...] |
| YAMLUnsafeYamlDeserialization.rb:12:28:12:33 | call to params : | YAMLUnsafeYamlDeserialization.rb:12:28:12:45 | ...[...] |
| YAMLUnsafeYamlDeserialization.rb:13:23:13:28 | call to params : | YAMLUnsafeYamlDeserialization.rb:13:23:13:42 | ...[...] |
| YAMLUnsafeYamlDeserialization.rb:14:24:14:29 | call to params : | YAMLUnsafeYamlDeserialization.rb:14:24:14:43 | ...[...] : |
| YAMLUnsafeYamlDeserialization.rb:14:24:14:43 | ...[...] : | YAMLUnsafeYamlDeserialization.rb:14:5:14:52 | call to to_ruby |
| YAMLUnsafeYamlDeserialization.rb:15:17:15:22 | call to params : | YAMLUnsafeYamlDeserialization.rb:15:17:15:36 | ...[...] : |
| YAMLUnsafeYamlDeserialization.rb:15:17:15:36 | ...[...] : | YAMLUnsafeYamlDeserialization.rb:15:5:15:45 | call to to_ruby |
| YAMLUnsafeYamlDeserialization.rb:16:22:16:27 | call to params : | YAMLUnsafeYamlDeserialization.rb:16:22:16:39 | ...[...] : |
| YAMLUnsafeYamlDeserialization.rb:16:22:16:39 | ...[...] : | YAMLUnsafeYamlDeserialization.rb:16:5:16:48 | call to to_ruby |
| file://:0:0:0:0 | parameter self of [] : | YAMLUnsafeYamlDeserialization.rb:11:23:11:42 | ...[...] |
| file://:0:0:0:0 | parameter self of [] : | YAMLUnsafeYamlDeserialization.rb:12:28:12:45 | ...[...] |
| file://:0:0:0:0 | parameter self of [] : | YAMLUnsafeYamlDeserialization.rb:13:23:13:42 | ...[...] |
| file://:0:0:0:0 | parameter self of [] : | YAMLUnsafeYamlDeserialization.rb:14:24:14:43 | ...[...] : |
| file://:0:0:0:0 | parameter self of [] : | YAMLUnsafeYamlDeserialization.rb:15:17:15:36 | ...[...] : |
| file://:0:0:0:0 | parameter self of [] : | YAMLUnsafeYamlDeserialization.rb:16:22:16:39 | ...[...] : |
| file://:0:0:0:0 | parameter self of [](:yaml_file) : | YAMLUnsafeYamlDeserialization.rb:12:28:12:45 | ...[...] |
| file://:0:0:0:0 | parameter self of [](:yaml_file) : | YAMLUnsafeYamlDeserialization.rb:16:22:16:39 | ...[...] : |
| file://:0:0:0:0 | parameter self of [](:yaml_string) : | YAMLUnsafeYamlDeserialization.rb:11:23:11:42 | ...[...] |
| file://:0:0:0:0 | parameter self of [](:yaml_string) : | YAMLUnsafeYamlDeserialization.rb:13:23:13:42 | ...[...] |
| file://:0:0:0:0 | parameter self of [](:yaml_string) : | YAMLUnsafeYamlDeserialization.rb:14:24:14:43 | ...[...] : |
| file://:0:0:0:0 | parameter self of [](:yaml_string) : | YAMLUnsafeYamlDeserialization.rb:15:17:15:36 | ...[...] : |
nodes
| YAMLUnsafeYamlDeserialization.rb:11:23:11:28 | call to params : | semmle.label | call to params : |
| YAMLUnsafeYamlDeserialization.rb:11:23:11:42 | ...[...] | semmle.label | ...[...] |
| YAMLUnsafeYamlDeserialization.rb:12:28:12:33 | call to params : | semmle.label | call to params : |
| YAMLUnsafeYamlDeserialization.rb:12:28:12:45 | ...[...] | semmle.label | ...[...] |
| YAMLUnsafeYamlDeserialization.rb:13:23:13:28 | call to params : | semmle.label | call to params : |
| YAMLUnsafeYamlDeserialization.rb:13:23:13:42 | ...[...] | semmle.label | ...[...] |
| YAMLUnsafeYamlDeserialization.rb:14:5:14:52 | call to to_ruby | semmle.label | call to to_ruby |
| YAMLUnsafeYamlDeserialization.rb:14:24:14:29 | call to params : | semmle.label | call to params : |
| YAMLUnsafeYamlDeserialization.rb:14:24:14:43 | ...[...] : | semmle.label | ...[...] : |
| YAMLUnsafeYamlDeserialization.rb:15:5:15:45 | call to to_ruby | semmle.label | call to to_ruby |
| YAMLUnsafeYamlDeserialization.rb:15:17:15:22 | call to params : | semmle.label | call to params : |
| YAMLUnsafeYamlDeserialization.rb:15:17:15:36 | ...[...] : | semmle.label | ...[...] : |
| YAMLUnsafeYamlDeserialization.rb:16:5:16:48 | call to to_ruby | semmle.label | call to to_ruby |
| YAMLUnsafeYamlDeserialization.rb:16:22:16:27 | call to params : | semmle.label | call to params : |
| YAMLUnsafeYamlDeserialization.rb:16:22:16:39 | ...[...] : | semmle.label | ...[...] : |
| file://:0:0:0:0 | parameter self of [] : | semmle.label | parameter self of [] : |
| file://:0:0:0:0 | parameter self of [](:yaml_file) : | semmle.label | parameter self of [](:yaml_file) : |
| file://:0:0:0:0 | parameter self of [](:yaml_string) : | semmle.label | parameter self of [](:yaml_string) : |
subpaths
#select
| YAMLUnsafeYamlDeserialization.rb:11:23:11:42 | ...[...] | YAMLUnsafeYamlDeserialization.rb:11:23:11:28 | call to params : | YAMLUnsafeYamlDeserialization.rb:11:23:11:42 | ...[...] | This file extraction depends on a $@. | YAMLUnsafeYamlDeserialization.rb:11:23:11:28 | call to params | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:11:23:11:42 | ...[...] | YAMLUnsafeYamlDeserialization.rb:11:23:11:42 | ...[...] | YAMLUnsafeYamlDeserialization.rb:11:23:11:42 | ...[...] | This file extraction depends on a $@. | YAMLUnsafeYamlDeserialization.rb:11:23:11:42 | ...[...] | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:11:23:11:42 | ...[...] | file://:0:0:0:0 | parameter self of [] : | YAMLUnsafeYamlDeserialization.rb:11:23:11:42 | ...[...] | This file extraction depends on a $@. | file://:0:0:0:0 | parameter self of [] | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:11:23:11:42 | ...[...] | file://:0:0:0:0 | parameter self of [](:yaml_string) : | YAMLUnsafeYamlDeserialization.rb:11:23:11:42 | ...[...] | This file extraction depends on a $@. | file://:0:0:0:0 | parameter self of [](:yaml_string) | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:12:28:12:45 | ...[...] | YAMLUnsafeYamlDeserialization.rb:12:28:12:33 | call to params : | YAMLUnsafeYamlDeserialization.rb:12:28:12:45 | ...[...] | This file extraction depends on a $@. | YAMLUnsafeYamlDeserialization.rb:12:28:12:33 | call to params | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:12:28:12:45 | ...[...] | YAMLUnsafeYamlDeserialization.rb:12:28:12:45 | ...[...] | YAMLUnsafeYamlDeserialization.rb:12:28:12:45 | ...[...] | This file extraction depends on a $@. | YAMLUnsafeYamlDeserialization.rb:12:28:12:45 | ...[...] | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:12:28:12:45 | ...[...] | file://:0:0:0:0 | parameter self of [] : | YAMLUnsafeYamlDeserialization.rb:12:28:12:45 | ...[...] | This file extraction depends on a $@. | file://:0:0:0:0 | parameter self of [] | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:12:28:12:45 | ...[...] | file://:0:0:0:0 | parameter self of [](:yaml_file) : | YAMLUnsafeYamlDeserialization.rb:12:28:12:45 | ...[...] | This file extraction depends on a $@. | file://:0:0:0:0 | parameter self of [](:yaml_file) | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:13:23:13:42 | ...[...] | YAMLUnsafeYamlDeserialization.rb:13:23:13:28 | call to params : | YAMLUnsafeYamlDeserialization.rb:13:23:13:42 | ...[...] | This file extraction depends on a $@. | YAMLUnsafeYamlDeserialization.rb:13:23:13:28 | call to params | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:13:23:13:42 | ...[...] | YAMLUnsafeYamlDeserialization.rb:13:23:13:42 | ...[...] | YAMLUnsafeYamlDeserialization.rb:13:23:13:42 | ...[...] | This file extraction depends on a $@. | YAMLUnsafeYamlDeserialization.rb:13:23:13:42 | ...[...] | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:13:23:13:42 | ...[...] | file://:0:0:0:0 | parameter self of [] : | YAMLUnsafeYamlDeserialization.rb:13:23:13:42 | ...[...] | This file extraction depends on a $@. | file://:0:0:0:0 | parameter self of [] | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:13:23:13:42 | ...[...] | file://:0:0:0:0 | parameter self of [](:yaml_string) : | YAMLUnsafeYamlDeserialization.rb:13:23:13:42 | ...[...] | This file extraction depends on a $@. | file://:0:0:0:0 | parameter self of [](:yaml_string) | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:14:5:14:52 | call to to_ruby | YAMLUnsafeYamlDeserialization.rb:14:5:14:52 | call to to_ruby | YAMLUnsafeYamlDeserialization.rb:14:5:14:52 | call to to_ruby | This file extraction depends on a $@. | YAMLUnsafeYamlDeserialization.rb:14:5:14:52 | call to to_ruby | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:14:5:14:52 | call to to_ruby | YAMLUnsafeYamlDeserialization.rb:14:24:14:29 | call to params : | YAMLUnsafeYamlDeserialization.rb:14:5:14:52 | call to to_ruby | This file extraction depends on a $@. | YAMLUnsafeYamlDeserialization.rb:14:24:14:29 | call to params | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:14:5:14:52 | call to to_ruby | YAMLUnsafeYamlDeserialization.rb:14:24:14:43 | ...[...] : | YAMLUnsafeYamlDeserialization.rb:14:5:14:52 | call to to_ruby | This file extraction depends on a $@. | YAMLUnsafeYamlDeserialization.rb:14:24:14:43 | ...[...] | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:14:5:14:52 | call to to_ruby | file://:0:0:0:0 | parameter self of [] : | YAMLUnsafeYamlDeserialization.rb:14:5:14:52 | call to to_ruby | This file extraction depends on a $@. | file://:0:0:0:0 | parameter self of [] | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:14:5:14:52 | call to to_ruby | file://:0:0:0:0 | parameter self of [](:yaml_string) : | YAMLUnsafeYamlDeserialization.rb:14:5:14:52 | call to to_ruby | This file extraction depends on a $@. | file://:0:0:0:0 | parameter self of [](:yaml_string) | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:15:5:15:45 | call to to_ruby | YAMLUnsafeYamlDeserialization.rb:15:5:15:45 | call to to_ruby | YAMLUnsafeYamlDeserialization.rb:15:5:15:45 | call to to_ruby | This file extraction depends on a $@. | YAMLUnsafeYamlDeserialization.rb:15:5:15:45 | call to to_ruby | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:15:5:15:45 | call to to_ruby | YAMLUnsafeYamlDeserialization.rb:15:17:15:22 | call to params : | YAMLUnsafeYamlDeserialization.rb:15:5:15:45 | call to to_ruby | This file extraction depends on a $@. | YAMLUnsafeYamlDeserialization.rb:15:17:15:22 | call to params | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:15:5:15:45 | call to to_ruby | YAMLUnsafeYamlDeserialization.rb:15:17:15:36 | ...[...] : | YAMLUnsafeYamlDeserialization.rb:15:5:15:45 | call to to_ruby | This file extraction depends on a $@. | YAMLUnsafeYamlDeserialization.rb:15:17:15:36 | ...[...] | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:15:5:15:45 | call to to_ruby | file://:0:0:0:0 | parameter self of [] : | YAMLUnsafeYamlDeserialization.rb:15:5:15:45 | call to to_ruby | This file extraction depends on a $@. | file://:0:0:0:0 | parameter self of [] | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:15:5:15:45 | call to to_ruby | file://:0:0:0:0 | parameter self of [](:yaml_string) : | YAMLUnsafeYamlDeserialization.rb:15:5:15:45 | call to to_ruby | This file extraction depends on a $@. | file://:0:0:0:0 | parameter self of [](:yaml_string) | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:16:5:16:48 | call to to_ruby | YAMLUnsafeYamlDeserialization.rb:16:5:16:48 | call to to_ruby | YAMLUnsafeYamlDeserialization.rb:16:5:16:48 | call to to_ruby | This file extraction depends on a $@. | YAMLUnsafeYamlDeserialization.rb:16:5:16:48 | call to to_ruby | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:16:5:16:48 | call to to_ruby | YAMLUnsafeYamlDeserialization.rb:16:22:16:27 | call to params : | YAMLUnsafeYamlDeserialization.rb:16:5:16:48 | call to to_ruby | This file extraction depends on a $@. | YAMLUnsafeYamlDeserialization.rb:16:22:16:27 | call to params | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:16:5:16:48 | call to to_ruby | YAMLUnsafeYamlDeserialization.rb:16:22:16:39 | ...[...] : | YAMLUnsafeYamlDeserialization.rb:16:5:16:48 | call to to_ruby | This file extraction depends on a $@. | YAMLUnsafeYamlDeserialization.rb:16:22:16:39 | ...[...] | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:16:5:16:48 | call to to_ruby | file://:0:0:0:0 | parameter self of [] : | YAMLUnsafeYamlDeserialization.rb:16:5:16:48 | call to to_ruby | This file extraction depends on a $@. | file://:0:0:0:0 | parameter self of [] | potentially untrusted source |
| YAMLUnsafeYamlDeserialization.rb:16:5:16:48 | call to to_ruby | file://:0:0:0:0 | parameter self of [](:yaml_file) : | YAMLUnsafeYamlDeserialization.rb:16:5:16:48 | call to to_ruby | This file extraction depends on a $@. | file://:0:0:0:0 | parameter self of [](:yaml_file) | potentially untrusted source |
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
experimental/CWE-502/YAMLUnsafeYamlDeserialization.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require 'yaml'
class UsersController < ActionController::Base
def example
# safe
Psych.load(params[:yaml_string])
Psych.load_file(params[:yaml_file])
Psych.parse_stream(params[:yaml_string])
Psych.parse(params[:yaml_string])
Psych.parse_file(params[:yaml_file])
# unsafe
Psych.unsafe_load(params[:yaml_string])
Psych.unsafe_load_file(params[:yaml_file])
Psych.load_stream(params[:yaml_string])
Psych.parse_stream(params[:yaml_string]).to_ruby
Psych.parse(params[:yaml_string]).to_ruby
Psych.parse_file(params[:yaml_file]).to_ruby

end
end