mirror of
https://github.com/github/codeql.git
synced 2026-06-12 16:31:10 +02:00
Compare commits
2 Commits
main
...
copilot/ql
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ec64167ac | ||
|
|
de281fc00c |
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
category: fix
|
|
||||||
---
|
|
||||||
* The query `actions/pr-on-self-hosted-runner` was updated to the latest standard runner labels reducing false positive results.
|
|
||||||
@@ -2,12 +2,10 @@ import actions
|
|||||||
|
|
||||||
bindingset[runner]
|
bindingset[runner]
|
||||||
predicate isGithubHostedRunner(string runner) {
|
predicate isGithubHostedRunner(string runner) {
|
||||||
// The list of github hosted repos:
|
// list of github hosted repos: https://github.com/actions/runner-images/blob/main/README.md#available-images
|
||||||
// https://github.com/actions/runner-images/blob/main/README.md#available-images
|
runner
|
||||||
// https://docs.github.com/en/enterprise-cloud@latest/actions/how-tos/write-workflows/choose-where-workflows-run/choose-the-runner-for-a-job#standard-github-hosted-runners-for-public-repositories
|
.toLowerCase()
|
||||||
runner.toLowerCase().regexpMatch("^ubuntu-([0-9.]+|latest|slim)(-arm)?$") or
|
.regexpMatch("^(ubuntu-([0-9.]+|latest)|macos-([0-9]+|latest)(-x?large)?|windows-([0-9.]+|latest))$")
|
||||||
runner.toLowerCase().regexpMatch("^macos-([0-9]+|latest)(-x?large|-intel)?$") or
|
|
||||||
runner.toLowerCase().regexpMatch("^windows-([0-9.]+|latest)(-vs[0-9.]+)?(-arm)?$")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[runner]
|
bindingset[runner]
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
name: test
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os:
|
|
||||||
- ubuntu-latest
|
|
||||||
- ubuntu-24.04
|
|
||||||
- ubuntu-24.04-arm
|
|
||||||
- ubuntu-22.04
|
|
||||||
- ubuntu-22.04-arm
|
|
||||||
- ubuntu-26.04
|
|
||||||
- ubuntu-26.04-arm
|
|
||||||
- ubuntu-slim
|
|
||||||
- macos-26
|
|
||||||
- macos-26-xlarge
|
|
||||||
- macos-26-intel
|
|
||||||
- macos-26-large
|
|
||||||
- macos-latest-large
|
|
||||||
- macos-15-large
|
|
||||||
- macos-15
|
|
||||||
- macos-15-intel
|
|
||||||
- macos-latest
|
|
||||||
- macos-15
|
|
||||||
- macos-15-xlarge
|
|
||||||
- macos-14-large
|
|
||||||
- macos-14
|
|
||||||
- macos-14-xlarge
|
|
||||||
- windows-2025-vs2026
|
|
||||||
- windows-latest
|
|
||||||
- windows-2025
|
|
||||||
- windows-2022
|
|
||||||
- windows-11
|
|
||||||
- windows-11-arm
|
|
||||||
- windows-11-vs2026-arm
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- run: cmd
|
|
||||||
@@ -203,7 +203,7 @@ module Ast implements AstSig<Location> {
|
|||||||
final private class FinalTryStmt = CS::TryStmt;
|
final private class FinalTryStmt = CS::TryStmt;
|
||||||
|
|
||||||
class TryStmt extends FinalTryStmt {
|
class TryStmt extends FinalTryStmt {
|
||||||
AstNode getBody(int index) { index = 0 and result = this.getBlock() }
|
Stmt getBody() { result = this.getBlock() }
|
||||||
|
|
||||||
CatchClause getCatch(int index) { result = this.getCatchClause(index) }
|
CatchClause getCatch(int index) { result = this.getCatchClause(index) }
|
||||||
|
|
||||||
|
|||||||
@@ -117,18 +117,15 @@ private module Ast implements AstSig<Location> {
|
|||||||
final private class FinalTryStmt = J::TryStmt;
|
final private class FinalTryStmt = J::TryStmt;
|
||||||
|
|
||||||
class TryStmt extends FinalTryStmt {
|
class TryStmt extends FinalTryStmt {
|
||||||
AstNode getBody(int index) {
|
Stmt getBody() { result = super.getBlock() }
|
||||||
result = super.getResource(index)
|
|
||||||
or
|
|
||||||
index = count(super.getAResource()) and
|
|
||||||
result = super.getBlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
CatchClause getCatch(int index) { result = super.getCatchClause(index) }
|
CatchClause getCatch(int index) { result = super.getCatchClause(index) }
|
||||||
|
|
||||||
Stmt getFinally() { result = super.getFinally() }
|
Stmt getFinally() { result = super.getFinally() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AstNode getTryInit(TryStmt try, int index) { result = try.getResource(index) }
|
||||||
|
|
||||||
final private class FinalCatchClause = J::CatchClause;
|
final private class FinalCatchClause = J::CatchClause;
|
||||||
|
|
||||||
class CatchClause extends FinalCatchClause {
|
class CatchClause extends FinalCatchClause {
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
experimental/CWE-522-DecompressionBombs/DecompressionBombs.ql
|
query: experimental/CWE-522-DecompressionBombs/DecompressionBombs.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
require 'zlib'
|
require 'zlib'
|
||||||
|
|
||||||
class TestController < ActionController::Base
|
class TestController < ActionController::Base
|
||||||
gzip_path = params[:path]
|
gzip_path = params[:path] # $ Source
|
||||||
|
|
||||||
Zlib::GzipReader.open(gzip_path).read
|
Zlib::GzipReader.open(gzip_path).read # $ Alert
|
||||||
Zlib::GzipReader.open(gzip_path) do |uncompressedfile|
|
Zlib::GzipReader.open(gzip_path) do |uncompressedfile|
|
||||||
puts uncompressedfile.read
|
puts uncompressedfile.read
|
||||||
end
|
end # $ Alert
|
||||||
Zlib::GzipReader.open(gzip_path) do |uncompressedfile|
|
Zlib::GzipReader.open(gzip_path) do |uncompressedfile|
|
||||||
uncompressedfile.each do |entry|
|
uncompressedfile.each do |entry|
|
||||||
puts entry
|
puts entry
|
||||||
end
|
end
|
||||||
end
|
end # $ Alert
|
||||||
uncompressedfile = Zlib::GzipReader.open(gzip_path)
|
uncompressedfile = Zlib::GzipReader.open(gzip_path) # $ Alert
|
||||||
uncompressedfile.each do |entry|
|
uncompressedfile.each do |entry|
|
||||||
puts entry
|
puts entry
|
||||||
end
|
end
|
||||||
|
|
||||||
Zlib::GzipReader.new(File.open(gzip_path, 'rb')).read
|
Zlib::GzipReader.new(File.open(gzip_path, 'rb')).read # $ Alert
|
||||||
Zlib::GzipReader.new(File.open(gzip_path, 'rb')).each do |entry|
|
Zlib::GzipReader.new(File.open(gzip_path, 'rb')).each do |entry| # $ Alert
|
||||||
puts entry
|
puts entry
|
||||||
end
|
end
|
||||||
|
|
||||||
Zlib::GzipReader.zcat(open(gzip_path))
|
Zlib::GzipReader.zcat(open(gzip_path)) # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
require 'zip'
|
require 'zip'
|
||||||
|
|
||||||
class TestController < ActionController::Base
|
class TestController < ActionController::Base
|
||||||
zipfile_path = params[:path]
|
zipfile_path = params[:path] # $ Source
|
||||||
|
|
||||||
Zip::InputStream.open(zipfile_path) do |input|
|
Zip::InputStream.open(zipfile_path) do |input|
|
||||||
while (entry = input.get_next_entry)
|
while (entry = input.get_next_entry)
|
||||||
puts :file_name, entry.name
|
puts :file_name, entry.name
|
||||||
input
|
input
|
||||||
end
|
end
|
||||||
end
|
end # $ Alert
|
||||||
Zip::InputStream.open(zipfile_path) do |input|
|
Zip::InputStream.open(zipfile_path) do |input|
|
||||||
input.read
|
input.read
|
||||||
end
|
end # $ Alert
|
||||||
input = Zip::InputStream.open(zipfile_path)
|
input = Zip::InputStream.open(zipfile_path) # $ Alert
|
||||||
|
|
||||||
Zip::File.open(zipfile_path).read "10GB"
|
Zip::File.open(zipfile_path).read "10GB" # $ Alert
|
||||||
Zip::File.open(zipfile_path).extract "10GB", "./"
|
Zip::File.open(zipfile_path).extract "10GB", "./" # $ Alert
|
||||||
|
|
||||||
Zip::File.open(zipfile_path) do |zip_file|
|
Zip::File.open(zipfile_path) do |zip_file|
|
||||||
# Handle entries one by one
|
# Handle entries one by one
|
||||||
@@ -25,33 +25,33 @@ class TestController < ActionController::Base
|
|||||||
# Extract to file or directory based on name in the archive
|
# Extract to file or directory based on name in the archive
|
||||||
entry.extract
|
entry.extract
|
||||||
# Read into memory
|
# Read into memory
|
||||||
entry.get_input_stream.read
|
entry.get_input_stream.read # $ Alert
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
zip_file = Zip::File.open(zipfile_path)
|
zip_file = Zip::File.open(zipfile_path)
|
||||||
zip_file.each do |entry|
|
zip_file.each do |entry|
|
||||||
entry.extract
|
entry.extract # $ Alert
|
||||||
entry.get_input_stream.read
|
entry.get_input_stream.read # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
# Find specific entry
|
# Find specific entry
|
||||||
Zip::File.open(zipfile_path) do |zip_file|
|
Zip::File.open(zipfile_path) do |zip_file|
|
||||||
zip_file.glob('*.xml').each do |entry|
|
zip_file.glob('*.xml').each do |entry|
|
||||||
zip_file.read(entry.name)
|
zip_file.read(entry.name) # $ Alert
|
||||||
entry.extract
|
entry.extract # $ Alert
|
||||||
end
|
end
|
||||||
entry = zip_file.glob('*.csv').first
|
entry = zip_file.glob('*.csv').first
|
||||||
raise 'File too large when extracted' if entry.size > MAX_SIZE
|
raise 'File too large when extracted' if entry.size > MAX_SIZE
|
||||||
puts entry.get_input_stream.read
|
puts entry.get_input_stream.read # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
zip_file = Zip::File.open(zipfile_path)
|
zip_file = Zip::File.open(zipfile_path)
|
||||||
entry = zip_file.glob('*.csv')
|
entry = zip_file.glob('*.csv')
|
||||||
puts entry.get_input_stream.read
|
puts entry.get_input_stream.read # $ Alert
|
||||||
|
|
||||||
zip_file = Zip::File.open(zipfile_path)
|
zip_file = Zip::File.open(zipfile_path)
|
||||||
zip_file.glob('*') do |entry|
|
zip_file.glob('*') do |entry|
|
||||||
entry.get_input_stream.read
|
entry.get_input_stream.read # $ Alert
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
experimental/ldap-improper-auth/ImproperLdapAuth.ql
|
query: experimental/ldap-improper-auth/ImproperLdapAuth.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ class FooController < ActionController::Base
|
|||||||
def some_request_handler
|
def some_request_handler
|
||||||
# A string tainted by user input is used directly as password
|
# A string tainted by user input is used directly as password
|
||||||
# (i.e a remote flow source)
|
# (i.e a remote flow source)
|
||||||
pass = params[:pass]
|
pass = params[:pass] # $ Source
|
||||||
|
|
||||||
# BAD: user input is not sanitized
|
# BAD: user input is not sanitized
|
||||||
ldap = Net::LDAP.new(
|
ldap = Net::LDAP.new(
|
||||||
@@ -12,7 +12,7 @@ class FooController < ActionController::Base
|
|||||||
auth: {
|
auth: {
|
||||||
method: :simple,
|
method: :simple,
|
||||||
username: 'uid=admin,dc=example,dc=com',
|
username: 'uid=admin,dc=example,dc=com',
|
||||||
password: pass
|
password: pass # $ Alert
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
ldap.bind
|
ldap.bind
|
||||||
@@ -21,14 +21,14 @@ class FooController < ActionController::Base
|
|||||||
def some_request_handler
|
def some_request_handler
|
||||||
# A string tainted by user input is used directly as password
|
# A string tainted by user input is used directly as password
|
||||||
# (i.e a remote flow source)
|
# (i.e a remote flow source)
|
||||||
pass = params[:pass]
|
pass = params[:pass] # $ Source
|
||||||
|
|
||||||
# BAD: user input is not sanitized
|
# BAD: user input is not sanitized
|
||||||
ldap = Net::LDAP.new
|
ldap = Net::LDAP.new
|
||||||
ldap.host = your_server_ip_address
|
ldap.host = your_server_ip_address
|
||||||
ldap.encryption(:method => :simple_tls)
|
ldap.encryption(:method => :simple_tls)
|
||||||
ldap.port = 639
|
ldap.port = 639
|
||||||
ldap.auth "admin", pass
|
ldap.auth "admin", pass # $ Alert
|
||||||
ldap.bind
|
ldap.bind
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -56,4 +56,4 @@ class BarController < ApplicationController
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
experimental/insecure-randomness/InsecureRandomness.ql
|
query: experimental/insecure-randomness/InsecureRandomness.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ require 'securerandom'
|
|||||||
def generate_password_1(length)
|
def generate_password_1(length)
|
||||||
chars = ('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a + ['!', '@', '#', '$', '%']
|
chars = ('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a + ['!', '@', '#', '$', '%']
|
||||||
# BAD: rand is not cryptographically secure
|
# BAD: rand is not cryptographically secure
|
||||||
password = (1..length).collect { chars[rand(chars.size)] }.join
|
password = (1..length).collect { chars[rand(chars.size)] }.join # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
def generate_password_2(length)
|
def generate_password_2(length)
|
||||||
@@ -16,4 +16,4 @@ def generate_password_2(length)
|
|||||||
end
|
end
|
||||||
|
|
||||||
password = generate_password_1(10)
|
password = generate_password_1(10)
|
||||||
password = generate_password_2(10)
|
password = generate_password_2(10)
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ class FooController < ActionController::Base
|
|||||||
def some_request_handler
|
def some_request_handler
|
||||||
# A string tainted by user input is used directly as DN
|
# A string tainted by user input is used directly as DN
|
||||||
# (i.e a remote flow source)
|
# (i.e a remote flow source)
|
||||||
dc = params[:dc]
|
dc = params[:dc] # $ Source
|
||||||
|
|
||||||
# A string tainted by user input is used directly as search filter or attribute
|
# A string tainted by user input is used directly as search filter or attribute
|
||||||
# (i.e a remote flow source)
|
# (i.e a remote flow source)
|
||||||
name = params[:user_name]
|
name = params[:user_name] # $ Source
|
||||||
|
|
||||||
# LDAP Connection
|
# LDAP Connection
|
||||||
ldap = Net::LDAP.new(
|
ldap = Net::LDAP.new(
|
||||||
@@ -22,20 +22,20 @@ class FooController < ActionController::Base
|
|||||||
|
|
||||||
# BAD: user input is used as DN
|
# BAD: user input is used as DN
|
||||||
# where dc is unsanitized
|
# where dc is unsanitized
|
||||||
ldap.search(base: "ou=people,dc=#{dc},dc=com", filter: "cn=George", attributes: [""])
|
ldap.search(base: "ou=people,dc=#{dc},dc=com", filter: "cn=George", attributes: [""]) # $ Alert
|
||||||
|
|
||||||
# BAD: user input is used as search filter
|
# BAD: user input is used as search filter
|
||||||
# where name is unsanitized
|
# where name is unsanitized
|
||||||
ldap.search(base: "ou=people,dc=example,dc=com", filter: "cn=#{name}", attributes: [""])
|
ldap.search(base: "ou=people,dc=example,dc=com", filter: "cn=#{name}", attributes: [""]) # $ Alert
|
||||||
|
|
||||||
# BAD: user input is used as attribute
|
# BAD: user input is used as attribute
|
||||||
# where name is unsanitized
|
# where name is unsanitized
|
||||||
ldap.search(base: "ou=people,dc=example,dc=com", filter: "cn=George", attributes: [name])
|
ldap.search(base: "ou=people,dc=example,dc=com", filter: "cn=George", attributes: [name]) # $ Alert
|
||||||
|
|
||||||
# BAD: user input is used as search filter
|
# BAD: user input is used as search filter
|
||||||
# where name is unsanitized
|
# where name is unsanitized
|
||||||
filter = Net::LDAP::Filter.eq('cn', name)
|
filter = Net::LDAP::Filter.eq('cn', name)
|
||||||
ldap.search(base: "ou=people,dc=example,dc=com", filter: filter, attributes: [""])
|
ldap.search(base: "ou=people,dc=example,dc=com", filter: filter, attributes: [""]) # $ Alert
|
||||||
|
|
||||||
# GOOD: user input is not used in the LDAP query
|
# GOOD: user input is not used in the LDAP query
|
||||||
result = ldap.search(base: "ou=people,dc=example,dc=com", filter: "cn=George", attributes: [""])
|
result = ldap.search(base: "ou=people,dc=example,dc=com", filter: "cn=George", attributes: [""])
|
||||||
@@ -63,4 +63,4 @@ class BarController < ApplicationController
|
|||||||
end
|
end
|
||||||
result = ldap.search(base: "ou=people,dc=example,dc=com", filter: "cn=#{name}", attributes: [""])
|
result = ldap.search(base: "ou=people,dc=example,dc=com", filter: "cn=#{name}", attributes: [""])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
experimental/ldap-injection/LdapInjection.ql
|
query: experimental/ldap-injection/LdapInjection.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ class FooController < ActionController::Base
|
|||||||
def some_request_handler
|
def some_request_handler
|
||||||
# A string tainted by user input is inserted into a template
|
# A string tainted by user input is inserted into a template
|
||||||
# (i.e a remote flow source)
|
# (i.e a remote flow source)
|
||||||
name = params[:name]
|
name = params[:name] # $ Source
|
||||||
|
|
||||||
# Template with the source
|
# Template with the source
|
||||||
bad_text = "
|
bad_text = "
|
||||||
@@ -12,11 +12,11 @@ class FooController < ActionController::Base
|
|||||||
|
|
||||||
# BAD: user input is evaluated
|
# BAD: user input is evaluated
|
||||||
# where name is unsanitized
|
# where name is unsanitized
|
||||||
template = ERB.new(bad_text).result(binding)
|
template = ERB.new(bad_text).result(binding) # $ Alert
|
||||||
|
|
||||||
# BAD: user input is evaluated
|
# BAD: user input is evaluated
|
||||||
# where name is unsanitized
|
# where name is unsanitized
|
||||||
render inline: bad_text
|
render inline: bad_text # $ Alert
|
||||||
|
|
||||||
# Template with the source
|
# Template with the source
|
||||||
good_text = "
|
good_text = "
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ class FooController < ActionController::Base
|
|||||||
def some_request_handler
|
def some_request_handler
|
||||||
# A string tainted by user input is inserted into a template
|
# A string tainted by user input is inserted into a template
|
||||||
# (i.e a remote flow source)
|
# (i.e a remote flow source)
|
||||||
name = params[:name]
|
name = params[:name] # $ Source
|
||||||
|
|
||||||
# Template with the source (no sanitizer)
|
# Template with the source (no sanitizer)
|
||||||
bad_text = "
|
bad_text = "
|
||||||
@@ -11,7 +11,7 @@ class FooController < ActionController::Base
|
|||||||
" % name
|
" % name
|
||||||
# BAD: renders user input
|
# BAD: renders user input
|
||||||
# where text is unsanitized
|
# where text is unsanitized
|
||||||
Slim::Template.new{ bad_text }.render
|
Slim::Template.new{ bad_text }.render # $ Alert
|
||||||
|
|
||||||
# Template with the source (no sanitizer)
|
# Template with the source (no sanitizer)
|
||||||
bad2_text = "
|
bad2_text = "
|
||||||
@@ -20,7 +20,7 @@ class FooController < ActionController::Base
|
|||||||
"
|
"
|
||||||
# BAD: renders user input
|
# BAD: renders user input
|
||||||
# where text is unsanitized
|
# where text is unsanitized
|
||||||
Slim::Template.new{ bad2_text }.render
|
Slim::Template.new{ bad2_text }.render # $ Alert
|
||||||
|
|
||||||
# Template with the source (no render)
|
# Template with the source (no render)
|
||||||
good_text = "
|
good_text = "
|
||||||
@@ -64,4 +64,4 @@ class BarController < ApplicationController
|
|||||||
" % name2
|
" % name2
|
||||||
template_bar1 = Slim::Template.new{ text_bar2 }.render
|
template_bar1 = Slim::Template.new{ text_bar2 }.render
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
experimental/template-injection/TemplateInjection.ql
|
query: experimental/template-injection/TemplateInjection.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ require 'libxml'
|
|||||||
|
|
||||||
class FooController < ActionController::Base
|
class FooController < ActionController::Base
|
||||||
def libxml_handler(event:, context:)
|
def libxml_handler(event:, context:)
|
||||||
name = params[:user_name]
|
name = params[:user_name] # $ Source
|
||||||
|
|
||||||
xml = <<-XML
|
xml = <<-XML
|
||||||
<root>
|
<root>
|
||||||
@@ -18,13 +18,13 @@ class FooController < ActionController::Base
|
|||||||
results1 = doc.find_first('//foo')
|
results1 = doc.find_first('//foo')
|
||||||
|
|
||||||
# BAD: XPath query is constructed from user input
|
# BAD: XPath query is constructed from user input
|
||||||
results2 = doc.find_first("//#{name}")
|
results2 = doc.find_first("//#{name}") # $ Alert
|
||||||
|
|
||||||
# GOOD: XPath query is not constructed from user input
|
# GOOD: XPath query is not constructed from user input
|
||||||
results3 = doc.find('//foo')
|
results3 = doc.find('//foo')
|
||||||
|
|
||||||
# BAD: XPath query is constructed from user input
|
# BAD: XPath query is constructed from user input
|
||||||
results4 = doc.find("//#{name}")
|
results4 = doc.find("//#{name}") # $ Alert
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ require 'nokogiri'
|
|||||||
|
|
||||||
class FooController < ActionController::Base
|
class FooController < ActionController::Base
|
||||||
def nokogiri_handler(event:, context:)
|
def nokogiri_handler(event:, context:)
|
||||||
name = params[:user_name]
|
name = params[:user_name] # $ Source
|
||||||
|
|
||||||
xml = <<-XML
|
xml = <<-XML
|
||||||
<root>
|
<root>
|
||||||
@@ -18,19 +18,19 @@ class FooController < ActionController::Base
|
|||||||
results1 = doc.at('//foo')
|
results1 = doc.at('//foo')
|
||||||
|
|
||||||
# BAD: XPath query is constructed from user input
|
# BAD: XPath query is constructed from user input
|
||||||
results2 = doc.at("//#{name}")
|
results2 = doc.at("//#{name}") # $ Alert
|
||||||
|
|
||||||
# GOOD: XPath query is not constructed from user input
|
# GOOD: XPath query is not constructed from user input
|
||||||
results3 = doc.xpath('//foo')
|
results3 = doc.xpath('//foo')
|
||||||
|
|
||||||
# BAD: XPath query is constructed from user input
|
# BAD: XPath query is constructed from user input
|
||||||
results4 = doc.xpath("//#{name}")
|
results4 = doc.xpath("//#{name}") # $ Alert
|
||||||
|
|
||||||
# GOOD: XPath query is not constructed from user input
|
# GOOD: XPath query is not constructed from user input
|
||||||
results5 = doc.at_xpath('//foo')
|
results5 = doc.at_xpath('//foo')
|
||||||
|
|
||||||
# BAD: XPath query is constructed from user input
|
# BAD: XPath query is constructed from user input
|
||||||
results6 = doc.at_xpath("//#{name}")
|
results6 = doc.at_xpath("//#{name}") # $ Alert
|
||||||
|
|
||||||
# GOOD: XPath query is not constructed from user input
|
# GOOD: XPath query is not constructed from user input
|
||||||
doc.xpath('//foo').each do |element|
|
doc.xpath('//foo').each do |element|
|
||||||
@@ -38,7 +38,7 @@ class FooController < ActionController::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
# BAD: XPath query constructed from user input
|
# BAD: XPath query constructed from user input
|
||||||
doc.xpath("//#{name}").each do |element|
|
doc.xpath("//#{name}").each do |element| # $ Alert
|
||||||
puts element.text
|
puts element.text
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ class FooController < ActionController::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
# BAD: XPath query constructed from user input
|
# BAD: XPath query constructed from user input
|
||||||
doc.search("//#{name}").each do |element|
|
doc.search("//#{name}").each do |element| # $ Alert
|
||||||
puts element.text
|
puts element.text
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -85,4 +85,4 @@ class BarController < ActionController::Base
|
|||||||
results9 = doc.at_xpath("//#{safe_name}")
|
results9 = doc.at_xpath("//#{safe_name}")
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ require 'rexml'
|
|||||||
|
|
||||||
class FooController < ActionController::Base
|
class FooController < ActionController::Base
|
||||||
def rexml_handler(event:, context:)
|
def rexml_handler(event:, context:)
|
||||||
name = params[:user_name]
|
name = params[:user_name] # $ Source
|
||||||
|
|
||||||
xml = <<-XML
|
xml = <<-XML
|
||||||
<root>
|
<root>
|
||||||
@@ -18,13 +18,13 @@ class FooController < ActionController::Base
|
|||||||
results1 = REXML::XPath.first(doc, "//foo")
|
results1 = REXML::XPath.first(doc, "//foo")
|
||||||
|
|
||||||
# BAD: XPath query is constructed from user input
|
# BAD: XPath query is constructed from user input
|
||||||
results2 = REXML::XPath.first(doc, "//#{name}")
|
results2 = REXML::XPath.first(doc, "//#{name}") # $ Alert
|
||||||
|
|
||||||
# GOOD: XPath query is not constructed from user input
|
# GOOD: XPath query is not constructed from user input
|
||||||
results3 = REXML::XPath.match(doc, "//foo", nil)
|
results3 = REXML::XPath.match(doc, "//foo", nil)
|
||||||
|
|
||||||
# BAD: XPath query is constructed from user input
|
# BAD: XPath query is constructed from user input
|
||||||
results4 = REXML::XPath.match(doc, "//#{name}", nil)
|
results4 = REXML::XPath.match(doc, "//#{name}", nil) # $ Alert
|
||||||
|
|
||||||
# GOOD: XPath query is not constructed from user input
|
# GOOD: XPath query is not constructed from user input
|
||||||
REXML::XPath.each(doc, "//foo") do |element|
|
REXML::XPath.each(doc, "//foo") do |element|
|
||||||
@@ -32,7 +32,7 @@ class FooController < ActionController::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
# BAD: XPath query constructed from user input
|
# BAD: XPath query constructed from user input
|
||||||
REXML::XPath.each(doc, "//#{name}") do |element|
|
REXML::XPath.each(doc, "//#{name}") do |element| # $ Alert
|
||||||
puts element.text
|
puts element.text
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -66,4 +66,4 @@ class BarController < ActionController::Base
|
|||||||
results6 = REXML::XPath.match(doc, "//#{safe_name}", nil)
|
results6 = REXML::XPath.match(doc, "//#{safe_name}", nil)
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
experimental/xpath-injection/XpathInjection.ql
|
query: experimental/xpath-injection/XpathInjection.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
experimental/cwe-022-zipslip/ZipSlip.ql
|
query: experimental/cwe-022-zipslip/ZipSlip.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ class TestController < ActionController::Base
|
|||||||
def tarReaderUnsafe
|
def tarReaderUnsafe
|
||||||
path = params[:path]
|
path = params[:path]
|
||||||
file_stream = IO.new(IO.sysopen(path))
|
file_stream = IO.new(IO.sysopen(path))
|
||||||
tarfile = Gem::Package::TarReader.new(file_stream)
|
tarfile = Gem::Package::TarReader.new(file_stream) # $ Source
|
||||||
tarfile.each do |entry|
|
tarfile.each do |entry|
|
||||||
::File.open(entry.full_name, "wb") do |os|
|
::File.open(entry.full_name, "wb") do |os| # $ Alert
|
||||||
entry.read
|
entry.read
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -17,9 +17,9 @@ class TestController < ActionController::Base
|
|||||||
def tarReaderBlockUnsafe
|
def tarReaderBlockUnsafe
|
||||||
path = params[:path]
|
path = params[:path]
|
||||||
file_stream = IO.new(IO.sysopen(path))
|
file_stream = IO.new(IO.sysopen(path))
|
||||||
Gem::Package::TarReader.new(file_stream) do |tarfile|
|
Gem::Package::TarReader.new(file_stream) do |tarfile| # $ Source
|
||||||
tarfile.each_entry do |entry|
|
tarfile.each_entry do |entry|
|
||||||
::File.open(entry.full_name, "wb") do |os|
|
::File.open(entry.full_name, "wb") do |os| # $ Alert
|
||||||
entry.read
|
entry.read
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -43,8 +43,8 @@ class TestController < ActionController::Base
|
|||||||
# BAD
|
# BAD
|
||||||
def zipFileUnsafe
|
def zipFileUnsafe
|
||||||
path = params[:path]
|
path = params[:path]
|
||||||
Zip::File.open(path).each do |entry|
|
Zip::File.open(path).each do |entry| # $ Source
|
||||||
File.open(entry.name, "wb") do |os|
|
File.open(entry.name, "wb") do |os| # $ Alert
|
||||||
entry.read
|
entry.read
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -53,9 +53,9 @@ class TestController < ActionController::Base
|
|||||||
# BAD
|
# BAD
|
||||||
def zipFileBlockUnsafe
|
def zipFileBlockUnsafe
|
||||||
path = params[:path]
|
path = params[:path]
|
||||||
Zip::File.open(path) do |zip_file|
|
Zip::File.open(path) do |zip_file| # $ Source
|
||||||
zip_file.each do |entry|
|
zip_file.each do |entry|
|
||||||
File.open(entry.name, "wb") do |os|
|
File.open(entry.name, "wb") do |os| # $ Alert
|
||||||
entry.read
|
entry.read
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -87,7 +87,7 @@ class TestController < ActionController::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def get_compressed_file_stream(compressed_file_path)
|
def get_compressed_file_stream(compressed_file_path)
|
||||||
gzip = Zlib::GzipReader.open(compressed_file_path)
|
gzip = Zlib::GzipReader.open(compressed_file_path) # $ Source
|
||||||
yield(gzip)
|
yield(gzip)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -97,7 +97,7 @@ class TestController < ActionController::Base
|
|||||||
get_compressed_file_stream(path) do |compressed_file|
|
get_compressed_file_stream(path) do |compressed_file|
|
||||||
compressed_file.each do |entry|
|
compressed_file.each do |entry|
|
||||||
entry_path = entry.full_name
|
entry_path = entry.full_name
|
||||||
::File.open(entry_path, 'wb') do |os|
|
::File.open(entry_path, 'wb') do |os| # $ Alert
|
||||||
entry.read
|
entry.read
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -120,10 +120,10 @@ class TestController < ActionController::Base
|
|||||||
def gzipReaderUnsafeNewInstance
|
def gzipReaderUnsafeNewInstance
|
||||||
path = params[:path]
|
path = params[:path]
|
||||||
File.open(path, 'rb') do |f|
|
File.open(path, 'rb') do |f|
|
||||||
gz = Zlib::GzipReader.new(f)
|
gz = Zlib::GzipReader.new(f) # $ Source
|
||||||
gz.each do |entry|
|
gz.each do |entry|
|
||||||
entry_path = entry.full_name
|
entry_path = entry.full_name
|
||||||
::File.open(entry_path, 'wb') do |os|
|
::File.open(entry_path, 'wb') do |os| # $ Alert
|
||||||
entry.read
|
entry.read
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
experimental/cwe-176/UnicodeBypassValidation.ql
|
query: experimental/cwe-176/UnicodeBypassValidation.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -4,35 +4,35 @@ require 'cgi'
|
|||||||
|
|
||||||
class UnicodeNormalizationOKController < ActionController::Base
|
class UnicodeNormalizationOKController < ActionController::Base
|
||||||
def unicodeNormalize
|
def unicodeNormalize
|
||||||
unicode_input = params[:unicode_input]
|
unicode_input = params[:unicode_input] # $ Source
|
||||||
normalized_nfkc = unicode_input.unicode_normalize(:nfkc) # $ MISSING:result=OK
|
normalized_nfkc = unicode_input.unicode_normalize(:nfkc) # $ Alert // $ MISSING:result=OK
|
||||||
normalized_nfc = unicode_input.unicode_normalize(:nfc) # $ MISSING:result=OK
|
normalized_nfc = unicode_input.unicode_normalize(:nfc) # $ Alert // $ MISSING:result=OK
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class UnicodeNormalizationStrManipulationController < ActionController::Base
|
class UnicodeNormalizationStrManipulationController < ActionController::Base
|
||||||
def unicodeNormalize
|
def unicodeNormalize
|
||||||
unicode_input = params[:unicode_input]
|
unicode_input = params[:unicode_input] # $ Source
|
||||||
unicode_input_manip = unicode_input.sub(/[aeiou]/, "*")
|
unicode_input_manip = unicode_input.sub(/[aeiou]/, "*") # $ Source
|
||||||
normalized_nfkc = unicode_input_manip.unicode_normalize(:nfkc) # $ result=BAD
|
normalized_nfkc = unicode_input_manip.unicode_normalize(:nfkc) # $ Alert // $ result=BAD
|
||||||
normalized_nfc = unicode_input_manip.unicode_normalize(:nfc) # $ result=BAD
|
normalized_nfc = unicode_input_manip.unicode_normalize(:nfc) # $ Alert // $ result=BAD
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class UnicodeNormalizationHtMLEscapeController < ActionController::Base
|
class UnicodeNormalizationHtMLEscapeController < ActionController::Base
|
||||||
def unicodeNormalize
|
def unicodeNormalize
|
||||||
unicode_input = params[:unicode_input]
|
unicode_input = params[:unicode_input] # $ Source
|
||||||
unicode_html_safe = html_escape(unicode_input)
|
unicode_html_safe = html_escape(unicode_input) # $ Source
|
||||||
normalized_nfkc = unicode_html_safe.unicode_normalize(:nfkc) # $ result=BAD
|
normalized_nfkc = unicode_html_safe.unicode_normalize(:nfkc) # $ Alert // $ result=BAD
|
||||||
normalized_nfc = unicode_html_safe.unicode_normalize(:nfc) # $ result=BAD
|
normalized_nfc = unicode_html_safe.unicode_normalize(:nfc) # $ Alert // $ result=BAD
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class UnicodeNormalizationCGIHtMLEscapeController < ActionController::Base
|
class UnicodeNormalizationCGIHtMLEscapeController < ActionController::Base
|
||||||
def unicodeNormalize
|
def unicodeNormalize
|
||||||
unicode_input = params[:unicode_input]
|
unicode_input = params[:unicode_input] # $ Source
|
||||||
unicode_html_safe = CGI.escapeHTML(unicode_input).html_safe
|
unicode_html_safe = CGI.escapeHTML(unicode_input).html_safe # $ Source
|
||||||
normalized_nfkc = unicode_html_safe.unicode_normalize(:nfkd) # $ result=BAD
|
normalized_nfkc = unicode_html_safe.unicode_normalize(:nfkd) # $ Alert // $ result=BAD
|
||||||
normalized_nfc = unicode_html_safe.unicode_normalize(:nfd) # $ result=BAD
|
normalized_nfc = unicode_html_safe.unicode_normalize(:nfd) # $ Alert // $ result=BAD
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
experimental/cwe-347/EmptyJWTSecret.ql
|
query: experimental/cwe-347/EmptyJWTSecret.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ payload = { foo: 'bar' }
|
|||||||
token1 = JWT.encode({ foo: 'bar' }, "secret", 'none')
|
token1 = JWT.encode({ foo: 'bar' }, "secret", 'none')
|
||||||
|
|
||||||
# BAD: the secret used is empty
|
# BAD: the secret used is empty
|
||||||
token2 = JWT.encode({ foo: 'bar' }, nil, 'HS256')
|
token2 = JWT.encode({ foo: 'bar' }, nil, 'HS256') # $ Alert[rb/jwt-empty-secret-or-algorithm]
|
||||||
|
|
||||||
# BAD: the secret used is empty
|
# BAD: the secret used is empty
|
||||||
token3 = JWT.encode({ foo: 'bar' }, "", 'HS256')
|
token3 = JWT.encode({ foo: 'bar' }, "", 'HS256') # $ Alert[rb/jwt-empty-secret-or-algorithm]
|
||||||
|
|
||||||
# GOOD: the token is signed
|
# GOOD: the token is signed
|
||||||
token4 = JWT.encode({ foo: 'bar' }, "secret", 'HS256')
|
token4 = JWT.encode({ foo: 'bar' }, "secret", 'HS256')
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
experimental/cwe-347/MissingJWTVerification.ql
|
query: experimental/cwe-347/MissingJWTVerification.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -3,22 +3,22 @@ require 'jwt'
|
|||||||
payload = { foo: 'bar' }
|
payload = { foo: 'bar' }
|
||||||
|
|
||||||
# Unsecure token
|
# Unsecure token
|
||||||
token_without_signature = JWT.encode(payload, nil, 'none')
|
token_without_signature = JWT.encode(payload, nil, 'none') # $ Alert[rb/jwt-empty-secret-or-algorithm]
|
||||||
|
|
||||||
# Secure token
|
# Secure token
|
||||||
token = JWT.encode(payload, "secret", 'HS256')
|
token = JWT.encode(payload, "secret", 'HS256')
|
||||||
|
|
||||||
# BAD: it does not verify
|
# BAD: it does not verify
|
||||||
decoded_token1 = JWT.decode(token_without_signature, nil, false, algorithm: 'HS256')
|
decoded_token1 = JWT.decode(token_without_signature, nil, false, algorithm: 'HS256') # $ Alert[rb/jwt-missing-verification]
|
||||||
|
|
||||||
# BAD: it's using none
|
# BAD: it's using none
|
||||||
decoded_token3 = JWT.decode(token_without_signature, secret, true, algorithm: 'none')
|
decoded_token3 = JWT.decode(token_without_signature, secret, true, algorithm: 'none') # $ Alert[rb/jwt-missing-verification]
|
||||||
|
|
||||||
# BAD: it's using none
|
# BAD: it's using none
|
||||||
decoded_token4 = JWT.decode(token_without_signature, secret, true, { algorithm: 'none' })
|
decoded_token4 = JWT.decode(token_without_signature, secret, true, { algorithm: 'none' }) # $ Alert[rb/jwt-missing-verification]
|
||||||
|
|
||||||
# GOOD: it does verify
|
# GOOD: it does verify
|
||||||
decoded_token5 = JWT.decode(token, secret, 'HS256')
|
decoded_token5 = JWT.decode(token, secret, 'HS256')
|
||||||
|
|
||||||
# GOOD: it does verify
|
# GOOD: it does verify
|
||||||
decoded_token2 = JWT.decode(token,secret)
|
decoded_token2 = JWT.decode(token,secret)
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
experimental/cwe-502/UnsafeYamlDeserialization.ql
|
query: experimental/cwe-502/UnsafeYamlDeserialization.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -7,15 +7,15 @@ require "yaml"
|
|||||||
class UsersController < ActionController::Base
|
class UsersController < ActionController::Base
|
||||||
# BAD before psych version 4.0.0 and
|
# BAD before psych version 4.0.0 and
|
||||||
def route1
|
def route1
|
||||||
yaml_data = params[:key]
|
yaml_data = params[:key] # $ Source
|
||||||
object = Psych.load yaml_data
|
object = Psych.load yaml_data # $ Alert
|
||||||
object = Psych.load_file yaml_data
|
object = Psych.load_file yaml_data
|
||||||
end
|
end
|
||||||
|
|
||||||
# GOOD In psych version 4.0.0 and above
|
# GOOD In psych version 4.0.0 and above
|
||||||
def route2
|
def route2
|
||||||
yaml_data = params[:key]
|
yaml_data = params[:key] # $ Source
|
||||||
object = Psych.load yaml_data
|
object = Psych.load yaml_data # $ Alert
|
||||||
object = Psych.load_file yaml_data
|
object = Psych.load_file yaml_data
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -29,14 +29,14 @@ class UsersController < ActionController::Base
|
|||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
def route4
|
def route4
|
||||||
yaml_data = params[:key]
|
yaml_data = params[:key] # $ Source
|
||||||
object = Psych.unsafe_load(yaml_data)
|
object = Psych.unsafe_load(yaml_data) # $ Alert
|
||||||
object = Psych.unsafe_load_file(yaml_data)
|
object = Psych.unsafe_load_file(yaml_data) # $ Alert
|
||||||
object = Psych.load_stream(yaml_data)
|
object = Psych.load_stream(yaml_data) # $ Alert
|
||||||
parse_output = Psych.parse_stream(yaml_data)
|
parse_output = Psych.parse_stream(yaml_data)
|
||||||
object = parse_output.to_ruby
|
object = parse_output.to_ruby # $ Alert
|
||||||
object = Psych.parse(yaml_data).to_ruby
|
object = Psych.parse(yaml_data).to_ruby # $ Alert
|
||||||
object = Psych.parse_file(yaml_data).to_ruby
|
object = Psych.parse_file(yaml_data).to_ruby # $ Alert
|
||||||
parsed_yaml = Psych.parse_stream(yaml_data)
|
parsed_yaml = Psych.parse_stream(yaml_data)
|
||||||
parsed_yaml.children.each do |child|
|
parsed_yaml.children.each do |child|
|
||||||
object = child.to_ruby
|
object = child.to_ruby
|
||||||
@@ -46,7 +46,7 @@ class UsersController < ActionController::Base
|
|||||||
end
|
end
|
||||||
object = parsed_yaml.children.first.to_ruby
|
object = parsed_yaml.children.first.to_ruby
|
||||||
content = parsed_yaml.children[0].children[0].children
|
content = parsed_yaml.children[0].children[0].children
|
||||||
object = parsed_yaml.to_ruby[0]
|
object = parsed_yaml.to_ruby[0] # $ Alert
|
||||||
object = content.to_ruby[0]
|
object = content.to_ruby[0]
|
||||||
object = Psych.parse(yaml_data).children[0].to_ruby
|
object = Psych.parse(yaml_data).children[0].to_ruby
|
||||||
end
|
end
|
||||||
@@ -58,18 +58,18 @@ class UsersController < ActionController::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def stdin
|
def stdin
|
||||||
object = YAML.load $stdin.read
|
object = YAML.load $stdin.read # $ Alert
|
||||||
|
|
||||||
# STDIN
|
# STDIN
|
||||||
object = YAML.load STDIN.gets
|
object = YAML.load STDIN.gets # $ Alert
|
||||||
|
|
||||||
# ARGF
|
# ARGF
|
||||||
object = YAML.load ARGF.read
|
object = YAML.load ARGF.read # $ Alert
|
||||||
|
|
||||||
# Kernel.gets
|
# Kernel.gets
|
||||||
object = YAML.load gets
|
object = YAML.load gets # $ Alert
|
||||||
|
|
||||||
# Kernel.readlines
|
# Kernel.readlines
|
||||||
object = YAML.load readlines
|
object = YAML.load readlines # $ Alert
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
experimental/manually-check-http-verb/ManuallyCheckHttpVerb.ql
|
query: experimental/manually-check-http-verb/ManuallyCheckHttpVerb.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -1,39 +1,39 @@
|
|||||||
class ExampleController < ActionController::Base
|
class ExampleController < ActionController::Base
|
||||||
# Should find
|
# Should find
|
||||||
def example_action
|
def example_action
|
||||||
if request.get?
|
if request.get? # $ Alert
|
||||||
Resource.find(id: params[:example_id])
|
Resource.find(id: params[:example_id])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Should find
|
# Should find
|
||||||
def other_action
|
def other_action
|
||||||
method = request.env['REQUEST_METHOD']
|
method = request.env['REQUEST_METHOD'] # $ Source
|
||||||
if method == "GET"
|
if method == "GET" # $ Alert
|
||||||
Resource.find(id: params[:id])
|
Resource.find(id: params[:id])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Should find
|
# Should find
|
||||||
def foo
|
def foo
|
||||||
method = request.request_method
|
method = request.request_method # $ Source
|
||||||
if method == "GET"
|
if method == "GET" # $ Alert
|
||||||
Resource.find(id: params[:id])
|
Resource.find(id: params[:id])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Should find
|
# Should find
|
||||||
def bar
|
def bar
|
||||||
method = request.method
|
method = request.method # $ Source
|
||||||
if method == "GET"
|
if method == "GET" # $ Alert
|
||||||
Resource.find(id: params[:id])
|
Resource.find(id: params[:id])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Should find
|
# Should find
|
||||||
def baz
|
def baz
|
||||||
method = request.raw_request_method
|
method = request.raw_request_method # $ Source
|
||||||
if method == "GET"
|
if method == "GET" # $ Alert
|
||||||
Resource.find(id: params[:id])
|
Resource.find(id: params[:id])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -48,15 +48,15 @@ class ExampleController < ActionController::Base
|
|||||||
|
|
||||||
# Should find
|
# Should find
|
||||||
def foobarbaz
|
def foobarbaz
|
||||||
method = request.request_method_symbol
|
method = request.request_method_symbol # $ Source
|
||||||
if method == :GET
|
if method == :GET # $ Alert
|
||||||
Resource.find(id: params[:id])
|
Resource.find(id: params[:id])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Should find
|
# Should find
|
||||||
def resource_action
|
def resource_action
|
||||||
case request.env['REQUEST_METHOD']
|
case request.env['REQUEST_METHOD'] # $ Alert
|
||||||
when "GET"
|
when "GET"
|
||||||
Resource.find(id: params[:id])
|
Resource.find(id: params[:id])
|
||||||
when "POST"
|
when "POST"
|
||||||
@@ -114,4 +114,4 @@ class NotAController
|
|||||||
end
|
end
|
||||||
|
|
||||||
class Resource < ActiveRecord::Base
|
class Resource < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
experimental/weak-params/WeakParams.ql
|
query: experimental/weak-params/WeakParams.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -2,22 +2,22 @@ class TestController < ActionController::Base
|
|||||||
|
|
||||||
# Should catch
|
# Should catch
|
||||||
def create
|
def create
|
||||||
TestObject.create(foo: request.request_parameters[:foo])
|
TestObject.create(foo: request.request_parameters[:foo]) # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
# Should catch
|
# Should catch
|
||||||
def create_query
|
def create_query
|
||||||
TestObject.create(foo: request.query_parameters[:foo])
|
TestObject.create(foo: request.query_parameters[:foo]) # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
# Should catch
|
# Should catch
|
||||||
def update_unsafe
|
def update_unsafe
|
||||||
TestObject.update(foo: request.POST[:foo])
|
TestObject.update(foo: request.POST[:foo]) # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
# Should catch
|
# Should catch
|
||||||
def update_unsafe_get
|
def update_unsafe_get
|
||||||
TestObject.update(foo: request.GET[:foo])
|
TestObject.update(foo: request.GET[:foo]) # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
# Should not catch
|
# Should not catch
|
||||||
@@ -37,4 +37,4 @@ class TestController < ActionController::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
class TestObject < ActiveRecord::Base
|
class TestObject < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
experimental/performance/UseDetect.ql
|
query: experimental/performance/UseDetect.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -2,14 +2,14 @@
|
|||||||
class DetectTest
|
class DetectTest
|
||||||
def test
|
def test
|
||||||
# These are bad
|
# These are bad
|
||||||
[].select { |i| true }.first
|
[].select { |i| true }.first # $ Alert
|
||||||
[].select { |i| true }.last
|
[].select { |i| true }.last # $ Alert
|
||||||
[].select { |i| true }[0]
|
[].select { |i| true }[0] # $ Alert
|
||||||
[].select { |i| true }[-1]
|
[].select { |i| true }[-1] # $ Alert
|
||||||
[].filter { |i| true }.first
|
[].filter { |i| true }.first # $ Alert
|
||||||
[].find_all { |i| true }.last
|
[].find_all { |i| true }.last # $ Alert
|
||||||
selection1 = [].select { |i| true }
|
selection1 = [].select { |i| true }
|
||||||
selection1.first
|
selection1.first # $ Alert
|
||||||
|
|
||||||
# These are good
|
# These are good
|
||||||
[].select("").first # Selecting a string
|
[].select("").first # Selecting a string
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-020/IncompleteHostnameRegExp.ql
|
query: queries/security/cwe-020/IncompleteHostnameRegExp.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
UNSAFE_REGEX1 = /(www|beta).example.com\//
|
UNSAFE_REGEX1 = /(www|beta).example.com\// # $ Alert
|
||||||
UNSAFE_REGEX2 = Regexp.compile("(www|beta).example.com/")
|
UNSAFE_REGEX2 = Regexp.compile("(www|beta).example.com/") # $ Alert
|
||||||
UNSAFE_REGEX3 = Regexp.new("(www|beta).example.com/")
|
UNSAFE_REGEX3 = Regexp.new("(www|beta).example.com/") # $ Alert
|
||||||
SAFE_REGEX = /(www|beta)\.example\.com\//
|
SAFE_REGEX = /(www|beta)\.example\.com\//
|
||||||
|
|
||||||
def unsafe
|
def unsafe
|
||||||
|
|||||||
@@ -1,31 +1,31 @@
|
|||||||
def foo
|
def foo
|
||||||
/^http:\/\/example.com/; # OK
|
/^http:\/\/example.com/; # OK
|
||||||
/^http:\/\/test.example.com/; # NOT OK
|
/^http:\/\/test.example.com/; # $ Alert // NOT OK
|
||||||
/^http:\/\/test\.example.com/; # OK
|
/^http:\/\/test\.example.com/; # OK
|
||||||
/^http:\/\/test.example.net/; # NOT OK
|
/^http:\/\/test.example.net/; # $ Alert // NOT OK
|
||||||
/^http:\/\/test.(example-a|example-b).com/; # NOT OK
|
/^http:\/\/test.(example-a|example-b).com/; # $ Alert // NOT OK
|
||||||
/^http:\/\/(.+).example.com\//; # NOT OK
|
/^http:\/\/(.+).example.com\//; # $ Alert // NOT OK
|
||||||
/^http:\/\/(\.+)\.example.com/; # OK
|
/^http:\/\/(\.+)\.example.com/; # OK
|
||||||
/^http:\/\/(?:.+)\.test\.example.com\//; # NOT OK
|
/^http:\/\/(?:.+)\.test\.example.com\//; # $ Alert // NOT OK
|
||||||
/^http:\/\/test.example.com\/(?:.*)/; # OK
|
/^http:\/\/test.example.com\/(?:.*)/; # $ Alert // OK
|
||||||
Regexp.new("^http://test.example.com"); # NOT OK
|
Regexp.new("^http://test.example.com"); # $ Alert // NOT OK
|
||||||
if (s.match("^http://test.example.com")); end # NOT OK
|
if (s.match("^http://test.example.com")); end # $ Alert // NOT OK
|
||||||
|
|
||||||
|
|
||||||
Regexp.new(id(id(id("^http://test.example.com")))); # NOT OK
|
Regexp.new(id(id(id("^http://test.example.com")))); # $ Alert // NOT OK
|
||||||
|
|
||||||
Regexp.new(`test.example.com$`); # NOT OK
|
Regexp.new(`test.example.com$`); # $ Alert // NOT OK
|
||||||
|
|
||||||
hostname = '^test.example.com'; # NOT OK
|
hostname = '^test.example.com'; # $ Alert // NOT OK
|
||||||
Regexp.new("#{hostname}$");
|
Regexp.new("#{hostname}$"); # $ Alert
|
||||||
|
|
||||||
domain = { hostname: 'test.example.com$' }; # NOT OK
|
domain = { hostname: 'test.example.com$' }; # $ Alert // NOT OK
|
||||||
Regexp.new(domain[:hostname]);
|
Regexp.new(domain[:hostname]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
convert1({ hostname: 'test.example.com$' }); # NOT OK
|
convert1({ hostname: 'test.example.com$' }); # $ Alert // NOT OK
|
||||||
|
|
||||||
domains = [ { hostname: 'test.example.com$' } ]; # NOT OK - but not flagged due to limitations of TypeTracking.
|
domains = [ { hostname: 'test.example.com$' } ]; # NOT OK - but not flagged due to limitations of TypeTracking.
|
||||||
|
|
||||||
@@ -34,18 +34,18 @@ def foo
|
|||||||
domains.map{ |d| convert2(d) };
|
domains.map{ |d| convert2(d) };
|
||||||
|
|
||||||
/^(.+\.(?:example-a|example-b)\.com)\//; # NOT OK
|
/^(.+\.(?:example-a|example-b)\.com)\//; # NOT OK
|
||||||
/^(https?:)?\/\/((service|www).)?example.com(?=$|\/)/; # NOT OK
|
/^(https?:)?\/\/((service|www).)?example.com(?=$|\/)/; # $ Alert // NOT OK
|
||||||
/^(http|https):\/\/www.example.com\/p\/f\//; # NOT OK
|
/^(http|https):\/\/www.example.com\/p\/f\//; # $ Alert // NOT OK
|
||||||
/^(http:\/\/sub.example.com\/)/i; # NOT OK
|
/^(http:\/\/sub.example.com\/)/i; # $ Alert // NOT OK
|
||||||
/^https?:\/\/api.example.com/; # NOT OK
|
/^https?:\/\/api.example.com/; # $ Alert // NOT OK
|
||||||
Regexp.new('^http://localhost:8000|' + "^https?://.+\\.example\\.com/"); # NOT OK
|
Regexp.new('^http://localhost:8000|' + "^https?://.+\\.example\\.com/"); # $ Alert // NOT OK
|
||||||
Regexp.new("^http[s]?:\/\/?sub1\\.sub2\\.example\\.com\/f\/(.+)"); # NOT OK
|
Regexp.new("^http[s]?:\/\/?sub1\\.sub2\\.example\\.com\/f\/(.+)"); # NOT OK
|
||||||
/^https:\/\/[a-z]*.example.com$/; # NOT OK
|
/^https:\/\/[a-z]*.example.com$/; # $ Alert // NOT OK
|
||||||
Regexp.compile('^protos?://(localhost|.+.example.net|.+.example-a.com|.+.example-b.com|.+.example.internal)'); # NOT OK
|
Regexp.compile('^protos?://(localhost|.+.example.net|.+.example-a.com|.+.example-b.com|.+.example.internal)'); # $ Alert // NOT OK
|
||||||
|
|
||||||
/^(example.dev|example.com)/; # OK
|
/^(example.dev|example.com)/; # OK
|
||||||
|
|
||||||
Regexp.new('^http://localhost:8000|' + "^https?://.+.example\\.com/"); # NOT OK
|
Regexp.new('^http://localhost:8000|' + "^https?://.+.example\\.com/"); # $ Alert // NOT OK
|
||||||
|
|
||||||
primary = 'example.com$';
|
primary = 'example.com$';
|
||||||
Regexp.new('test.' + primary); # NOT OK, but not detected
|
Regexp.new('test.' + primary); # NOT OK, but not detected
|
||||||
@@ -56,7 +56,7 @@ def foo
|
|||||||
|
|
||||||
/^http:\/\/(..|...)\.example\.com\/index\.html/; # OK, wildcards are intentional
|
/^http:\/\/(..|...)\.example\.com\/index\.html/; # OK, wildcards are intentional
|
||||||
/^http:\/\/.\.example\.com\/index\.html/; # OK, the wildcard is intentional
|
/^http:\/\/.\.example\.com\/index\.html/; # OK, the wildcard is intentional
|
||||||
/^(foo.example\.com|whatever)$/; # kinda OK - one disjunction doesn't even look like a hostname
|
/^(foo.example\.com|whatever)$/; # $ Alert // kinda OK - one disjunction doesn't even look like a hostname
|
||||||
end
|
end
|
||||||
def id(e); return e; end
|
def id(e); return e; end
|
||||||
def convert1(domain)
|
def convert1(domain)
|
||||||
@@ -78,4 +78,4 @@ class B
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
B.match?("^http://test.example.com") # NOT OK
|
B.match?("^http://test.example.com") # $ Alert // NOT OK
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-020/IncompleteUrlSubstringSanitization.ql
|
query: queries/security/cwe-020/IncompleteUrlSubstringSanitization.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
def test (x)
|
def test (x)
|
||||||
x.index("internal") != nil; # NOT OK, but not flagged
|
x.index("internal") != nil; # NOT OK, but not flagged
|
||||||
x.index("localhost") != nil; # NOT OK, but not flagged
|
x.index("localhost") != nil; # NOT OK, but not flagged
|
||||||
x.index("secure.com") != nil; # NOT OK
|
x.index("secure.com") != nil; # $ Alert // NOT OK
|
||||||
x.index("secure.net") != nil; # NOT OK
|
x.index("secure.net") != nil; # $ Alert // NOT OK
|
||||||
x.index(".secure.com") != nil; # NOT OK
|
x.index(".secure.com") != nil; # $ Alert // NOT OK
|
||||||
x.index("sub.secure.") != nil; # NOT OK, but not flagged
|
x.index("sub.secure.") != nil; # NOT OK, but not flagged
|
||||||
x.index(".sub.secure.") != nil; # NOT OK, but not flagged
|
x.index(".sub.secure.") != nil; # NOT OK, but not flagged
|
||||||
|
|
||||||
x.index("secure.com") === nil; # NOT OK
|
x.index("secure.com") === nil; # $ Alert // NOT OK
|
||||||
x.index("secure.com") === 0; # NOT OK
|
x.index("secure.com") === 0; # $ Alert // NOT OK
|
||||||
x.index("secure.com") >= 0; # NOT OK
|
x.index("secure.com") >= 0; # $ Alert // NOT OK
|
||||||
|
|
||||||
x.start_with?("https://secure.com"); # NOT OK
|
x.start_with?("https://secure.com"); # $ Alert // NOT OK
|
||||||
x.end_with?("secure.com"); # NOT OK
|
x.end_with?("secure.com"); # $ Alert // NOT OK
|
||||||
x.end_with?(".secure.com"); # OK
|
x.end_with?(".secure.com"); # OK
|
||||||
x.start_with?("secure.com/"); # OK
|
x.start_with?("secure.com/"); # OK
|
||||||
x.index("secure.com/") === 0; # OK
|
x.index("secure.com/") === 0; # OK
|
||||||
|
|
||||||
x.include?("secure.com"); # NOT OK
|
x.include?("secure.com"); # $ Alert // NOT OK
|
||||||
|
|
||||||
x.index("#") != nil; # OK
|
x.index("#") != nil; # OK
|
||||||
x.index(":") != nil; # OK
|
x.index(":") != nil; # OK
|
||||||
@@ -29,9 +29,9 @@ def test (x)
|
|||||||
x.index("some/path") != nil; # OK
|
x.index("some/path") != nil; # OK
|
||||||
x.index("/index.html") != nil; # OK
|
x.index("/index.html") != nil; # OK
|
||||||
x.index(":template:") != nil; # OK
|
x.index(":template:") != nil; # OK
|
||||||
x.index("https://secure.com") != nil; # NOT OK
|
x.index("https://secure.com") != nil; # $ Alert // NOT OK
|
||||||
x.index("https://secure.com:443") != nil; # NOT OK
|
x.index("https://secure.com:443") != nil; # $ Alert // NOT OK
|
||||||
x.index("https://secure.com/") != nil; # NOT OK
|
x.index("https://secure.com/") != nil; # $ Alert // NOT OK
|
||||||
|
|
||||||
x.index(".cn") != nil; # NOT OK, but not flagged
|
x.index(".cn") != nil; # NOT OK, but not flagged
|
||||||
x.index(".jpg") != nil; # OK
|
x.index(".jpg") != nil; # OK
|
||||||
@@ -49,28 +49,28 @@ def test (x)
|
|||||||
x.index("tar.gz") + offset; # OK
|
x.index("tar.gz") + offset; # OK
|
||||||
x.index("tar.gz") - offset; # OK
|
x.index("tar.gz") - offset; # OK
|
||||||
|
|
||||||
x.index("https://example.internal") != nil; # NOT OK
|
x.index("https://example.internal") != nil; # $ Alert // NOT OK
|
||||||
x.index("https://") != nil; # OK
|
x.index("https://") != nil; # OK
|
||||||
|
|
||||||
x.start_with?("https://example.internal"); # NOT OK
|
x.start_with?("https://example.internal"); # $ Alert // NOT OK
|
||||||
x.index('https://example.internal.org') != 0; # NOT OK
|
x.index('https://example.internal.org') != 0; # $ Alert // NOT OK
|
||||||
x.index('https://example.internal.org') === 0; # NOT OK
|
x.index('https://example.internal.org') === 0; # $ Alert // NOT OK
|
||||||
x.end_with?("internal.com"); # NOT OK
|
x.end_with?("internal.com"); # $ Alert // NOT OK
|
||||||
x.start_with?("https://example.internal:80"); # OK
|
x.start_with?("https://example.internal:80"); # OK
|
||||||
|
|
||||||
x.index("secure.com") != nil; # NOT OK
|
x.index("secure.com") != nil; # $ Alert // NOT OK
|
||||||
x.index("secure.com") === nil; # OK
|
x.index("secure.com") === nil; # $ Alert // OK
|
||||||
!(x.index("secure.com") != nil); # OK
|
!(x.index("secure.com") != nil); # $ Alert // OK
|
||||||
!x.include?("secure.com"); # OK
|
!x.include?("secure.com"); # $ Alert // OK
|
||||||
|
|
||||||
if !x.include?("secure.com") # NOT OK
|
if !x.include?("secure.com") # $ Alert // NOT OK
|
||||||
|
|
||||||
else
|
else
|
||||||
doSomeThingWithTrustedURL(x);
|
doSomeThingWithTrustedURL(x);
|
||||||
end
|
end
|
||||||
|
|
||||||
x.start_with?("https://secure.com/foo/bar"); # OK - a forward slash after the domain makes prefix checks safe.
|
x.start_with?("https://secure.com/foo/bar"); # OK - a forward slash after the domain makes prefix checks safe.
|
||||||
x.index("https://secure.com/foo/bar") >= 0 # NOT OK - the url can be anywhere in the string.
|
x.index("https://secure.com/foo/bar") >= 0 # $ Alert // NOT OK - the url can be anywhere in the string.
|
||||||
x.index("https://secure.com") >= 0 # NOT OK
|
x.index("https://secure.com") >= 0 # $ Alert // NOT OK
|
||||||
x.index("https://secure.com/foo/bar-baz") >= 0 # NOT OK - the url can be anywhere in the string.
|
x.index("https://secure.com/foo/bar-baz") >= 0 # $ Alert // NOT OK - the url can be anywhere in the string.
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-020/MissingFullAnchor.ql
|
query: queries/security/cwe-020/MissingFullAnchor.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
class Foobar
|
class Foobar
|
||||||
def foo1(name)
|
def foo1(name) # $ Source
|
||||||
raise Blabity, 'Invalid thing' if name !~ /^[A-Za-z0-9\+\-_]+(\/[A-Za-z0-9\+\-_]+)*$/ # NOT OK
|
raise Blabity, 'Invalid thing' if name !~ /^[A-Za-z0-9\+\-_]+(\/[A-Za-z0-9\+\-_]+)*$/ # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def foo2(name)
|
def foo2(name) # $ Source
|
||||||
raise Blabity, 'Invalid thing' unless name !~ /^[A-Za-z0-9\+\-_]+(\/[A-Za-z0-9\+\-_]+)*$/ # NOT OK
|
raise Blabity, 'Invalid thing' unless name !~ /^[A-Za-z0-9\+\-_]+(\/[A-Za-z0-9\+\-_]+)*$/ # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def foo3(name)
|
def foo3(name)
|
||||||
raise Blabity, 'Invalid thing' unless name !~ /\A[A-Za-z0-9\+\-_]+(\/[A-Za-z0-9\+\-_]+)*\z/ # OK
|
raise Blabity, 'Invalid thing' unless name !~ /\A[A-Za-z0-9\+\-_]+(\/[A-Za-z0-9\+\-_]+)*\z/ # OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def foo4(name)
|
def foo4(name) # $ Source
|
||||||
raise Blabity, 'Invalid thing' unless not name !~ /^[A-Za-z0-9\+\-_]+(\/[A-Za-z0-9\+\-_]+)*$/ # NOT OK
|
raise Blabity, 'Invalid thing' unless not name !~ /^[A-Za-z0-9\+\-_]+(\/[A-Za-z0-9\+\-_]+)*$/ # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-020/MissingRegExpAnchor.ql
|
query: queries/security/cwe-020/MissingRegExpAnchor.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/www\.example\.com/ # BAD
|
/www\.example\.com/ # $ Alert // BAD
|
||||||
/^www\.example\.com$/ # BAD: uses end-of-line anchors rather than end-of-string anchors
|
/^www\.example\.com$/ # BAD: uses end-of-line anchors rather than end-of-string anchors
|
||||||
/\Awww\.example\.com\z/ # GOOD
|
/\Awww\.example\.com\z/ # GOOD
|
||||||
|
|
||||||
/foo\.bar/ # GOOD
|
/foo\.bar/ # GOOD
|
||||||
|
|
||||||
/https?:\/\/good\.com/ # BAD
|
/https?:\/\/good\.com/ # $ Alert // BAD
|
||||||
/^https?:\/\/good\.com/ # BAD: missing end-of-string anchor
|
/^https?:\/\/good\.com/ # $ Alert // BAD: missing end-of-string anchor
|
||||||
/(^https?:\/\/good1\.com)|(^https?:#good2\.com)/ # BAD: missing end-of-string anchor
|
/(^https?:\/\/good1\.com)|(^https?:#good2\.com)/ # BAD: missing end-of-string anchor
|
||||||
|
|
||||||
/bar/ # GOOD
|
/bar/ # GOOD
|
||||||
@@ -16,40 +16,40 @@ foo.gsub!(/www\.example\.com/, "bar") # GOOD
|
|||||||
foo.sub!(/www\.example\.com/, "bar") # GOOD
|
foo.sub!(/www\.example\.com/, "bar") # GOOD
|
||||||
|
|
||||||
/^a|/
|
/^a|/
|
||||||
/^a|b/ # BAD
|
/^a|b/ # $ Alert // BAD
|
||||||
/a|^b/
|
/a|^b/
|
||||||
/^a|^b/
|
/^a|^b/
|
||||||
/^a|b|c/ # BAD
|
/^a|b|c/ # $ Alert // BAD
|
||||||
/a|^b|c/
|
/a|^b|c/
|
||||||
/a|b|^c/
|
/a|b|^c/
|
||||||
/^a|^b|c/
|
/^a|^b|c/
|
||||||
|
|
||||||
/(^a)|b/
|
/(^a)|b/
|
||||||
/^a|(b)/ # BAD
|
/^a|(b)/ # $ Alert // BAD
|
||||||
/^a|(^b)/
|
/^a|(^b)/
|
||||||
/^(a)|(b)/ # BAD
|
/^(a)|(b)/ # $ Alert // BAD
|
||||||
|
|
||||||
|
|
||||||
/a|b$/ # BAD
|
/a|b$/ # $ Alert // BAD
|
||||||
/a$|b/
|
/a$|b/
|
||||||
/a$|b$/
|
/a$|b$/
|
||||||
/a|b|c$/ # BAD
|
/a|b|c$/ # $ Alert // BAD
|
||||||
/a|b$|c/
|
/a|b$|c/
|
||||||
/a$|b|c/
|
/a$|b|c/
|
||||||
/a|b$|c$/
|
/a|b$|c$/
|
||||||
|
|
||||||
/a|(b$)/
|
/a|(b$)/
|
||||||
/(a)|b$/ # BAD
|
/(a)|b$/ # $ Alert // BAD
|
||||||
/(a$)|b$/
|
/(a$)|b$/
|
||||||
/(a)|(b)$/ # BAD
|
/(a)|(b)$/ # $ Alert // BAD
|
||||||
|
|
||||||
/^good.com|better.com/ # BAD
|
/^good.com|better.com/ # $ Alert // BAD
|
||||||
/^good\.com|better\.com/ # BAD
|
/^good\.com|better\.com/ # $ Alert // BAD
|
||||||
/^good\\.com|better\\.com/ # BAD
|
/^good\\.com|better\\.com/ # $ Alert // BAD
|
||||||
/^good\\\.com|better\\\.com/ # BAD
|
/^good\\\.com|better\\\.com/ # $ Alert // BAD
|
||||||
/^good\\\\.com|better\\\\.com/ # BAD
|
/^good\\\\.com|better\\\\.com/ # $ Alert // BAD
|
||||||
|
|
||||||
/^foo|bar|baz$/ # BAD
|
/^foo|bar|baz$/ # $ Alert // BAD
|
||||||
/^foo|%/ # OK
|
/^foo|%/ # OK
|
||||||
|
|
||||||
REGEXP = /foo/
|
REGEXP = /foo/
|
||||||
@@ -57,5 +57,5 @@ REGEXP.match? "http://example.com" # GOOD: the url is the text not the regexp
|
|||||||
REGEXP.match "http://example.com" # GOOD: the url is the text not the regexp
|
REGEXP.match "http://example.com" # GOOD: the url is the text not the regexp
|
||||||
"http://example.com".match? REGEXP # GOOD: the url is the text not the regexp
|
"http://example.com".match? REGEXP # GOOD: the url is the text not the regexp
|
||||||
"http://example.com".match REGEXP # GOOD: the url is the text not the regexp
|
"http://example.com".match REGEXP # GOOD: the url is the text not the regexp
|
||||||
"some text".match? "http://example.com" # BAD
|
"some text".match? "http://example.com" # $ Alert // BAD
|
||||||
"some text".match "http://example.com" # BAD
|
"some text".match "http://example.com" # $ Alert // BAD
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-020/OverlyLargeRange.ql
|
query: queries/security/cwe-020/OverlyLargeRange.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
overlap1 = /^[0-93-5]$/ # NOT OK
|
overlap1 = /^[0-93-5]$/ # $ Alert // NOT OK
|
||||||
|
|
||||||
overlap2 = /[A-ZA-z]/ # NOT OK
|
overlap2 = /[A-ZA-z]/ # $ Alert // NOT OK
|
||||||
|
|
||||||
isEmpty = /^[z-a]$/ # NOT OK
|
isEmpty = /^[z-a]$/ # $ Alert // NOT OK
|
||||||
|
|
||||||
isAscii = /^[\x00-\x7F]*$/ # OK
|
isAscii = /^[\x00-\x7F]*$/ # OK
|
||||||
|
|
||||||
@@ -12,22 +12,22 @@ codePoints = /[^\x21-\x7E]|[\[\](){}<>\/%]/ # OK
|
|||||||
|
|
||||||
NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/ # OK
|
NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/ # OK
|
||||||
|
|
||||||
smallOverlap = /[0-9a-fA-f]/ # NOT OK
|
smallOverlap = /[0-9a-fA-f]/ # $ Alert // NOT OK
|
||||||
|
|
||||||
weirdRange = /[$-`]/ # NOT OK
|
weirdRange = /[$-`]/ # $ Alert // NOT OK
|
||||||
|
|
||||||
keywordOperator = /[!\~\*\/%+-<>\^|=&]/ # NOT OK
|
keywordOperator = /[!\~\*\/%+-<>\^|=&]/ # $ Alert // NOT OK
|
||||||
|
|
||||||
notYoutube = /youtu\.be\/[a-z1-9.-_]+/ # NOT OK
|
notYoutube = /youtu\.be\/[a-z1-9.-_]+/ # $ Alert // NOT OK
|
||||||
|
|
||||||
numberToLetter = /[7-F]/ # NOT OK
|
numberToLetter = /[7-F]/ # $ Alert // NOT OK
|
||||||
|
|
||||||
overlapsWithClass1 = /[0-9\d]/ # NOT OK
|
overlapsWithClass1 = /[0-9\d]/ # $ Alert // NOT OK
|
||||||
|
|
||||||
overlapsWithClass2 = /[\w,.-?:*+]/ # NOT OK
|
overlapsWithClass2 = /[\w,.-?:*+]/ # $ Alert // NOT OK
|
||||||
|
|
||||||
escapes = /[\000-\037\047\134\177-\377]/n # OK - they are escapes
|
escapes = /[\000-\037\047\134\177-\377]/n # OK - they are escapes
|
||||||
|
|
||||||
nested = /[a-z&&[^a-c]]/ # OK
|
nested = /[a-z&&[^a-c]]/ # OK
|
||||||
|
|
||||||
overlapsWithNothing = /[\w_%-.]/;
|
overlapsWithNothing = /[\w_%-.]/; # $ Alert
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-078/KernelOpen.ql
|
query: queries/security/cwe-078/KernelOpen.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
class UsersController < ActionController::Base
|
class UsersController < ActionController::Base
|
||||||
def create
|
def create
|
||||||
file = params[:file]
|
file = params[:file] # $ Source
|
||||||
open(file) # BAD
|
open(file) # $ Alert // BAD
|
||||||
IO.read(file) # BAD
|
IO.read(file) # $ Alert // BAD
|
||||||
IO.write(file) # BAD
|
IO.write(file) # $ Alert // BAD
|
||||||
IO.binread(file) # BAD
|
IO.binread(file) # $ Alert // BAD
|
||||||
IO.binwrite(file) # BAD
|
IO.binwrite(file) # $ Alert // BAD
|
||||||
IO.foreach(file) # BAD
|
IO.foreach(file) # $ Alert // BAD
|
||||||
IO.readlines(file) # BAD
|
IO.readlines(file) # $ Alert // BAD
|
||||||
URI.open(file) # BAD
|
URI.open(file) # $ Alert // BAD
|
||||||
|
|
||||||
IO.read(File.join(file, "")) # BAD - file as first argument to File.join
|
IO.read(File.join(file, "")) # $ Alert // BAD - file as first argument to File.join
|
||||||
IO.read(File.join("", file)) # GOOD - file path is sanitised by guard
|
IO.read(File.join("", file)) # GOOD - file path is sanitised by guard
|
||||||
|
|
||||||
File.open(file).read # GOOD
|
File.open(file).read # GOOD
|
||||||
@@ -23,6 +23,6 @@ class UsersController < ActionController::Base
|
|||||||
IO.read(file) # GOOD - file path is sanitised by guard
|
IO.read(file) # GOOD - file path is sanitised by guard
|
||||||
end
|
end
|
||||||
|
|
||||||
open(file) # BAD - sanity check to verify that file was not mistakenly marked as sanitized
|
open(file) # $ Alert // BAD - sanity check to verify that file was not mistakenly marked as sanitized
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-078/NonConstantKernelOpen.ql
|
query: queries/security/cwe-078/NonConstantKernelOpen.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -4,18 +4,18 @@ class UsersController < ActionController::Base
|
|||||||
|
|
||||||
def create
|
def create
|
||||||
file = params[:file]
|
file = params[:file]
|
||||||
open(file) # BAD
|
open(file) # $ Alert // BAD
|
||||||
IO.read(file) # BAD
|
IO.read(file) # $ Alert // BAD
|
||||||
IO.write(file) # BAD
|
IO.write(file) # $ Alert // BAD
|
||||||
IO.binread(file) # BAD
|
IO.binread(file) # $ Alert // BAD
|
||||||
IO.binwrite(file) # BAD
|
IO.binwrite(file) # $ Alert // BAD
|
||||||
IO.foreach(file) # BAD
|
IO.foreach(file) # $ Alert // BAD
|
||||||
IO.readlines(file) # BAD
|
IO.readlines(file) # $ Alert // BAD
|
||||||
URI.open(file) # BAD
|
URI.open(file) # $ Alert // BAD
|
||||||
|
|
||||||
File.open(file).read # GOOD
|
File.open(file).read # GOOD
|
||||||
|
|
||||||
Kernel.open(file) # BAD
|
Kernel.open(file) # $ Alert // BAD
|
||||||
|
|
||||||
File.open(file, "r") # GOOD
|
File.open(file, "r") # GOOD
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ class UsersController < ActionController::Base
|
|||||||
|
|
||||||
Kernel.open("this is #{fine}") # GOOD
|
Kernel.open("this is #{fine}") # GOOD
|
||||||
|
|
||||||
Kernel.open("#{this_is} bad") # BAD
|
Kernel.open("#{this_is} bad") # $ Alert // BAD
|
||||||
|
|
||||||
open("| #{this_is_an_explicit_command} foo bar") # GOOD
|
open("| #{this_is_an_explicit_command} foo bar") # GOOD
|
||||||
|
|
||||||
@@ -43,6 +43,6 @@ class UsersController < ActionController::Base
|
|||||||
|
|
||||||
open.where(external: false) # GOOD - an open method is called withoout arguments
|
open.where(external: false) # GOOD - an open method is called withoout arguments
|
||||||
|
|
||||||
open(file) # BAD - sanity check to verify that file was not mistakenly marked as sanitized
|
open(file) # $ Alert // BAD - sanity check to verify that file was not mistakenly marked as sanitized
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-078/UnsafeShellCommandConstruction.ql
|
query: queries/security/cwe-078/UnsafeShellCommandConstruction.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
class Foobar
|
class Foobar
|
||||||
def foo1(target)
|
def foo1(target) # $ Source
|
||||||
IO.popen("cat #{target}", "w") # NOT OK - everything assumed to be imported...
|
IO.popen("cat #{target}", "w") # $ Alert // NOT OK - everything assumed to be imported...
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
class Foobar
|
class Foobar
|
||||||
def foo1(target)
|
def foo1(target) # $ Source
|
||||||
IO.popen("cat #{target}", "w") # NOT OK
|
IO.popen("cat #{target}", "w") # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
require 'sub/other2'
|
require 'sub/other2'
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
class Foobar
|
class Foobar
|
||||||
def foo1(target)
|
def foo1(target) # $ Source
|
||||||
IO.popen("cat #{target}", "w") # NOT OK
|
IO.popen("cat #{target}", "w") # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
class Foobar
|
class Foobar
|
||||||
def foo1(target)
|
def foo1(target) # $ Source
|
||||||
IO.popen("cat #{target}", "w") # NOT OK
|
IO.popen("cat #{target}", "w") # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def foo2(x)
|
def foo2(x) # $ Source
|
||||||
format = sprintf("cat %s", x) # NOT OK
|
format = sprintf("cat %s", x) # $ Alert // NOT OK
|
||||||
IO.popen(format, "w")
|
IO.popen(format, "w")
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -12,30 +12,30 @@ class Foobar
|
|||||||
File.read(path) # OK
|
File.read(path) # OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def my_exec(cmd, command, myCmd, myCommand, innocent_file_path)
|
def my_exec(cmd, command, myCmd, myCommand, innocent_file_path) # $ Source
|
||||||
IO.popen("which #{cmd}", "w") # OK - the parameter is named `cmd`, so it's meant to be a command
|
IO.popen("which #{cmd}", "w") # OK - the parameter is named `cmd`, so it's meant to be a command
|
||||||
IO.popen("which #{command}", "w") # OK - the parameter is named `command`, so it's meant to be a command
|
IO.popen("which #{command}", "w") # OK - the parameter is named `command`, so it's meant to be a command
|
||||||
IO.popen("which #{myCmd}", "w") # OK - the parameter is named `myCmd`, so it's meant to be a command
|
IO.popen("which #{myCmd}", "w") # OK - the parameter is named `myCmd`, so it's meant to be a command
|
||||||
IO.popen("which #{myCommand}", "w") # OK - the parameter is named `myCommand`, so it's meant to be a command
|
IO.popen("which #{myCommand}", "w") # OK - the parameter is named `myCommand`, so it's meant to be a command
|
||||||
IO.popen("which #{innocent_file_path}", "w") # NOT OK - the parameter is named `innocent_file_path`, so it's not meant to be a command
|
IO.popen("which #{innocent_file_path}", "w") # $ Alert // NOT OK - the parameter is named `innocent_file_path`, so it's not meant to be a command
|
||||||
end
|
end
|
||||||
|
|
||||||
def escaped(file_path)
|
def escaped(file_path) # $ Source
|
||||||
IO.popen("cat #{file_path.shellescape}", "w") # OK - the parameter is escaped
|
IO.popen("cat #{file_path.shellescape}", "w") # OK - the parameter is escaped
|
||||||
|
|
||||||
IO.popen("cat #{file_path}", "w") # NOT OK - the parameter is not escaped
|
IO.popen("cat #{file_path}", "w") # $ Alert // NOT OK - the parameter is not escaped
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
require File.join(File.dirname(__FILE__), 'sub', 'other')
|
require File.join(File.dirname(__FILE__), 'sub', 'other')
|
||||||
|
|
||||||
class Foobar2
|
class Foobar2
|
||||||
def foo1(target)
|
def foo1(target) # $ Source
|
||||||
IO.popen("cat #{target}", "w") # NOT OK
|
IO.popen("cat #{target}", "w") # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def id(x)
|
def id(x) # $ Source
|
||||||
IO.popen("cat #{x}", "w") # NOT OK - the parameter is not a constant.
|
IO.popen("cat #{x}", "w") # $ Alert // NOT OK - the parameter is not a constant.
|
||||||
return x
|
return x
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -44,27 +44,27 @@ class Foobar2
|
|||||||
end
|
end
|
||||||
|
|
||||||
# class methods
|
# class methods
|
||||||
def self.foo(target)
|
def self.foo(target) # $ Source
|
||||||
IO.popen("cat #{target}", "w") # NOT OK
|
IO.popen("cat #{target}", "w") # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def arrayJoin(x)
|
def arrayJoin(x) # $ Source
|
||||||
IO.popen(x.join(' '), "w") # NOT OK
|
IO.popen(x.join(' '), "w") # $ Alert // NOT OK
|
||||||
|
|
||||||
IO.popen(["foo", "bar", x].join(' '), "w") # NOT OK
|
IO.popen(["foo", "bar", x].join(' '), "w") # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def string_concat(x)
|
def string_concat(x) # $ Source
|
||||||
IO.popen("cat " + x, "w") # NOT OK
|
IO.popen("cat " + x, "w") # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def array_taint (x, y)
|
def array_taint (x, y) # $ Source
|
||||||
arr = ["cat"]
|
arr = ["cat"]
|
||||||
arr.push(x)
|
arr.push(x)
|
||||||
IO.popen(arr.join(' '), "w") # NOT OK
|
IO.popen(arr.join(' '), "w") # $ Alert // NOT OK
|
||||||
|
|
||||||
arr2 = ["cat"]
|
arr2 = ["cat"]
|
||||||
arr2 << y
|
arr2 << y
|
||||||
IO.popen(arr.join(' '), "w") # NOT OK
|
IO.popen(arr.join(' '), "w") # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-079/ReflectedXSS.ql
|
query: queries/security/cwe-079/ReflectedXSS.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-079/StoredXSS.ql
|
query: queries/security/cwe-079/StoredXSS.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-079/UnsafeHtmlConstruction.ql
|
query: queries/security/cwe-079/UnsafeHtmlConstruction.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -6,34 +6,34 @@ class BarsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def user_name
|
def user_name
|
||||||
return params[:user_name]
|
return params[:user_name] # $ Source[rb/reflected-xss]
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_name_memo
|
def user_name_memo
|
||||||
@user_name ||= params[:user_name]
|
@user_name ||= params[:user_name] # $ Source[rb/reflected-xss]
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@user_website = params[:website]
|
@user_website = params[:website] # $ Source[rb/reflected-xss]
|
||||||
dt = params[:text]
|
dt = params[:text] # $ Source[rb/reflected-xss]
|
||||||
@instance_text = dt
|
@instance_text = dt
|
||||||
@safe_foo = params[:text]
|
@safe_foo = params[:text]
|
||||||
@safe_foo = "safe_foo"
|
@safe_foo = "safe_foo"
|
||||||
@html_escaped = ERB::Util.html_escape(params[:text])
|
@html_escaped = ERB::Util.html_escape(params[:text])
|
||||||
@header_escaped = ERB::Util.html_escape(cookies[:foo]) # OK - cookies not controllable by 3rd party
|
@header_escaped = ERB::Util.html_escape(cookies[:foo]) # OK - cookies not controllable by 3rd party
|
||||||
response.header["content-type"] = params[:content_type]
|
response.header["content-type"] = params[:content_type] # $ Alert[rb/reflected-xss]
|
||||||
response.header["x-customer-header"] = params[:bar] # OK - header not relevant to XSS
|
response.header["x-customer-header"] = params[:bar] # OK - header not relevant to XSS
|
||||||
render "foo/bars/show", locals: { display_text: dt, safe_text: "hello" }
|
render "foo/bars/show", locals: { display_text: dt, safe_text: "hello" }
|
||||||
end
|
end
|
||||||
|
|
||||||
def make_safe_html
|
def make_safe_html
|
||||||
str = params[:user_name]
|
str = params[:user_name] # $ Source[rb/reflected-xss]
|
||||||
str.html_safe
|
str.html_safe # $ Alert[rb/reflected-xss]
|
||||||
|
|
||||||
translate("welcome", name: params[:user_name]).html_safe # NOT OK - translate preserves taint
|
translate("welcome", name: params[:user_name]).html_safe # $ Alert[rb/reflected-xss] // NOT OK - translate preserves taint
|
||||||
t("welcome", name: params[:user_name]).html_safe # NOT OK - t is an alias of translate
|
t("welcome", name: params[:user_name]).html_safe # $ Alert[rb/reflected-xss] // NOT OK - t is an alias of translate
|
||||||
t("welcome_html", name: params[:user_name]).html_safe # OK - t escapes html when key ends in _html
|
t("welcome_html", name: params[:user_name]).html_safe # OK - t escapes html when key ends in _html
|
||||||
I18n.t("welcome_html", name: params[:user_name]).html_safe # NOT OK - I18n.t does not escape html
|
I18n.t("welcome_html", name: params[:user_name]).html_safe # $ Alert[rb/reflected-xss] // NOT OK - I18n.t does not escape html
|
||||||
I18n.translate("welcome_html", name: params[:user_name]).html_safe # NOT OK - alias
|
I18n.translate("welcome_html", name: params[:user_name]).html_safe # $ Alert[rb/reflected-xss] // NOT OK - alias
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ class StoresController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
dt = File.read("foo.txt")
|
dt = File.read("foo.txt") # $ Source[rb/stored-xss]
|
||||||
@instance_text = dt
|
@instance_text = dt
|
||||||
@user = User.find 1
|
@user = User.find 1
|
||||||
@safe_user_handle = ERB::Util.html_escape(@user.handle)
|
@safe_user_handle = ERB::Util.html_escape(@user.handle)
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
<%= raw @display_text %>
|
<%= raw @display_text %>
|
||||||
|
|
||||||
<%# BAD: A local rendered raw as a local variable %>
|
<%# BAD: A local rendered raw as a local variable %>
|
||||||
<%= raw display_text %>
|
<%= raw display_text %> <%# $ Alert[rb/reflected-xss], Alert[rb/stored-xss] %>
|
||||||
|
|
||||||
<%# BAD: A local rendered raw via the local_assigns hash %>
|
<%# BAD: A local rendered raw via the local_assigns hash %>
|
||||||
<%= raw local_assigns[:display_text] %>
|
<%= raw local_assigns[:display_text] %> <%# $ Alert[rb/reflected-xss], Alert[rb/stored-xss] %>
|
||||||
|
|
||||||
<%# GOOD: A local rendered with default escaping via the local_assigns hash %>
|
<%# GOOD: A local rendered with default escaping via the local_assigns hash %>
|
||||||
<%= local_assigns[:display_text] %>
|
<%= local_assigns[:display_text] %>
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
<%# BAD: An instance variable rendered without escaping %>
|
<%# BAD: An instance variable rendered without escaping %>
|
||||||
<a href="<%= raw @user_website %>">website</a>
|
<a href="<%= raw @user_website %>">website</a> <%# $ Alert[rb/reflected-xss] %>
|
||||||
|
|
||||||
<%# BAD: A local rendered raw as a local variable %>
|
<%# BAD: A local rendered raw as a local variable %>
|
||||||
<%= raw display_text %>
|
<%= raw display_text %> <%# $ Alert[rb/reflected-xss] %>
|
||||||
|
|
||||||
<%# BAD: A local rendered raw via the local_assigns hash %>
|
<%# BAD: A local rendered raw via the local_assigns hash %>
|
||||||
<%= raw local_assigns[:display_text] %>
|
<%= raw local_assigns[:display_text] %> <%# $ Alert[rb/reflected-xss] %>
|
||||||
|
|
||||||
<% key = :display_text %>
|
<% key = :display_text %>
|
||||||
<%# BAD: A local rendered raw via the locals_assigns hash %>
|
<%# BAD: A local rendered raw via the locals_assigns hash %>
|
||||||
<%= raw local_assigns[key] %>
|
<%= raw local_assigns[key] %> <%# $ Alert[rb/reflected-xss] %>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<% for key in [:display_text, :safe_text] do %>
|
<% for key in [:display_text, :safe_text] do %>
|
||||||
<%# BAD: A local rendered raw via the locals hash %>
|
<%# BAD: A local rendered raw via the locals hash %>
|
||||||
<li><%= raw local_assigns[key] %></li>
|
<li><%= raw local_assigns[key] %></li> <%# $ Alert[rb/reflected-xss] %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -32,28 +32,28 @@
|
|||||||
|
|
||||||
<%# BAD: html_safe marks string as not requiring HTML escaping %>
|
<%# BAD: html_safe marks string as not requiring HTML escaping %>
|
||||||
<%=
|
<%=
|
||||||
display_text.html_safe
|
display_text.html_safe <%# $ Alert[rb/reflected-xss] %>
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<%# BAD: html_safe marks string as not requiring HTML escaping %>
|
<%# BAD: html_safe marks string as not requiring HTML escaping %>
|
||||||
<%=
|
<%=
|
||||||
@instance_text.html_safe
|
@instance_text.html_safe <%# $ Alert[rb/reflected-xss] %>
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<%= render partial: 'foo/bars/widget', locals: { display_text: "widget_" + display_text } %>
|
<%= render partial: 'foo/bars/widget', locals: { display_text: "widget_" + display_text } %>
|
||||||
|
|
||||||
<%# BAD: user_name is a helper method that returns unsanitized user-input %>
|
<%# BAD: user_name is a helper method that returns unsanitized user-input %>
|
||||||
<%= user_name.html_safe %>
|
<%= user_name.html_safe %> <%# $ Alert[rb/reflected-xss] %>
|
||||||
|
|
||||||
<%# BAD: user_name_memo is a helper method that returns unsanitized user-input %>
|
<%# BAD: user_name_memo is a helper method that returns unsanitized user-input %>
|
||||||
<%# TODO: we miss this because the return value from user_name_memo is not properly linked to this call %>
|
<%# TODO: we miss this because the return value from user_name_memo is not properly linked to this call %>
|
||||||
<%= user_name_memo.html_safe %>
|
<%= user_name_memo.html_safe %> <%# $ Alert[rb/reflected-xss] %>
|
||||||
|
|
||||||
<%# BAD: unsanitized user-input should not be passed to link_to as the URL %>
|
<%# BAD: unsanitized user-input should not be passed to link_to as the URL %>
|
||||||
<%= link_to "user website", params[:website] %>
|
<%= link_to "user website", params[:website] %> <%# $ Alert[rb/reflected-xss] %>
|
||||||
|
|
||||||
<%# BAD: unsanitized user-input should not be passed to link_to as the URL %>
|
<%# BAD: unsanitized user-input should not be passed to link_to as the URL %>
|
||||||
<%= link_to params[:website], class: "user-link" do %>
|
<%= link_to params[:website], class: "user-link" do %> <%# $ Alert[rb/reflected-xss] %>
|
||||||
user website
|
user website
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
@@ -70,20 +70,20 @@
|
|||||||
%>
|
%>
|
||||||
|
|
||||||
<%# BAD: simple_format called with sanitize: false %>
|
<%# BAD: simple_format called with sanitize: false %>
|
||||||
<%= simple_format(params[:comment], sanitize: false) %>
|
<%= simple_format(params[:comment], sanitize: false) %> <%# $ Alert[rb/reflected-xss] %>
|
||||||
|
|
||||||
<%# BAD: javasript_include_tag called with remote input %>
|
<%# BAD: javasript_include_tag called with remote input %>
|
||||||
<%= javascript_include_tag params[:url] %>
|
<%= javascript_include_tag params[:url] %> <%# $ Alert[rb/reflected-xss] %>
|
||||||
|
|
||||||
<%# GOOD: input is sanitized %>
|
<%# GOOD: input is sanitized %>
|
||||||
<%= sanitize(params[:comment]).html_safe %>
|
<%= sanitize(params[:comment]).html_safe %>
|
||||||
|
|
||||||
<%# BAD: A local rendered raw as a local variable %>
|
<%# BAD: A local rendered raw as a local variable %>
|
||||||
<%== display_text %>
|
<%== display_text %> <%# $ Alert[rb/reflected-xss] %>
|
||||||
|
|
||||||
<%# BAD: translate preserves taint %>
|
<%# BAD: translate preserves taint %>
|
||||||
<%= raw translate("welcome", name: display_text) %>
|
<%= raw translate("welcome", name: display_text) %> <%# $ Alert[rb/reflected-xss] %>
|
||||||
<%= raw t("welcome", name: display_text) %>
|
<%= raw t("welcome", name: display_text) %> <%# $ Alert[rb/reflected-xss] %>
|
||||||
|
|
||||||
<%# GOOD: translate sanitizes for html keys %>
|
<%# GOOD: translate sanitizes for html keys %>
|
||||||
<%= raw t("welcome1.html", name: display_text) %>
|
<%= raw t("welcome1.html", name: display_text) %>
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
<%# BAD: A local rendered raw as a local variable %>
|
<%# BAD: A local rendered raw as a local variable %>
|
||||||
<%= raw display_text %>
|
<%= raw display_text %> <%# $ Alert[rb/stored-xss] %>
|
||||||
|
|
||||||
<%# BAD: A local rendered raw via the local_assigns hash %>
|
<%# BAD: A local rendered raw via the local_assigns hash %>
|
||||||
<%= raw local_assigns[:display_text] %>
|
<%= raw local_assigns[:display_text] %> <%# $ Alert[rb/stored-xss] %>
|
||||||
|
|
||||||
<% key = :display_text %>
|
<% key = :display_text %>
|
||||||
<%# BAD: A local rendered raw via the locals_assigns hash %>
|
<%# BAD: A local rendered raw via the locals_assigns hash %>
|
||||||
<%= raw local_assigns[key] %>
|
<%= raw local_assigns[key] %> <%# $ Alert[rb/stored-xss] %>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<% for key in [:display_text, :safe_text] do %>
|
<% for key in [:display_text, :safe_text] do %>
|
||||||
<%# BAD: A local rendered raw via the locals hash %>
|
<%# BAD: A local rendered raw via the locals hash %>
|
||||||
<li><%= raw local_assigns[key] %></li>
|
<li><%= raw local_assigns[key] %></li> <%# $ Alert[rb/stored-xss] %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -29,12 +29,12 @@
|
|||||||
|
|
||||||
<%# BAD: html_safe marks string as not requiring HTML escaping %>
|
<%# BAD: html_safe marks string as not requiring HTML escaping %>
|
||||||
<%=
|
<%=
|
||||||
display_text.html_safe
|
display_text.html_safe <%# $ Alert[rb/stored-xss] %>
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<%# BAD: html_safe marks string as not requiring HTML escaping %>
|
<%# BAD: html_safe marks string as not requiring HTML escaping %>
|
||||||
<%=
|
<%=
|
||||||
@instance_text.html_safe
|
@instance_text.html_safe <%# $ Alert[rb/stored-xss] %>
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<%= render partial: 'foo/bars/widget', locals: { display_text: "widget_" + display_text } %>
|
<%= render partial: 'foo/bars/widget', locals: { display_text: "widget_" + display_text } %>
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
<%= user_name_handle.html_safe %>
|
<%= user_name_handle.html_safe %>
|
||||||
|
|
||||||
<%# BAD: Direct to a database value without escaping %>
|
<%# BAD: Direct to a database value without escaping %>
|
||||||
<%= @user.handle.html_safe %>
|
<%= @user.handle.html_safe %> <%# $ Alert[rb/stored-xss] %>
|
||||||
|
|
||||||
<%# BAD: Indirect to a database value without escaping %>
|
<%# BAD: Indirect to a database value without escaping %>
|
||||||
<%= @user.raw_name.html_safe %>
|
<%= @user.raw_name.html_safe %>
|
||||||
@@ -60,7 +60,7 @@
|
|||||||
<%# BAD: Direct to a database value without escaping %>
|
<%# BAD: Direct to a database value without escaping %>
|
||||||
<%=
|
<%=
|
||||||
some_user = User.find 1
|
some_user = User.find 1
|
||||||
some_user.handle.html_safe
|
some_user.handle.html_safe <%# $ Alert[rb/stored-xss] %>
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<%# BAD: Indirect to a database value without escaping (currently missed due to lack of 'self' handling in ORM tracking) %>
|
<%# BAD: Indirect to a database value without escaping (currently missed due to lack of 'self' handling in ORM tracking) %>
|
||||||
@@ -83,7 +83,7 @@
|
|||||||
|
|
||||||
<%# BAD: Kernel.sprintf is a taint-step %>
|
<%# BAD: Kernel.sprintf is a taint-step %>
|
||||||
<%=
|
<%=
|
||||||
sprintf("%s", @user.handle).html_safe
|
sprintf("%s", @user.handle).html_safe <%# $ Alert[rb/stored-xss] %>
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<%# GOOD: The `foo.bar.baz` is not recognized as a source %>
|
<%# GOOD: The `foo.bar.baz` is not recognized as a source %>
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
class Foobar
|
class Foobar
|
||||||
def create_user_description(name)
|
def create_user_description(name) # $ Source[rb/html-constructed-from-input]
|
||||||
"<h2>#{name}</h2>".html_safe # NOT OK - the parameter is not escaped
|
"<h2>#{name}</h2>".html_safe # $ Alert[rb/html-constructed-from-input] // NOT OK - the parameter is not escaped
|
||||||
|
|
||||||
# escape
|
# escape
|
||||||
"<h2>#{ERB::Util.html_escape(name)}</h2>".html_safe # OK - the parameter is escaped
|
"<h2>#{ERB::Util.html_escape(name)}</h2>".html_safe # OK - the parameter is escaped
|
||||||
end
|
end
|
||||||
|
|
||||||
def string_like_literal name
|
def string_like_literal name # $ Source[rb/html-constructed-from-input]
|
||||||
h = <<-HTML
|
h = <<-HTML
|
||||||
<h2>#{name}</h2>
|
<h2>#{name}</h2> # $ Alert[rb/html-constructed-from-input]
|
||||||
HTML
|
HTML
|
||||||
h.html_safe # NOT OK - the parameter is not escaped
|
h.html_safe # NOT OK - the parameter is not escaped
|
||||||
end
|
end
|
||||||
|
|
||||||
def sprintf_use name
|
def sprintf_use name # $ Source[rb/html-constructed-from-input]
|
||||||
sprintf("<h2>%s</h2>", name).html_safe # NOT OK - the parameter is not escaped
|
sprintf("<h2>%s</h2>", name).html_safe # $ Alert[rb/html-constructed-from-input] // NOT OK - the parameter is not escaped
|
||||||
|
|
||||||
# escape
|
# escape
|
||||||
sprintf("<h2>%s</h2>", ERB::Util.html_escape(name)).html_safe # OK - the parameter is escaped
|
sprintf("<h2>%s</h2>", ERB::Util.html_escape(name)).html_safe # OK - the parameter is escaped
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_user_description2(name)
|
def create_user_description2(name) # $ Source[rb/html-constructed-from-input]
|
||||||
"<h2>#{name}</h2>".html_safe # NOT OK - the value is not necessarily HTML safe
|
"<h2>#{name}</h2>".html_safe # $ Alert[rb/html-constructed-from-input] // NOT OK - the value is not necessarily HTML safe
|
||||||
|
|
||||||
if name.html_safe?
|
if name.html_safe?
|
||||||
"<h2>#{name}</h2>".html_safe # OK - value is marked as being HTML safe
|
"<h2>#{name}</h2>".html_safe # OK - value is marked as being HTML safe
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ class User < ApplicationRecord
|
|||||||
|
|
||||||
def self.authenticate(name, pass)
|
def self.authenticate(name, pass)
|
||||||
# BAD: possible untrusted input interpolated into SQL fragment
|
# BAD: possible untrusted input interpolated into SQL fragment
|
||||||
find(:first, :conditions => "name='#{name}' and pass='#{pass}'")
|
find(:first, :conditions => "name='#{name}' and pass='#{pass}'") # $ Alert
|
||||||
# BAD: interpolation in array argument
|
# BAD: interpolation in array argument
|
||||||
find(:first, conditions: ["name='#{name}' and pass='#{pass}'"])
|
find(:first, conditions: ["name='#{name}' and pass='#{pass}'"]) # $ Alert
|
||||||
# GOOD: using SQL parameters
|
# GOOD: using SQL parameters
|
||||||
find(:first, conditions: ["name = ? and pass = ?", name, pass])
|
find(:first, conditions: ["name = ? and pass = ?", name, pass])
|
||||||
# BAD: interpolation with flow
|
# BAD: interpolation with flow
|
||||||
conds = "name=#{name}"
|
conds = "name=#{name}" # $ Alert
|
||||||
find(:first, conditions: conds)
|
find(:first, conditions: conds)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ class Admin < User
|
|||||||
def self.delete_by(condition = nil)
|
def self.delete_by(condition = nil)
|
||||||
# BAD: `delete_by overrides an ActiveRecord method, but doesn't perform
|
# BAD: `delete_by overrides an ActiveRecord method, but doesn't perform
|
||||||
# any validation before passing its arguments on to another ActiveRecord method
|
# any validation before passing its arguments on to another ActiveRecord method
|
||||||
destroy_by(condition)
|
destroy_by(condition) # $ Alert
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -39,64 +39,64 @@ class FooController < ActionController::Base
|
|||||||
def some_request_handler
|
def some_request_handler
|
||||||
# BAD: executes `SELECT AVG(#{params[:column]}) FROM "users"`
|
# BAD: executes `SELECT AVG(#{params[:column]}) FROM "users"`
|
||||||
# where `params[:column]` is unsanitized
|
# where `params[:column]` is unsanitized
|
||||||
User.calculate(:average, params[:column])
|
User.calculate(:average, params[:column]) # $ Alert
|
||||||
|
|
||||||
# BAD: executes `SELECT MAX(#{params[:column]}) FROM "users"`
|
# BAD: executes `SELECT MAX(#{params[:column]}) FROM "users"`
|
||||||
# where `params[:column]` is unsanitized
|
# where `params[:column]` is unsanitized
|
||||||
User.maximum(params[:column])
|
User.maximum(params[:column]) # $ Alert
|
||||||
|
|
||||||
# BAD: executes `DELETE FROM "users" WHERE (id = '#{params[:id]}')`
|
# BAD: executes `DELETE FROM "users" WHERE (id = '#{params[:id]}')`
|
||||||
# where `params[:id]` is unsanitized
|
# where `params[:id]` is unsanitized
|
||||||
User.delete_by("id = '#{params[:id]}'")
|
User.delete_by("id = '#{params[:id]}'") # $ Alert
|
||||||
|
|
||||||
# BAD: executes `DELETE FROM "users" WHERE (id = '#{params[:id]}')`
|
# BAD: executes `DELETE FROM "users" WHERE (id = '#{params[:id]}')`
|
||||||
# where `params[:id]` is unsanitized
|
# where `params[:id]` is unsanitized
|
||||||
# (in Rails < 4.0)
|
# (in Rails < 4.0)
|
||||||
User.delete_all("id = '#{params[:id]}'")
|
User.delete_all("id = '#{params[:id]}'") # $ Alert
|
||||||
|
|
||||||
# BAD: executes `SELECT "users".* FROM "users" WHERE (id = '#{params[:id]}')`
|
# BAD: executes `SELECT "users".* FROM "users" WHERE (id = '#{params[:id]}')`
|
||||||
# where `params[:id]` is unsanitized
|
# where `params[:id]` is unsanitized
|
||||||
User.destroy_by(["id = '#{params[:id]}'"])
|
User.destroy_by(["id = '#{params[:id]}'"]) # $ Alert
|
||||||
|
|
||||||
# BAD: executes `SELECT "users".* FROM "users" WHERE (id = '#{params[:id]}')`
|
# BAD: executes `SELECT "users".* FROM "users" WHERE (id = '#{params[:id]}')`
|
||||||
# where `params[:id]` is unsanitized
|
# where `params[:id]` is unsanitized
|
||||||
# (in Rails < 4.0)
|
# (in Rails < 4.0)
|
||||||
User.destroy_all(["id = '#{params[:id]}'"])
|
User.destroy_all(["id = '#{params[:id]}'"]) # $ Alert
|
||||||
|
|
||||||
# BAD: executes `SELECT "users".* FROM "users" WHERE id BETWEEN '#{params[:min_id]}' AND 100000`
|
# BAD: executes `SELECT "users".* FROM "users" WHERE id BETWEEN '#{params[:min_id]}' AND 100000`
|
||||||
# where `params[:min_id]` is unsanitized
|
# where `params[:min_id]` is unsanitized
|
||||||
User.where(<<-SQL, MAX_USER_ID)
|
User.where(<<-SQL, MAX_USER_ID) # $ Alert
|
||||||
id BETWEEN '#{params[:min_id]}' AND ?
|
id BETWEEN '#{params[:min_id]}' AND ? # $ Source
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
# BAD: chained method case
|
# BAD: chained method case
|
||||||
# executes `SELECT "users".* FROM "users" WHERE (NOT (user_id = 'params[:id]'))`
|
# executes `SELECT "users".* FROM "users" WHERE (NOT (user_id = 'params[:id]'))`
|
||||||
# where `params[:id]` is unsanitized
|
# where `params[:id]` is unsanitized
|
||||||
User.where.not("user.id = '#{params[:id]}'")
|
User.where.not("user.id = '#{params[:id]}'") # $ Alert
|
||||||
|
|
||||||
User.authenticate(params[:name], params[:pass])
|
User.authenticate(params[:name], params[:pass]) # $ Source
|
||||||
|
|
||||||
# BAD: executes `SELECT "users".* FROM "users" WHERE (id = '#{params[:id]}')` LIMIT 1
|
# BAD: executes `SELECT "users".* FROM "users" WHERE (id = '#{params[:id]}')` LIMIT 1
|
||||||
# where `params[:id]` is unsanitized
|
# where `params[:id]` is unsanitized
|
||||||
User.find_or_initialize_by("id = '#{params[:id]}'")
|
User.find_or_initialize_by("id = '#{params[:id]}'") # $ Alert
|
||||||
|
|
||||||
user = User.first
|
user = User.first
|
||||||
# BAD: executes `SELECT "users".* FROM "users" WHERE id = 1 LIMIT 1 #{params[:lock]}`
|
# BAD: executes `SELECT "users".* FROM "users" WHERE id = 1 LIMIT 1 #{params[:lock]}`
|
||||||
# where `params[:lock]` is unsanitized
|
# where `params[:lock]` is unsanitized
|
||||||
user.reload(lock: params[:lock])
|
user.reload(lock: params[:lock]) # $ Alert
|
||||||
|
|
||||||
# BAD: executes `SELECT #{params[:column]} FROM "users"`
|
# BAD: executes `SELECT #{params[:column]} FROM "users"`
|
||||||
# where `params[:column]` is unsanitized
|
# where `params[:column]` is unsanitized
|
||||||
User.select(params[:column])
|
User.select(params[:column]) # $ Alert
|
||||||
User.reselect(params[:column])
|
User.reselect(params[:column]) # $ Alert
|
||||||
|
|
||||||
# BAD: executes `SELECT "users".* FROM "users" WHERE (#{params[:condition]})`
|
# BAD: executes `SELECT "users".* FROM "users" WHERE (#{params[:condition]})`
|
||||||
# where `params[:condition]` is unsanitized
|
# where `params[:condition]` is unsanitized
|
||||||
User.rewhere(params[:condition])
|
User.rewhere(params[:condition]) # $ Alert
|
||||||
|
|
||||||
# BAD: executes `UPDATE "users" SET #{params[:fields]}`
|
# BAD: executes `UPDATE "users" SET #{params[:fields]}`
|
||||||
# where `params[:fields]` is unsanitized
|
# where `params[:fields]` is unsanitized
|
||||||
User.update_all(params[:fields])
|
User.update_all(params[:fields]) # $ Alert
|
||||||
|
|
||||||
# GOOD -- `update_all` sanitizes its bind variable arguments
|
# GOOD -- `update_all` sanitizes its bind variable arguments
|
||||||
User.find_by(name: params[:user_name])
|
User.find_by(name: params[:user_name])
|
||||||
@@ -104,41 +104,41 @@ class FooController < ActionController::Base
|
|||||||
|
|
||||||
# BAD -- `update_all` does not sanitize its query (array arg)
|
# BAD -- `update_all` does not sanitize its query (array arg)
|
||||||
User.find_by(name: params[:user_name])
|
User.find_by(name: params[:user_name])
|
||||||
.update_all(["name = '#{params[:new_user_name]}'"])
|
.update_all(["name = '#{params[:new_user_name]}'"]) # $ Alert
|
||||||
|
|
||||||
# BAD -- `update_all` does not sanitize its query (string arg)
|
# BAD -- `update_all` does not sanitize its query (string arg)
|
||||||
User.find_by(name: params[:user_name])
|
User.find_by(name: params[:user_name])
|
||||||
.update_all("name = '#{params[:new_user_name]}'")
|
.update_all("name = '#{params[:new_user_name]}'") # $ Alert
|
||||||
|
|
||||||
User.reorder(params[:direction])
|
User.reorder(params[:direction]) # $ Alert
|
||||||
|
|
||||||
User.select('a','b', params[:column])
|
User.select('a','b', params[:column]) # $ Alert
|
||||||
User.reselect('a','b', params[:column])
|
User.reselect('a','b', params[:column]) # $ Alert
|
||||||
User.order('a ASC', "b #{params[:direction]}")
|
User.order('a ASC', "b #{params[:direction]}") # $ Alert
|
||||||
User.reorder('a ASC', "b #{params[:direction]}")
|
User.reorder('a ASC', "b #{params[:direction]}") # $ Alert
|
||||||
User.group('a', params[:column])
|
User.group('a', params[:column]) # $ Alert
|
||||||
User.pluck('a', params[:column])
|
User.pluck('a', params[:column]) # $ Alert
|
||||||
User.joins(:a, params[:column])
|
User.joins(:a, params[:column]) # $ Alert
|
||||||
|
|
||||||
User.count_by_sql(params[:custom_sql_query])
|
User.count_by_sql(params[:custom_sql_query]) # $ Alert
|
||||||
|
|
||||||
# BAD: executes `SELECT users.* FROM #{params[:tab]}`
|
# BAD: executes `SELECT users.* FROM #{params[:tab]}`
|
||||||
# where `params[:tab]` is unsanitized
|
# where `params[:tab]` is unsanitized
|
||||||
User.all.from(params[:tab])
|
User.all.from(params[:tab]) # $ Alert
|
||||||
# BAD: executes `SELECT "users".* FROM (SELECT "users".* FROM "users") #{params[:sq]}
|
# BAD: executes `SELECT "users".* FROM (SELECT "users".* FROM "users") #{params[:sq]}
|
||||||
User.all.from(User.all, params[:sq])
|
User.all.from(User.all, params[:sq]) # $ Alert
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class BarController < ApplicationController
|
class BarController < ApplicationController
|
||||||
def some_other_request_handler
|
def some_other_request_handler
|
||||||
ps = params
|
ps = params # $ Source
|
||||||
uid = ps[:id]
|
uid = ps[:id]
|
||||||
uidEq = "= '#{uid}'"
|
uidEq = "= '#{uid}'"
|
||||||
|
|
||||||
# BAD: executes `DELETE FROM "users" WHERE (id = #{uid})`
|
# BAD: executes `DELETE FROM "users" WHERE (id = #{uid})`
|
||||||
# where `uid` is unsantized
|
# where `uid` is unsantized
|
||||||
User.delete_by("id " + uidEq)
|
User.delete_by("id " + uidEq) # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
def safe_paths
|
def safe_paths
|
||||||
@@ -171,7 +171,7 @@ end
|
|||||||
|
|
||||||
class BazController < BarController
|
class BazController < BarController
|
||||||
def yet_another_handler
|
def yet_another_handler
|
||||||
Admin.delete_by(params[:admin_condition])
|
Admin.delete_by(params[:admin_condition]) # $ Alert, Source
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -185,7 +185,7 @@ class AnnotatedController < ActionController::Base
|
|||||||
def unsafe_action
|
def unsafe_action
|
||||||
name = params[:user_name]
|
name = params[:user_name]
|
||||||
# BAD: user input passed into annotations are vulnerable to SQLi
|
# BAD: user input passed into annotations are vulnerable to SQLi
|
||||||
users = User.annotate("this is an unsafe annotation:#{params[:comment]}").find_by(user_name: name)
|
users = User.annotate("this is an unsafe annotation:#{params[:comment]}").find_by(user_name: name) # $ Alert
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -198,27 +198,27 @@ class RegressionController < ActionController::Base
|
|||||||
def index
|
def index
|
||||||
my_params = permitted_params
|
my_params = permitted_params
|
||||||
query = "SELECT * FROM users WHERE id = #{my_params[:user_id]}"
|
query = "SELECT * FROM users WHERE id = #{my_params[:user_id]}"
|
||||||
result = Regression.find_by_sql(query)
|
result = Regression.find_by_sql(query) # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def permitted_params
|
def permitted_params
|
||||||
params.require(:my_key).permit(:id, :user_id, :my_type)
|
params.require(:my_key).permit(:id, :user_id, :my_type) # $ Source
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
ActiveRecord::Base.connection.execute("SELECT * FROM users WHERE id = #{permitted_params[:user_id]}")
|
ActiveRecord::Base.connection.execute("SELECT * FROM users WHERE id = #{permitted_params[:user_id]}") # $ Alert
|
||||||
Regression.connection.execute("SELECT * FROM users WHERE id = #{permitted_params[:user_id]}")
|
Regression.connection.execute("SELECT * FROM users WHERE id = #{permitted_params[:user_id]}") # $ Alert
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class User
|
class User
|
||||||
scope :with_role, ->(role) { where("role = #{role}") }
|
scope :with_role, ->(role) { where("role = #{role}") } # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
class UsersController < ActionController::Base
|
class UsersController < ActionController::Base
|
||||||
def index
|
def index
|
||||||
# BAD: user input passed to scope which uses it without sanitization.
|
# BAD: user input passed to scope which uses it without sanitization.
|
||||||
@users = User.with_role(params[:role])
|
@users = User.with_role(params[:role]) # $ Source
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
|
|
||||||
class PotatoController < ActionController::Base
|
class PotatoController < ActionController::Base
|
||||||
def unsafe_action
|
def unsafe_action
|
||||||
name = params[:user_name]
|
name = params[:user_name] # $ Source
|
||||||
# BAD: SQL statement constructed from user input
|
# BAD: SQL statement constructed from user input
|
||||||
sql = Arel.sql("SELECT * FROM users WHERE name = #{name}")
|
sql = Arel.sql("SELECT * FROM users WHERE name = #{name}") # $ Alert
|
||||||
sql = Arel::Nodes::SqlLiteral.new("SELECT * FROM users WHERE name = #{name}")
|
sql = Arel::Nodes::SqlLiteral.new("SELECT * FROM users WHERE name = #{name}") # $ Alert
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ class FooController < ActionController::Base
|
|||||||
def some_request_handler
|
def some_request_handler
|
||||||
# A string tainted by user input is inserted into a query
|
# A string tainted by user input is inserted into a query
|
||||||
# (i.e a remote flow source)
|
# (i.e a remote flow source)
|
||||||
name = params[:name]
|
name = params[:name] # $ Source
|
||||||
|
|
||||||
# Establish a connection to a PostgreSQL database
|
# Establish a connection to a PostgreSQL database
|
||||||
conn = PG::Connection.open(:dbname => 'postgresql', :user => 'user', :password => 'pass', :host => 'localhost', :port => '5432')
|
conn = PG::Connection.open(:dbname => 'postgresql', :user => 'user', :password => 'pass', :host => 'localhost', :port => '5432')
|
||||||
@@ -11,14 +11,14 @@ class FooController < ActionController::Base
|
|||||||
# .exec() and .async_exec()
|
# .exec() and .async_exec()
|
||||||
# BAD: SQL statement constructed from user input
|
# BAD: SQL statement constructed from user input
|
||||||
qry1 = "SELECT * FROM users WHERE username = '#{name}';"
|
qry1 = "SELECT * FROM users WHERE username = '#{name}';"
|
||||||
conn.exec(qry1)
|
conn.exec(qry1) # $ Alert
|
||||||
conn.async_exec(qry1)
|
conn.async_exec(qry1) # $ Alert
|
||||||
|
|
||||||
# .exec_params() and .async_exec_params()
|
# .exec_params() and .async_exec_params()
|
||||||
# BAD: SQL statement constructed from user input
|
# BAD: SQL statement constructed from user input
|
||||||
qry2 = "SELECT * FROM users WHERE username = '#{name}';"
|
qry2 = "SELECT * FROM users WHERE username = '#{name}';"
|
||||||
conn.exec_params(qry2)
|
conn.exec_params(qry2) # $ Alert
|
||||||
conn.async_exec_params(qry2)
|
conn.async_exec_params(qry2) # $ Alert
|
||||||
|
|
||||||
# .exec_params() and .async_exec_params()
|
# .exec_params() and .async_exec_params()
|
||||||
# GOOD: SQL statement constructed from sanitized user input
|
# GOOD: SQL statement constructed from sanitized user input
|
||||||
@@ -29,7 +29,7 @@ class FooController < ActionController::Base
|
|||||||
# .prepare() and .exec_prepared()
|
# .prepare() and .exec_prepared()
|
||||||
# BAD: SQL statement constructed from user input
|
# BAD: SQL statement constructed from user input
|
||||||
qry3 = "SELECT * FROM users WHERE username = '#{name}';"
|
qry3 = "SELECT * FROM users WHERE username = '#{name}';"
|
||||||
conn.prepare("query_1", qry3)
|
conn.prepare("query_1", qry3) # $ Alert
|
||||||
conn.exec_prepared('query_1')
|
conn.exec_prepared('query_1')
|
||||||
|
|
||||||
# .prepare() and .exec_prepared()
|
# .prepare() and .exec_prepared()
|
||||||
@@ -41,7 +41,7 @@ class FooController < ActionController::Base
|
|||||||
# .prepare() and .exec_prepared()
|
# .prepare() and .exec_prepared()
|
||||||
# NOT EXECUTED: SQL statement constructed from user input but not executed
|
# NOT EXECUTED: SQL statement constructed from user input but not executed
|
||||||
qry3 = "SELECT * FROM users WHERE username = '#{name}';"
|
qry3 = "SELECT * FROM users WHERE username = '#{name}';"
|
||||||
conn.prepare("query_3", qry3)
|
conn.prepare("query_3", qry3) # $ Alert
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-089/SqlInjection.ql
|
query: queries/security/cwe-089/SqlInjection.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-094/UnsafeCodeConstruction.ql
|
query: queries/security/cwe-094/UnsafeCodeConstruction.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
class Foobar
|
class Foobar
|
||||||
def foo1(target)
|
def foo1(target) # $ Source
|
||||||
eval("foo = #{target}") # NOT OK
|
eval("foo = #{target}") # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
# sprintf
|
# sprintf
|
||||||
def foo2(x)
|
def foo2(x) # $ Source
|
||||||
eval(sprintf("foo = %s", x)) # NOT OK
|
eval(sprintf("foo = %s", x)) # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
# String#%
|
# String#%
|
||||||
def foo3(x)
|
def foo3(x) # $ Source
|
||||||
eval("foo = %{foo}" % {foo: x}) # NOT OK
|
eval("foo = %{foo}" % {foo: x}) # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def indirect_eval(x)
|
def indirect_eval(x)
|
||||||
@@ -25,42 +25,42 @@ class Foobar
|
|||||||
eval("def \n #{code} \n end") # OK - parameter is named code
|
eval("def \n #{code} \n end") # OK - parameter is named code
|
||||||
end
|
end
|
||||||
|
|
||||||
def joinStuff(my_arr)
|
def joinStuff(my_arr) # $ Source
|
||||||
eval(my_arr.join("\n")) # NOT OK
|
eval(my_arr.join("\n")) # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def joinWithElemt(x)
|
def joinWithElemt(x) # $ Source
|
||||||
arr = [x, "foobar"]
|
arr = [x, "foobar"]
|
||||||
eval(arr.join("\n")) # NOT OK
|
eval(arr.join("\n")) # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def pushArr(x, y)
|
def pushArr(x, y) # $ Source
|
||||||
arr = []
|
arr = []
|
||||||
arr.push(x)
|
arr.push(x)
|
||||||
eval(arr.join("\n")) # NOT OK
|
eval(arr.join("\n")) # $ Alert // NOT OK
|
||||||
|
|
||||||
arr2 = []
|
arr2 = []
|
||||||
arr2 << y
|
arr2 << y
|
||||||
eval(arr.join("\n")) # NOT OK
|
eval(arr.join("\n")) # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def hereDoc(x)
|
def hereDoc(x) # $ Source
|
||||||
foo = <<~HERE
|
foo = <<~HERE
|
||||||
#{x}
|
#{x} # $ Alert
|
||||||
HERE
|
HERE
|
||||||
eval(foo) # NOT OK
|
eval(foo) # NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def string_concat(x)
|
def string_concat(x) # $ Source
|
||||||
foo = "foo = " + x
|
foo = "foo = " + x # $ Alert
|
||||||
eval(foo) # NOT OK
|
eval(foo) # NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def join_indirect(x, y)
|
def join_indirect(x, y) # $ Source
|
||||||
arr = Array(x)
|
arr = Array(x)
|
||||||
eval(arr.join(" ")) # NOT OK
|
eval(arr.join(" ")) # $ Alert // NOT OK
|
||||||
|
|
||||||
arr2 = [Array(["foo = ", y]).join(" ")]
|
arr2 = [Array(["foo = ", y]).join(" ")]
|
||||||
eval(arr2.join("\n")) # NOT OK
|
eval(arr2.join("\n")) # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-116/BadTagFilter.ql
|
query: queries/security/cwe-116/BadTagFilter.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
filters = [
|
filters = [
|
||||||
/<script.*?>.*?<\/script>/i, # NOT OK - doesn't match newlines or `</script >`
|
/<script.*?>.*?<\/script>/i, # $ Alert // NOT OK - doesn't match newlines or `</script >`
|
||||||
/<script.*?>.*?<\/script>/im, # NOT OK - doesn't match `</script >`
|
/<script.*?>.*?<\/script>/im, # $ Alert // NOT OK - doesn't match `</script >`
|
||||||
/<script.*?>.*?<\/script[^>]*>/im, # OK
|
/<script.*?>.*?<\/script[^>]*>/im, # OK
|
||||||
/<!--.*-->/im, # OK - we don't care regexps that only match comments
|
/<!--.*-->/im, # OK - we don't care regexps that only match comments
|
||||||
/<!--.*--!?>/im, # OK
|
/<!--.*--!?>/im, # OK
|
||||||
/<!--.*--!?>/i, # NOT OK, does not match newlines
|
/<!--.*--!?>/i, # $ Alert // NOT OK, does not match newlines
|
||||||
/<script.*?>(.|\s)*?<\/script[^>]*>/i, # NOT OK - doesn't match inside the script tag
|
/<script.*?>(.|\s)*?<\/script[^>]*>/i, # $ Alert // NOT OK - doesn't match inside the script tag
|
||||||
/<script[^>]*?>.*?<\/script[^>]*>/i, # NOT OK - doesn't match newlines inside the content
|
/<script[^>]*?>.*?<\/script[^>]*>/i, # $ Alert // NOT OK - doesn't match newlines inside the content
|
||||||
/<script(\s|\w|=|")*?>.*?<\/script[^>]*>/im, # NOT OK - does not match single quotes for attribute values
|
/<script(\s|\w|=|")*?>.*?<\/script[^>]*>/im, # $ Alert // NOT OK - does not match single quotes for attribute values
|
||||||
/<script(\s|\w|=|')*?>.*?<\/script[^>]*>/im, # NOT OK - does not match double quotes for attribute values
|
/<script(\s|\w|=|')*?>.*?<\/script[^>]*>/im, # $ Alert // NOT OK - does not match double quotes for attribute values
|
||||||
/<script( |\n|\w|=|'|")*?>.*?<\/script[^>]*>/im, # NOT OK - does not match tabs between attributes
|
/<script( |\n|\w|=|'|")*?>.*?<\/script[^>]*>/im, # $ Alert // NOT OK - does not match tabs between attributes
|
||||||
/<script.*?>.*?<\/script[^>]*>/m, # NOT OK - does not match uppercase SCRIPT tags
|
/<script.*?>.*?<\/script[^>]*>/m, # $ Alert // NOT OK - does not match uppercase SCRIPT tags
|
||||||
/<(script|SCRIPT).*?>.*?<\/(script|SCRIPT)[^>]*>/m, # NOT OK - does not match mixed case script tags
|
/<(script|SCRIPT).*?>.*?<\/(script|SCRIPT)[^>]*>/m, # $ Alert // NOT OK - does not match mixed case script tags
|
||||||
/<script[^>]*?>[\s\S]*?<\/script.*>/i, # NOT OK - doesn't match newlines in the end tag
|
/<script[^>]*?>[\s\S]*?<\/script.*>/i, # $ Alert // NOT OK - doesn't match newlines in the end tag
|
||||||
/<script[^>]*?>[\s\S]*?<\/script[^>]*?>/i, # OK
|
/<script[^>]*?>[\s\S]*?<\/script[^>]*?>/i, # OK
|
||||||
/<script\b[^>]*>([\s\S]*?)<\/script>/gi, # NOT OK - too strict matching on the end tag
|
/<script\b[^>]*>([\s\S]*?)<\/script>/gi, # $ Alert // NOT OK - too strict matching on the end tag
|
||||||
/<(?:!--([\S|\s]*?)-->)|([^\/\s>]+)[\S\s]*?>/, # NOT OK - doesn't match comments with the right capture groups
|
/<(?:!--([\S|\s]*?)-->)|([^\/\s>]+)[\S\s]*?>/, # $ Alert // NOT OK - doesn't match comments with the right capture groups
|
||||||
/<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\/\s>]+)((?:\s+[\w\-:.]+(?:\s*=\s*?(?:(?:"[^"]*")|(?:'[^']*')|[^\s"'\/>]+))?)*)[\S\s]*?(\/?)>))/, # NOT OK - capture groups
|
/<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\/\s>]+)((?:\s+[\w\-:.]+(?:\s*=\s*?(?:(?:"[^"]*")|(?:'[^']*')|[^\s"'\/>]+))?)*)[\S\s]*?(\/?)>))/, # $ Alert // NOT OK - capture groups
|
||||||
]
|
]
|
||||||
|
|
||||||
doFilters(filters)
|
doFilters(filters)
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-116/IncompleteSanitization.ql
|
query: queries/security/cwe-116/IncompleteSanitization.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -1,91 +1,91 @@
|
|||||||
|
|
||||||
def bad1(s)
|
def bad1(s)
|
||||||
s.sub "'", "" # NOT OK
|
s.sub "'", "" # $ Alert // NOT OK
|
||||||
s.sub! "'", "" # NOT OK
|
s.sub! "'", "" # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def bad2(s)
|
def bad2(s)
|
||||||
s.sub /'/, "" # NOT OK
|
s.sub /'/, "" # $ Alert // NOT OK
|
||||||
s.sub! /'/, "" # NOT OK
|
s.sub! /'/, "" # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def bad3(s1, s2, s3)
|
def bad3(s1, s2, s3)
|
||||||
s1.gsub /'/, "\\'" # NOT OK
|
s1.gsub /'/, "\\'" # $ Alert // NOT OK
|
||||||
s1.gsub /'/, '\\\'' # NOT OK
|
s1.gsub /'/, '\\\'' # $ Alert // NOT OK
|
||||||
s2.gsub! /'/, "\\'" # NOT OK
|
s2.gsub! /'/, "\\'" # $ Alert // NOT OK
|
||||||
s3.gsub! /'/, '\\\'' # NOT OK
|
s3.gsub! /'/, '\\\'' # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def bad4(s1, s2, s3)
|
def bad4(s1, s2, s3)
|
||||||
s1.gsub /'/, "\\\\\\&" # NOT OK
|
s1.gsub /'/, "\\\\\\&" # $ Alert // NOT OK
|
||||||
s1.gsub /'/, '\\\\\&' # NOT OK
|
s1.gsub /'/, '\\\\\&' # $ Alert // NOT OK
|
||||||
s2.gsub! /'/, "\\\\\\&" # NOT OK
|
s2.gsub! /'/, "\\\\\\&" # $ Alert // NOT OK
|
||||||
s3.gsub! /'/, '\\\\\&' # NOT OK
|
s3.gsub! /'/, '\\\\\&' # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def bad5(s)
|
def bad5(s)
|
||||||
s.gsub /['"]/, '\\\\\&' # NOT OK
|
s.gsub /['"]/, '\\\\\&' # $ Alert // NOT OK
|
||||||
s.gsub! /['"]/, '\\\\\&' # NOT OK
|
s.gsub! /['"]/, '\\\\\&' # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def bad6(s)
|
def bad6(s)
|
||||||
s.gsub /(['"])/, '\\\\\\1' # NOT OK
|
s.gsub /(['"])/, '\\\\\\1' # $ Alert // NOT OK
|
||||||
s.gsub! /(['"])/, '\\\\\\1' # NOT OK
|
s.gsub! /(['"])/, '\\\\\\1' # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def bad7(s)
|
def bad7(s)
|
||||||
s.gsub /('|")/, '\\\\\1' # NOT OK
|
s.gsub /('|")/, '\\\\\1' # $ Alert // NOT OK
|
||||||
s.gsub! /('|")/, '\\\\\1' # NOT OK
|
s.gsub! /('|")/, '\\\\\1' # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def bad8(s)
|
def bad8(s)
|
||||||
s.sub '|', '' # NOT OK
|
s.sub '|', '' # $ Alert // NOT OK
|
||||||
s.sub! '|', '' # NOT OK
|
s.sub! '|', '' # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def bad9(s1, s2, s3, s4)
|
def bad9(s1, s2, s3, s4)
|
||||||
s1.gsub /"/, "\\\"" # NOT OK
|
s1.gsub /"/, "\\\"" # $ Alert // NOT OK
|
||||||
s1.gsub /"/, '\\"' # NOT OK
|
s1.gsub /"/, '\\"' # $ Alert // NOT OK
|
||||||
s1.gsub '"', '\\"' # NOT OK
|
s1.gsub '"', '\\"' # $ Alert // NOT OK
|
||||||
s2.gsub! /"/, "\\\"" # NOT OK
|
s2.gsub! /"/, "\\\"" # $ Alert // NOT OK
|
||||||
s3.gsub! /"/, '\\"' # NOT OK
|
s3.gsub! /"/, '\\"' # $ Alert // NOT OK
|
||||||
s4.gsub! '"', '\\"' # NOT OK
|
s4.gsub! '"', '\\"' # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def bad10(s)
|
def bad10(s)
|
||||||
s.sub "/", "%2F" # NOT OK
|
s.sub "/", "%2F" # $ Alert // NOT OK
|
||||||
s.sub! "/", "%2F" # NOT OK
|
s.sub! "/", "%2F" # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def bad11(s)
|
def bad11(s)
|
||||||
s.sub "%25", "%" # NOT OK
|
s.sub "%25", "%" # $ Alert // NOT OK
|
||||||
s.sub! "%25", "%" # NOT OK
|
s.sub! "%25", "%" # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def bad12(s)
|
def bad12(s)
|
||||||
s.sub %q['], %q[] # NOT OK
|
s.sub %q['], %q[] # $ Alert // NOT OK
|
||||||
s.sub! %q['], %q[] # NOT OK
|
s.sub! %q['], %q[] # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def bad13(s)
|
def bad13(s)
|
||||||
s.sub "'" + "", "" # NOT OK
|
s.sub "'" + "", "" # $ Alert // NOT OK
|
||||||
s.sub! "'" + "", "" # NOT OK
|
s.sub! "'" + "", "" # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def bad14(s)
|
def bad14(s)
|
||||||
s.sub "'", "" + "" # NOT OK
|
s.sub "'", "" + "" # $ Alert // NOT OK
|
||||||
s.sub! "'", "" + "" # NOT OK
|
s.sub! "'", "" + "" # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def bad15(s)
|
def bad15(s)
|
||||||
s.sub "'" + "", "" + "" # NOT OK
|
s.sub "'" + "", "" + "" # $ Alert // NOT OK
|
||||||
s.sub! "'" + "", "" + "" # NOT OK
|
s.sub! "'" + "", "" + "" # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def bad16(s)
|
def bad16(s)
|
||||||
indirect = /'/
|
indirect = /'/
|
||||||
s.sub(indirect, "") # NOT OK
|
s.sub(indirect, "") # $ Alert // NOT OK
|
||||||
s.sub!(indirect, "") # NOT OK
|
s.sub!(indirect, "") # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def good1a(s)
|
def good1a(s)
|
||||||
@@ -212,15 +212,15 @@ def good13a(s)
|
|||||||
s.sub('[', '').sub(']', '') # OK
|
s.sub('[', '').sub(']', '') # OK
|
||||||
s.sub('(', '').sub(')', '') # OK
|
s.sub('(', '').sub(')', '') # OK
|
||||||
s.sub('{', '').sub('}', '') # OK
|
s.sub('{', '').sub('}', '') # OK
|
||||||
s.sub('<', '').sub('>', '') # NOT OK: too common as a bad HTML sanitizer
|
s.sub('<', '').sub('>', '') # $ Alert // NOT OK: too common as a bad HTML sanitizer
|
||||||
|
|
||||||
s.sub('[', '\\[').sub(']', '\\]') # NOT OK
|
s.sub('[', '\\[').sub(']', '\\]') # $ Alert // NOT OK
|
||||||
s.sub('{', '\\{').sub('}', '\\}') # NOT OK
|
s.sub('{', '\\{').sub('}', '\\}') # $ Alert // NOT OK
|
||||||
|
|
||||||
s = s.sub('[', '') # OK
|
s = s.sub('[', '') # OK
|
||||||
s = s.sub(']', '') # OK
|
s = s.sub(']', '') # OK
|
||||||
s.sub(/{/, '').sub(/}/, '') # OK
|
s.sub(/{/, '').sub(/}/, '') # OK
|
||||||
s.sub(']', '').sub('[', '') # probably OK, but still flagged
|
s.sub(']', '').sub('[', '') # $ Alert // probably OK, but still flagged
|
||||||
end
|
end
|
||||||
|
|
||||||
def good13b(s1)
|
def good13b(s1)
|
||||||
@@ -245,8 +245,8 @@ def newlines_a(a, b, c)
|
|||||||
# motivation for whitelist
|
# motivation for whitelist
|
||||||
`which emacs`.sub("\n", "") # OK
|
`which emacs`.sub("\n", "") # OK
|
||||||
|
|
||||||
a.sub("\n", "").sub(b, c) # NOT OK
|
a.sub("\n", "").sub(b, c) # $ Alert // NOT OK
|
||||||
a.sub(b, c).sub("\n", "") # NOT OK
|
a.sub(b, c).sub("\n", "") # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def newlines_b(a, b, c)
|
def newlines_b(a, b, c)
|
||||||
@@ -255,18 +255,18 @@ def newlines_b(a, b, c)
|
|||||||
output.sub!("\n", "") # OK
|
output.sub!("\n", "") # OK
|
||||||
|
|
||||||
d = a.dup
|
d = a.dup
|
||||||
d.sub!("\n", "") # NOT OK
|
d.sub!("\n", "") # $ Alert // NOT OK
|
||||||
d.sub!(b, c)
|
d.sub!(b, c)
|
||||||
|
|
||||||
e = a.dup
|
e = a.dup
|
||||||
d.sub!(b, c)
|
d.sub!(b, c)
|
||||||
d.sub!("\n", "") # NOT OK
|
d.sub!("\n", "") # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def bad_path_sanitizer(p1, p2)
|
def bad_path_sanitizer(p1, p2)
|
||||||
# attempt at path sanitization
|
# attempt at path sanitization
|
||||||
p1.sub! "/../", "" # NOT OK
|
p1.sub! "/../", "" # $ Alert // NOT OK
|
||||||
p2.sub "/../", "" # NOT OK
|
p2.sub "/../", "" # $ Alert // NOT OK
|
||||||
end
|
end
|
||||||
|
|
||||||
def each_line_sanitizer(p1)
|
def each_line_sanitizer(p1)
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-117/LogInjection.ql
|
query: queries/security/cwe-117/LogInjection.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ class UsersController < ApplicationController
|
|||||||
def read_from_params
|
def read_from_params
|
||||||
init_logger
|
init_logger
|
||||||
|
|
||||||
unsanitized = params[:foo]
|
unsanitized = params[:foo] # $ Source
|
||||||
@logger.debug unsanitized # BAD: unsanitized user input
|
@logger.debug unsanitized # $ Alert // BAD: unsanitized user input
|
||||||
@logger.error "input: " + unsanitized # BAD: unsanitized user input
|
@logger.error "input: " + unsanitized # $ Alert // BAD: unsanitized user input
|
||||||
|
|
||||||
sanitized = unsanitized.gsub("\n", "")
|
sanitized = unsanitized.gsub("\n", "")
|
||||||
@logger.fatal sanitized # GOOD: sanitized user input
|
@logger.fatal sanitized # GOOD: sanitized user input
|
||||||
@@ -22,17 +22,17 @@ class UsersController < ApplicationController
|
|||||||
|
|
||||||
unsanitized2 = unsanitized.sub("\n", "")
|
unsanitized2 = unsanitized.sub("\n", "")
|
||||||
@logger.info do
|
@logger.info do
|
||||||
unsanitized2 # BAD: partially sanitized user input
|
unsanitized2 # $ Alert // BAD: partially sanitized user input
|
||||||
end
|
end
|
||||||
@logger << "input: " + unsanitized2 # BAD: partially sanitized user input
|
@logger << "input: " + unsanitized2 # $ Alert // BAD: partially sanitized user input
|
||||||
end
|
end
|
||||||
|
|
||||||
def read_from_cookies
|
def read_from_cookies
|
||||||
init_logger
|
init_logger
|
||||||
|
|
||||||
unsanitized = cookies[:bar]
|
unsanitized = cookies[:bar] # $ Source
|
||||||
@logger.add(Logger::INFO) { unsanitized } # BAD: unsanitized user input
|
@logger.add(Logger::INFO) { unsanitized } # $ Alert // BAD: unsanitized user input
|
||||||
@logger.log(Logger::WARN) { "input: " + unsanitized } # BAD: unsanitized user input
|
@logger.log(Logger::WARN) { "input: " + unsanitized } # $ Alert // BAD: unsanitized user input
|
||||||
end
|
end
|
||||||
|
|
||||||
def html_sanitization
|
def html_sanitization
|
||||||
@@ -46,7 +46,7 @@ class UsersController < ApplicationController
|
|||||||
def inspect_sanitization
|
def inspect_sanitization
|
||||||
init_logger
|
init_logger
|
||||||
|
|
||||||
@logger.debug params[:foo] # BAD: unsanitized user input
|
@logger.debug params[:foo] # $ Alert // BAD: unsanitized user input
|
||||||
@logger.debug params[:foo].inspect # GOOD: sanitized user input
|
@logger.debug params[:foo].inspect # GOOD: sanitized user input
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-1333/ReDoS.ql
|
query: queries/security/cwe-1333/ReDoS.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# NOT GOOD; attack: "_" + "__".repeat(100)
|
# NOT GOOD; attack: "_" + "__".repeat(100)
|
||||||
# Adapted from marked (https://github.com/markedjs/marked), which is licensed
|
# Adapted from marked (https://github.com/markedjs/marked), which is licensed
|
||||||
# under the MIT license; see file marked-LICENSE.
|
# under the MIT license; see file marked-LICENSE.
|
||||||
bad1 = /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/
|
bad1 = /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/ # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
# Adapted from marked (https://github.com/markedjs/marked), which is licensed
|
# Adapted from marked (https://github.com/markedjs/marked), which is licensed
|
||||||
@@ -16,7 +16,7 @@ good2 = /(.*,)+.+/
|
|||||||
# NOT GOOD; attack: " '" + "\\\\".repeat(100)
|
# NOT GOOD; attack: " '" + "\\\\".repeat(100)
|
||||||
# Adapted from CodeMirror (https://github.com/codemirror/codemirror),
|
# Adapted from CodeMirror (https://github.com/codemirror/codemirror),
|
||||||
# which is licensed under the MIT license; see file CodeMirror-LICENSE.
|
# which is licensed under the MIT license; see file CodeMirror-LICENSE.
|
||||||
bad2 = /^(?:\s+(?:"(?:[^"\\]|\\\\|\\.)+"|'(?:[^'\\]|\\\\|\\.)+'|\((?:[^)\\]|\\\\|\\.)+\)))?/
|
bad2 = /^(?:\s+(?:"(?:[^"\\]|\\\\|\\.)+"|'(?:[^'\\]|\\\\|\\.)+'|\((?:[^)\\]|\\\\|\\.)+\)))?/ # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
# Adapted from lulucms2 (https://github.com/yiifans/lulucms2).
|
# Adapted from lulucms2 (https://github.com/yiifans/lulucms2).
|
||||||
@@ -28,89 +28,89 @@ good2 = /\(\*(?:[\s\S]*?\(\*[\s\S]*?\*\))*[\s\S]*?\*\)/
|
|||||||
good3 = /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/
|
good3 = /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/
|
||||||
|
|
||||||
# NOT GOOD, variant of good3; attack: "a|\n:|\n" + "||\n".repeat(100)
|
# NOT GOOD, variant of good3; attack: "a|\n:|\n" + "||\n".repeat(100)
|
||||||
bad4 = /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)a/
|
bad4 = /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)a/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD; attack: "/" + "\\/a".repeat(100)
|
# NOT GOOD; attack: "/" + "\\/a".repeat(100)
|
||||||
# Adapted from ANodeBlog (https://github.com/gefangshuai/ANodeBlog),
|
# Adapted from ANodeBlog (https://github.com/gefangshuai/ANodeBlog),
|
||||||
# which is licensed under the Apache License 2.0; see file ANodeBlog-LICENSE.
|
# which is licensed under the Apache License 2.0; see file ANodeBlog-LICENSE.
|
||||||
bad5 = /\/(?![ *])(\\\/|.)*?\/[gim]*(?=\W|$)/
|
bad5 = /\/(?![ *])(\\\/|.)*?\/[gim]*(?=\W|$)/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD; attack: "##".repeat(100) + "\na"
|
# NOT GOOD; attack: "##".repeat(100) + "\na"
|
||||||
# Adapted from CodeMirror (https://github.com/codemirror/codemirror),
|
# Adapted from CodeMirror (https://github.com/codemirror/codemirror),
|
||||||
# which is licensed under the MIT license; see file CodeMirror-LICENSE.
|
# which is licensed under the MIT license; see file CodeMirror-LICENSE.
|
||||||
bad6 = /^([\s\[\{\(]|#.*)*$/
|
bad6 = /^([\s\[\{\(]|#.*)*$/ # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
good4 = /(\r\n|\r|\n)+/
|
good4 = /(\r\n|\r|\n)+/
|
||||||
|
|
||||||
# BAD - PoC: `node -e "/((?:[^\"\']|\".*?\"|\'.*?\')*?)([(,)]|$)/.test(\"'''''''''''''''''''''''''''''''''''''''''''''\\\"\");"`. It's complicated though, because the regexp still matches something, it just matches the empty-string after the attack string.
|
# BAD - PoC: `node -e "/((?:[^\"\']|\".*?\"|\'.*?\')*?)([(,)]|$)/.test(\"'''''''''''''''''''''''''''''''''''''''''''''\\\"\");"`. It's complicated though, because the regexp still matches something, it just matches the empty-string after the attack string.
|
||||||
actuallyBad = /((?:[^"']|".*?"|'.*?')*?)([(,)]|$)/
|
actuallyBad = /((?:[^"']|".*?"|'.*?')*?)([(,)]|$)/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD; attack: "a" + "[]".repeat(100) + ".b\n"
|
# NOT GOOD; attack: "a" + "[]".repeat(100) + ".b\n"
|
||||||
# Adapted from Knockout (https://github.com/knockout/knockout), which is
|
# Adapted from Knockout (https://github.com/knockout/knockout), which is
|
||||||
# licensed under the MIT license; see file knockout-LICENSE
|
# licensed under the MIT license; see file knockout-LICENSE
|
||||||
bad6 = /^[\_$a-z][\_$a-z0-9]*(\[.*?\])*(\.[\_$a-z][\_$a-z0-9]*(\[.*?\])*)*$/i
|
bad6 = /^[\_$a-z][\_$a-z0-9]*(\[.*?\])*(\.[\_$a-z][\_$a-z0-9]*(\[.*?\])*)*$/i # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
good6 = /(a|.)*/
|
good6 = /(a|.)*/
|
||||||
|
|
||||||
# Testing the NFA - only some of the below are detected.
|
# Testing the NFA - only some of the below are detected.
|
||||||
bad7 = /^([a-z]+)+$/
|
bad7 = /^([a-z]+)+$/ # $ Alert
|
||||||
bad8 = /^([a-z]*)*$/
|
bad8 = /^([a-z]*)*$/ # $ Alert
|
||||||
bad9 = /^([a-zA-Z0-9])(([\\.-]|[_]+)?([a-zA-Z0-9]+))*(@){1}[a-z0-9]+[.]{1}(([a-z]{2,3})|([a-z]{2,3}[.]{1}[a-z]{2,3}))$/
|
bad9 = /^([a-zA-Z0-9])(([\\.-]|[_]+)?([a-zA-Z0-9]+))*(@){1}[a-z0-9]+[.]{1}(([a-z]{2,3})|([a-z]{2,3}[.]{1}[a-z]{2,3}))$/ # $ Alert
|
||||||
bad10 = /^(([a-z])+.)+[A-Z]([a-z])+$/
|
bad10 = /^(([a-z])+.)+[A-Z]([a-z])+$/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD; attack: "[" + "][".repeat(100) + "]!"
|
# NOT GOOD; attack: "[" + "][".repeat(100) + "]!"
|
||||||
# Adapted from Prototype.js (https://github.com/prototypejs/prototype), which
|
# Adapted from Prototype.js (https://github.com/prototypejs/prototype), which
|
||||||
# is licensed under the MIT license; see file Prototype.js-LICENSE.
|
# is licensed under the MIT license; see file Prototype.js-LICENSE.
|
||||||
bad11 = /(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/
|
bad11 = /(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD; attack: "'" + "\\a".repeat(100) + '"'
|
# NOT GOOD; attack: "'" + "\\a".repeat(100) + '"'
|
||||||
# Adapted from Prism (https://github.com/PrismJS/prism), which is licensed
|
# Adapted from Prism (https://github.com/PrismJS/prism), which is licensed
|
||||||
# under the MIT license; see file Prism-LICENSE.
|
# under the MIT license; see file Prism-LICENSE.
|
||||||
bad12 = /("|')(\\?.)*?\1/
|
bad12 = /("|')(\\?.)*?\1/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad13 = /(b|a?b)*c/
|
bad13 = /(b|a?b)*c/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad15 = /(a|aa?)*b/
|
bad15 = /(a|aa?)*b/ # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
good7 = /(.|\n)*!/
|
good7 = /(.|\n)*!/
|
||||||
|
|
||||||
# NOT GOOD; attack: "\n".repeat(100) + "."
|
# NOT GOOD; attack: "\n".repeat(100) + "."
|
||||||
bad16 = /(.|\n)*!/m
|
bad16 = /(.|\n)*!/m # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
good8 = /([\w.]+)*/
|
good8 = /([\w.]+)*/
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad17 = Regexp.new '(a|aa?)*b'
|
bad17 = Regexp.new '(a|aa?)*b' # $ Alert
|
||||||
|
|
||||||
# GOOD - not used as regexp
|
# GOOD - not used as regexp
|
||||||
good9 = '(a|aa?)*b'
|
good9 = '(a|aa?)*b'
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad18 = /(([\S\s]|[^a])*)"/
|
bad18 = /(([\S\s]|[^a])*)"/ # $ Alert
|
||||||
|
|
||||||
# GOOD - there is no witness in the end that could cause the regexp to not match
|
# GOOD - there is no witness in the end that could cause the regexp to not match
|
||||||
good10 = /([^"']+)*/
|
good10 = /([^"']+)*/
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad20 = /((.|[^a])*)"/
|
bad20 = /((.|[^a])*)"/ # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
good10 = /((a|[^a])*)"/
|
good10 = /((a|[^a])*)"/
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad21 = /((b|[^a])*)"/
|
bad21 = /((b|[^a])*)"/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad22 = /((G|[^a])*)"/
|
bad22 = /((G|[^a])*)"/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad23 = /(([0-9]|[^a])*)"/
|
bad23 = /(([0-9]|[^a])*)"/ # $ Alert
|
||||||
|
|
||||||
# BAD - missing result
|
# BAD - missing result
|
||||||
bad24 = /(?:=(?:([!#\$%&'\*\+\-\.\^_`\|~0-9A-Za-z]+)|"((?:\\[\x00-\x7f]|[^\x00-\x08\x0a-\x1f\x7f"])*)"))?/
|
bad24 = /(?:=(?:([!#\$%&'\*\+\-\.\^_`\|~0-9A-Za-z]+)|"((?:\\[\x00-\x7f]|[^\x00-\x08\x0a-\x1f\x7f"])*)"))?/
|
||||||
@@ -122,55 +122,55 @@ bad25 = /"((?:\\[\x00-\x7f]|[^\x00-\x08\x0a-\x1f\x7f"])*)"/
|
|||||||
bad26 = /"((?:\\[\x00-\x7f]|[^\x00-\x08\x0a-\x1f\x7f"\\])*)"/
|
bad26 = /"((?:\\[\x00-\x7f]|[^\x00-\x08\x0a-\x1f\x7f"\\])*)"/
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad27 = /(([a-z]|[d-h])*)"/
|
bad27 = /(([a-z]|[d-h])*)"/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad27 = /(([^a-z]|[^0-9])*)"/
|
bad27 = /(([^a-z]|[^0-9])*)"/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad28 = /((\d|[0-9])*)"/
|
bad28 = /((\d|[0-9])*)"/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad29 = /((\s|\s)*)"/
|
bad29 = /((\s|\s)*)"/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad30 = /((\w|G)*)"/
|
bad30 = /((\w|G)*)"/ # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
good11 = /((\s|\d)*)"/
|
good11 = /((\s|\d)*)"/
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad31 = /((\d|\w)*)"/
|
bad31 = /((\d|\w)*)"/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad32 = /((\d|5)*)"/
|
bad32 = /((\d|5)*)"/ # $ Alert
|
||||||
|
|
||||||
# BAD - \f is not handled correctly
|
# BAD - \f is not handled correctly
|
||||||
bad33 = /((\s|[\f])*)"/
|
bad33 = /((\s|[\f])*)"/ # $ Alert
|
||||||
|
|
||||||
# BAD - \v is not handled correctly
|
# BAD - \v is not handled correctly
|
||||||
bad34 = /((\s|[\v]|\\v)*)"/
|
bad34 = /((\s|[\v]|\\v)*)"/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad35 = /((\f|[\f])*)"/
|
bad35 = /((\f|[\f])*)"/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad36 = /((\W|\D)*)"/
|
bad36 = /((\W|\D)*)"/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad37 = /((\S|\w)*)"/
|
bad37 = /((\S|\w)*)"/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad38 = /((\S|[\w])*)"/
|
bad38 = /((\S|[\w])*)"/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad39 = /((1s|[\da-z])*)"/
|
bad39 = /((1s|[\da-z])*)"/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad40 = /((0|[\d])*)"/
|
bad40 = /((0|[\d])*)"/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad41 = /(([\d]+)*)"/
|
bad41 = /(([\d]+)*)"/ # $ Alert
|
||||||
|
|
||||||
# GOOD - there is no witness in the end that could cause the regexp to not match
|
# GOOD - there is no witness in the end that could cause the regexp to not match
|
||||||
good12 = /(\d+(X\d+)?)+/
|
good12 = /(\d+(X\d+)?)+/
|
||||||
@@ -182,49 +182,49 @@ good13 = /([0-9]+(X[0-9]*)?)*/
|
|||||||
good15 = /^([^>]+)*(>|$)/
|
good15 = /^([^>]+)*(>|$)/
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad43 = /^([^>a]+)*(>|$)/
|
bad43 = /^([^>a]+)*(>|$)/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad44 = /(\n\s*)+$/
|
bad44 = /(\n\s*)+$/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad45 = /^(?:\s+|#.*|\(\?#[^)]*\))*(?:[?*+]|{\d+(?:,\d*)?})/
|
bad45 = /^(?:\s+|#.*|\(\?#[^)]*\))*(?:[?*+]|{\d+(?:,\d*)?})/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad46 = /\{\[\s*([a-zA-Z]+)\(([a-zA-Z]+)\)((\s*([a-zA-Z]+)\: ?([ a-zA-Z{}]+),?)+)*\s*\]\}/
|
bad46 = /\{\[\s*([a-zA-Z]+)\(([a-zA-Z]+)\)((\s*([a-zA-Z]+)\: ?([ a-zA-Z{}]+),?)+)*\s*\]\}/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad47 = /(a+|b+|c+)*c/
|
bad47 = /(a+|b+|c+)*c/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad48 = /(((a+a?)*)+b+)/
|
bad48 = /(((a+a?)*)+b+)/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad49 = /(a+)+bbbb/
|
bad49 = /(a+)+bbbb/ # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
good16 = /(a+)+aaaaa*a+/
|
good16 = /(a+)+aaaaa*a+/
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad50 = /(a+)+aaaaa$/
|
bad50 = /(a+)+aaaaa$/ # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
good17 = /(\n+)+\n\n/
|
good17 = /(\n+)+\n\n/
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad51 = /(\n+)+\n\n$/
|
bad51 = /(\n+)+\n\n$/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad52 = /([^X]+)*$/
|
bad52 = /([^X]+)*$/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad53 = /(([^X]b)+)*$/
|
bad53 = /(([^X]b)+)*$/ # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
good18 = /(([^X]b)+)*($|[^X]b)/
|
good18 = /(([^X]b)+)*($|[^X]b)/
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad54 = /(([^X]b)+)*($|[^X]c)/
|
bad54 = /(([^X]b)+)*($|[^X]c)/ # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
good20 = /((ab)+)*ababab/
|
good20 = /((ab)+)*ababab/
|
||||||
@@ -236,13 +236,13 @@ good21 = /((ab)+)*abab(ab)*(ab)+/
|
|||||||
good22 = /((ab)+)*/
|
good22 = /((ab)+)*/
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad55 = /((ab)+)*$/
|
bad55 = /((ab)+)*$/ # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
good23 = /((ab)+)*[a1][b1][a2][b2][a3][b3]/
|
good23 = /((ab)+)*[a1][b1][a2][b2][a3][b3]/
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad56 = /([\n\s]+)*(.)/
|
bad56 = /([\n\s]+)*(.)/ # $ Alert
|
||||||
|
|
||||||
# GOOD - any witness passes through the accept state.
|
# GOOD - any witness passes through the accept state.
|
||||||
good24 = /(A*A*X)*/
|
good24 = /(A*A*X)*/
|
||||||
@@ -251,13 +251,13 @@ good24 = /(A*A*X)*/
|
|||||||
good26 = /([^\\\]]+)*/
|
good26 = /([^\\\]]+)*/
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad59 = /(\w*foobarbaz\w*foobarbaz\w*foobarbaz\w*foobarbaz\s*foobarbaz\d*foobarbaz\w*)+-/
|
bad59 = /(\w*foobarbaz\w*foobarbaz\w*foobarbaz\w*foobarbaz\s*foobarbaz\d*foobarbaz\w*)+-/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad60 = /(.thisisagoddamnlongstringforstresstestingthequery|\sthisisagoddamnlongstringforstresstestingthequery)*-/
|
bad60 = /(.thisisagoddamnlongstringforstresstestingthequery|\sthisisagoddamnlongstringforstresstestingthequery)*-/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad61 = /(thisisagoddamnlongstringforstresstestingthequery|this\w+query)*-/
|
bad61 = /(thisisagoddamnlongstringforstresstestingthequery|this\w+query)*-/ # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
good27 = /(thisisagoddamnlongstringforstresstestingthequery|imanotherbutunrelatedstringcomparedtotheotherstring)*-/
|
good27 = /(thisisagoddamnlongstringforstresstestingthequery|imanotherbutunrelatedstringcomparedtotheotherstring)*-/
|
||||||
@@ -269,58 +269,58 @@ good27 = /(thisisagoddamnlongstringforstresstestingthequery|imanotherbutunrelate
|
|||||||
#good29 = /foo((\uDC66|\uDC67)|(\uDC68|\uDC69))*foo/
|
#good29 = /foo((\uDC66|\uDC67)|(\uDC68|\uDC69))*foo/
|
||||||
|
|
||||||
# NOT GOOD (but cannot currently construct a prefix)
|
# NOT GOOD (but cannot currently construct a prefix)
|
||||||
bad62 = /a{2,3}(b+)+X/
|
bad62 = /a{2,3}(b+)+X/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD (and a good prefix test)
|
# NOT GOOD (and a good prefix test)
|
||||||
bad63 = /^<(\w+)((?:\s+\w+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/
|
bad63 = /^<(\w+)((?:\s+\w+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/ # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
good30 = /(a+)*[\S\s][\S\s][\S\s]?/
|
good30 = /(a+)*[\S\s][\S\s][\S\s]?/
|
||||||
|
|
||||||
# GOOD - but we fail to see that repeating the attack string ends in the "accept any" state (due to not parsing the range `[^]{2,3}`).
|
# GOOD - but we fail to see that repeating the attack string ends in the "accept any" state (due to not parsing the range `[^]{2,3}`).
|
||||||
good31 = /(a+)*[\S\s]{2,3}/
|
good31 = /(a+)*[\S\s]{2,3}/ # $ Alert
|
||||||
|
|
||||||
# GOOD - but we spuriously conclude that a rejecting suffix exists (due to not parsing the range `[^]{2,}` when constructing the NFA).
|
# GOOD - but we spuriously conclude that a rejecting suffix exists (due to not parsing the range `[^]{2,}` when constructing the NFA).
|
||||||
good32 = /(a+)*([\S\s]{2,}|X)$/
|
good32 = /(a+)*([\S\s]{2,}|X)$/ # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
good33 = /(a+)*([\S\s]*|X)$/
|
good33 = /(a+)*([\S\s]*|X)$/
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad64 = /((a+)*$|[\S\s]+)/
|
bad64 = /((a+)*$|[\S\s]+)/ # $ Alert
|
||||||
|
|
||||||
# GOOD - but still flagged. The only change compared to the above is the order of alternatives, which we don't model.
|
# GOOD - but still flagged. The only change compared to the above is the order of alternatives, which we don't model.
|
||||||
good34 = /([\S\s]+|(a+)*$)/
|
good34 = /([\S\s]+|(a+)*$)/ # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
good35 = /((;|^)a+)+$/
|
good35 = /((;|^)a+)+$/
|
||||||
|
|
||||||
# NOT GOOD (a good prefix test)
|
# NOT GOOD (a good prefix test)
|
||||||
bad65 = /(^|;)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(e+)+f/
|
bad65 = /(^|;)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(e+)+f/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad66 = /^ab(c+)+$/
|
bad66 = /^ab(c+)+$/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad67 = /(\d(\s+)*){20}/
|
bad67 = /(\d(\s+)*){20}/ # $ Alert
|
||||||
|
|
||||||
# GOOD - but we spuriously conclude that a rejecting suffix exists.
|
# GOOD - but we spuriously conclude that a rejecting suffix exists.
|
||||||
good36 = /(([^\/]|X)+)(\/[\S\s]*)*$/
|
good36 = /(([^\/]|X)+)(\/[\S\s]*)*$/ # $ Alert
|
||||||
|
|
||||||
# GOOD - but we spuriously conclude that a rejecting suffix exists.
|
# GOOD - but we spuriously conclude that a rejecting suffix exists.
|
||||||
good37 = /^((x([^Y]+)?)*(Y|$))/
|
good37 = /^((x([^Y]+)?)*(Y|$))/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad68 = /(a*)+b/
|
bad68 = /(a*)+b/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad69 = /foo([\w-]*)+bar/
|
bad69 = /foo([\w-]*)+bar/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad70 = /((ab)*)+c/
|
bad70 = /((ab)*)+c/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad71 = /(a?a?)*b/
|
bad71 = /(a?a?)*b/ # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
good38 = /(a?)*b/
|
good38 = /(a?)*b/
|
||||||
@@ -329,54 +329,54 @@ good38 = /(a?)*b/
|
|||||||
bad72 = /(c?a?)*b/
|
bad72 = /(c?a?)*b/
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad73 = /(?:a|a?)+b/
|
bad73 = /(?:a|a?)+b/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD - but not detected.
|
# NOT GOOD - but not detected.
|
||||||
bad74 = /(a?b?)*$/
|
bad74 = /(a?b?)*$/
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad76 = /PRE(([a-c]|[c-d])T(e?e?e?e?|X))+(cTcT|cTXcTX$)/
|
bad76 = /PRE(([a-c]|[c-d])T(e?e?e?e?|X))+(cTcT|cTXcTX$)/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD - but not detected
|
# NOT GOOD - but not detected
|
||||||
bad77 = /^((a)+\w)+$/
|
bad77 = /^((a)+\w)+$/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad78 = /^(b+.)+$/
|
bad78 = /^(b+.)+$/ # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
good39 = /a*b/
|
good39 = /a*b/
|
||||||
|
|
||||||
# All 4 bad combinations of nested * and +
|
# All 4 bad combinations of nested * and +
|
||||||
bad79 = /(a*)*b/
|
bad79 = /(a*)*b/ # $ Alert
|
||||||
bad80 = /(a+)*b/
|
bad80 = /(a+)*b/ # $ Alert
|
||||||
bad81 = /(a*)+b/
|
bad81 = /(a*)+b/ # $ Alert
|
||||||
bad82 = /(a+)+b/
|
bad82 = /(a+)+b/ # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
good40 = /(a|b)+/
|
good40 = /(a|b)+/
|
||||||
good41 = /(?:[\s;,"'<>(){}|\[\]@=+*]|:(?![\/\\]))+/
|
good41 = /(?:[\s;,"'<>(){}|\[\]@=+*]|:(?![\/\\]))+/
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad83 = /^((?:a{|-)|\w\{)+X$/
|
bad83 = /^((?:a{|-)|\w\{)+X$/ # $ Alert
|
||||||
bad84 = /^((?:a{0|-)|\w\{\d)+X$/
|
bad84 = /^((?:a{0|-)|\w\{\d)+X$/ # $ Alert
|
||||||
bad85 = /^((?:a{0,|-)|\w\{\d,)+X$/
|
bad85 = /^((?:a{0,|-)|\w\{\d,)+X$/ # $ Alert
|
||||||
bad86 = /^((?:a{0,2|-)|\w\{\d,\d)+X$/
|
bad86 = /^((?:a{0,2|-)|\w\{\d,\d)+X$/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad87 = /^((?:a{0,2}|-)|\w\{\d,\d\})+X$/
|
bad87 = /^((?:a{0,2}|-)|\w\{\d,\d\})+X$/
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad88 = /^X(\u0061|a)*Y$/
|
bad88 = /^X(\u0061|a)*Y$/ # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
good43 = /^X(\u0061|b)+Y$/
|
good43 = /^X(\u0061|b)+Y$/
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad88 = /X([[:digit:]]|\d)+Y/
|
bad88 = /X([[:digit:]]|\d)+Y/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD
|
# NOT GOOD
|
||||||
bad89 = /\G(a|\w)*$/
|
bad89 = /\G(a|\w)*$/ # $ Alert
|
||||||
bad90 = /\b(a|\w)*$/
|
bad90 = /\b(a|\w)*$/ # $ Alert
|
||||||
|
|
||||||
# NOT GOOD; attack: "0".repeat(30) + "!"
|
# NOT GOOD; attack: "0".repeat(30) + "!"
|
||||||
# Adapated from addressable (https://github.com/sporkmonger/addressable)
|
# Adapated from addressable (https://github.com/sporkmonger/addressable)
|
||||||
@@ -387,5 +387,5 @@ module Bad91
|
|||||||
var_char_class = ALPHA + DIGIT + '_'
|
var_char_class = ALPHA + DIGIT + '_'
|
||||||
var_char = "(?:(?:[#{var_char_class}]|%[a-fA-F0-9][a-fA-F0-9])+)"
|
var_char = "(?:(?:[#{var_char_class}]|%[a-fA-F0-9][a-fA-F0-9])+)"
|
||||||
var = "(?:#{var_char}(?:\\.?#{var_char})*)"
|
var = "(?:#{var_char}(?:\\.?#{var_char})*)"
|
||||||
bad91 = /^#{var}$/
|
bad91 = /^#{var}$/ # $ Alert
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-1333/PolynomialReDoS.ql
|
query: queries/security/cwe-1333/PolynomialReDoS.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -1,35 +1,35 @@
|
|||||||
class FooController < ActionController::Base
|
class FooController < ActionController::Base
|
||||||
def some_request_handler
|
def some_request_handler
|
||||||
# A source for the data-flow query (i.e. a remote flow source)
|
# A source for the data-flow query (i.e. a remote flow source)
|
||||||
name = params[:name]
|
name = params[:name] # $ Source
|
||||||
|
|
||||||
# A vulnerable regex
|
# A vulnerable regex
|
||||||
regex = /^\s+|\s+$/
|
regex = /^\s+|\s+$/
|
||||||
|
|
||||||
# Various sinks that match the source against the regex
|
# Various sinks that match the source against the regex
|
||||||
name =~ regex # NOT GOOD
|
name =~ regex # $ Alert // NOT GOOD
|
||||||
name !~ regex # NOT GOOD
|
name !~ regex # $ Alert // NOT GOOD
|
||||||
name[regex] # NOT GOOD
|
name[regex] # $ Alert // NOT GOOD
|
||||||
name.gsub regex, '' # NOT GOOD
|
name.gsub regex, '' # $ Alert // NOT GOOD
|
||||||
name.index regex # NOT GOOD
|
name.index regex # $ Alert // NOT GOOD
|
||||||
name.match regex # NOT GOOD
|
name.match regex # $ Alert // NOT GOOD
|
||||||
name.match? regex # NOT GOOD
|
name.match? regex # $ Alert // NOT GOOD
|
||||||
name.partition regex # NOT GOOD
|
name.partition regex # $ Alert // NOT GOOD
|
||||||
name.rindex regex # NOT GOOD
|
name.rindex regex # $ Alert // NOT GOOD
|
||||||
name.rpartition regex # NOT GOOD
|
name.rpartition regex # $ Alert // NOT GOOD
|
||||||
name.scan regex # NOT GOOD
|
name.scan regex # $ Alert // NOT GOOD
|
||||||
name.split regex # NOT GOOD
|
name.split regex # $ Alert // NOT GOOD
|
||||||
name.sub regex, '' # NOT GOOD
|
name.sub regex, '' # $ Alert // NOT GOOD
|
||||||
regex.match name # NOT GOOD
|
regex.match name # $ Alert // NOT GOOD
|
||||||
regex.match? name # NOT GOOD
|
regex.match? name # $ Alert // NOT GOOD
|
||||||
|
|
||||||
# Destructive variants
|
# Destructive variants
|
||||||
a = params[:b]
|
a = params[:b] # $ Source
|
||||||
a.gsub! regex, '' # NOT GOOD
|
a.gsub! regex, '' # $ Alert // NOT GOOD
|
||||||
b = params[:a]
|
b = params[:a] # $ Source
|
||||||
b.slice! regex # NOT GOOD
|
b.slice! regex # $ Alert // NOT GOOD
|
||||||
c = params[:c]
|
c = params[:c] # $ Source
|
||||||
c.sub! regex, '' # NOT GOOD
|
c.sub! regex, '' # $ Alert // NOT GOOD
|
||||||
|
|
||||||
# GOOD - guarded by a string length check
|
# GOOD - guarded by a string length check
|
||||||
if name.length < 1024
|
if name.length < 1024
|
||||||
@@ -39,19 +39,19 @@ class FooController < ActionController::Base
|
|||||||
# GOOD - regex does not suffer from polynomial backtracking (regression test)
|
# GOOD - regex does not suffer from polynomial backtracking (regression test)
|
||||||
params[:foo] =~ /\A[bc].*\Z/
|
params[:foo] =~ /\A[bc].*\Z/
|
||||||
|
|
||||||
case name # NOT GOOD
|
case name # $ Sink // NOT GOOD
|
||||||
when regex
|
when regex
|
||||||
puts "foo"
|
puts "foo"
|
||||||
end
|
end # $ Alert
|
||||||
|
|
||||||
case name # NOT GOOD
|
case name # $ Sink // NOT GOOD
|
||||||
in /^\s+|\s+$/ then
|
in /^\s+|\s+$/ then
|
||||||
puts "foo"
|
puts "foo"
|
||||||
end
|
end # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
def some_other_request_handle
|
def some_other_request_handle
|
||||||
name = params[:name] # source
|
name = params[:name] # $ Source // source
|
||||||
|
|
||||||
indirect_use_of_reg /^\s+|\s+$/, name
|
indirect_use_of_reg /^\s+|\s+$/, name
|
||||||
|
|
||||||
@@ -59,22 +59,22 @@ class FooController < ActionController::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def indirect_use_of_reg (reg, input)
|
def indirect_use_of_reg (reg, input)
|
||||||
input.gsub reg, '' # NOT GOOD
|
input.gsub reg, '' # $ Alert // NOT GOOD
|
||||||
end
|
end
|
||||||
|
|
||||||
def as_string_indirect (reg_as_string, input)
|
def as_string_indirect (reg_as_string, input)
|
||||||
input.match? reg_as_string, '' # NOT GOOD
|
input.match? reg_as_string, '' # $ Alert // NOT GOOD
|
||||||
end
|
end
|
||||||
|
|
||||||
def re_compile_indirect
|
def re_compile_indirect
|
||||||
name = params[:name] # source
|
name = params[:name] # $ Source // source
|
||||||
|
|
||||||
reg = Regexp.new '^\s+|\s+$'
|
reg = Regexp.new '^\s+|\s+$'
|
||||||
re_compile_indirect_2 reg, name
|
re_compile_indirect_2 reg, name
|
||||||
end
|
end
|
||||||
|
|
||||||
def re_compile_indirect_2 (reg, input)
|
def re_compile_indirect_2 (reg, input)
|
||||||
input.gsub reg, '' # NOT GOOD
|
input.gsub reg, '' # $ Alert // NOT GOOD
|
||||||
end
|
end
|
||||||
|
|
||||||
# See https://github.com/dependabot/dependabot-core/blob/37dc1767fde9b7184020763f4d0c1434f93d11d6/python/lib/dependabot/python/requirement_parser.rb#L6-L25
|
# See https://github.com/dependabot/dependabot-core/blob/37dc1767fde9b7184020763f4d0c1434f93d11d6/python/lib/dependabot/python/requirement_parser.rb#L6-L25
|
||||||
@@ -100,8 +100,8 @@ class FooController < ActionController::Base
|
|||||||
MARKER_EXPR = /(#{MARKER_EXPR_ONE}|\(\s*|\s*\)|\s+and\s+|\s+or\s+)+/
|
MARKER_EXPR = /(#{MARKER_EXPR_ONE}|\(\s*|\s*\)|\s+and\s+|\s+or\s+)+/
|
||||||
|
|
||||||
def use_marker_expr
|
def use_marker_expr
|
||||||
name = params[:name] # source
|
name = params[:name] # $ Source // source
|
||||||
|
|
||||||
name =~ MARKER_EXPR
|
name =~ MARKER_EXPR # $ Alert
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
module Foo
|
module Foo
|
||||||
def bar(x)
|
def bar(x) # $ Source
|
||||||
# Run the /a+$/ regex on the input x.
|
# Run the /a+$/ regex on the input x.
|
||||||
match = x.match(/a+$/)
|
match = x.match(/a+$/) # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
def baz(x)
|
def baz(x) # $ Source
|
||||||
match = x.match(/a+$/)
|
match = x.match(/a+$/) # $ Alert
|
||||||
|
|
||||||
match2 = x.match(/(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)C.*Y$/)
|
match2 = x.match(/(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)C.*Y$/) # $ Alert
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-1333/RegExpInjection.ql
|
query: queries/security/cwe-1333/RegExpInjection.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
class FooController < ActionController::Base
|
class FooController < ActionController::Base
|
||||||
# BAD
|
# BAD
|
||||||
def route0
|
def route0
|
||||||
name = params[:name]
|
name = params[:name] # $ Source
|
||||||
regex = /#{name}/
|
regex = /#{name}/ # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
def route1
|
def route1
|
||||||
name = params[:name]
|
name = params[:name] # $ Source
|
||||||
regex = /foo#{name}bar/
|
regex = /foo#{name}bar/ # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
def route2
|
def route2
|
||||||
name = params[:name]
|
name = params[:name] # $ Source
|
||||||
regex = Regexp.new(name)
|
regex = Regexp.new(name) # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
def route3
|
def route3
|
||||||
name = params[:name]
|
name = params[:name] # $ Source
|
||||||
regex = Regexp.new("@" + name)
|
regex = Regexp.new("@" + name) # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
# GOOD - string is compared against a constant string
|
# GOOD - string is compared against a constant string
|
||||||
@@ -51,7 +51,7 @@ class FooController < ActionController::Base
|
|||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
def route8
|
def route8
|
||||||
name = params[:name]
|
name = params[:name] # $ Source
|
||||||
regex = Regexp.compile("@" + name)
|
regex = Regexp.compile("@" + name) # $ Alert
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-134/TaintedFormatString.ql
|
query: queries/security/cwe-134/TaintedFormatString.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -1,44 +1,44 @@
|
|||||||
class UsersController < ActionController::Base
|
class UsersController < ActionController::Base
|
||||||
|
|
||||||
def show
|
def show
|
||||||
printf(params[:format], arg) # BAD
|
printf(params[:format], arg) # $ Alert // BAD
|
||||||
Kernel.printf(params[:format], arg) # BAD
|
Kernel.printf(params[:format], arg) # $ Alert // BAD
|
||||||
|
|
||||||
printf(params[:format]) # GOOD
|
printf(params[:format]) # GOOD
|
||||||
Kernel.printf(params[:format]) # GOOD
|
Kernel.printf(params[:format]) # GOOD
|
||||||
|
|
||||||
printf(IO.new(1), params[:format], arg) # BAD
|
printf(IO.new(1), params[:format], arg) # $ Alert // BAD
|
||||||
Kernel.printf(IO.new(1), params[:format], arg) # BAD
|
Kernel.printf(IO.new(1), params[:format], arg) # $ Alert // BAD
|
||||||
|
|
||||||
printf("%s", params[:format]) # GOOD
|
printf("%s", params[:format]) # GOOD
|
||||||
Kernel.printf("%s", params[:format]) # GOOD
|
Kernel.printf("%s", params[:format]) # GOOD
|
||||||
fmt = "%s"
|
fmt = "%s"
|
||||||
printf(fmt, params[:format]) # GOOD
|
printf(fmt, params[:format]) # GOOD
|
||||||
|
|
||||||
printf(IO.new(1), params[:format]) # GOOD [FALSE POSITIVE]
|
printf(IO.new(1), params[:format]) # $ Alert // GOOD [FALSE POSITIVE]
|
||||||
Kernel.printf(IO.new(1), params[:format]) # GOOD [FALSE POSITIVE]
|
Kernel.printf(IO.new(1), params[:format]) # $ Alert // GOOD [FALSE POSITIVE]
|
||||||
|
|
||||||
str1 = Kernel.sprintf(params[:format], arg) # BAD
|
str1 = Kernel.sprintf(params[:format], arg) # $ Alert // BAD
|
||||||
str2 = sprintf(params[:format], arg) # BAD
|
str2 = sprintf(params[:format], arg) # $ Alert // BAD
|
||||||
|
|
||||||
str1 = Kernel.sprintf(params[:format]) # GOOD
|
str1 = Kernel.sprintf(params[:format]) # GOOD
|
||||||
str2 = sprintf(params[:format]) # GOOD
|
str2 = sprintf(params[:format]) # GOOD
|
||||||
|
|
||||||
stdout = IO.new 1
|
stdout = IO.new 1
|
||||||
stdout.printf(params[:format], arg) # BAD
|
stdout.printf(params[:format], arg) # $ Alert // BAD
|
||||||
|
|
||||||
stdout.printf(params[:format]) # GOOD
|
stdout.printf(params[:format]) # GOOD
|
||||||
|
|
||||||
# Taint via string concatenation
|
# Taint via string concatenation
|
||||||
printf("A log message: " + params[:format], arg) # BAD
|
printf("A log message: " + params[:format], arg) # $ Alert // BAD
|
||||||
|
|
||||||
# Taint via string interpolation
|
# Taint via string interpolation
|
||||||
printf("A log message: #{params[:format]}", arg) # BAD
|
printf("A log message: #{params[:format]}", arg) # $ Alert // BAD
|
||||||
|
|
||||||
# Using String#
|
# Using String#
|
||||||
"A log message #{params[:format]} %{foo}" % {foo: "foo"} # BAD
|
"A log message #{params[:format]} %{foo}" % {foo: "foo"} # $ Alert // BAD
|
||||||
|
|
||||||
# String# with an array
|
# String# with an array
|
||||||
"A log message #{params[:format]} %08x" % ["foo"] # BAD
|
"A log message #{params[:format]} %08x" % ["foo"] # $ Alert // BAD
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-209/StackTraceExposure.ql
|
query: queries/security/cwe-209/StackTraceExposure.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -3,19 +3,19 @@ class FooController < ApplicationController
|
|||||||
def show
|
def show
|
||||||
something_that_might_fail()
|
something_that_might_fail()
|
||||||
rescue => e
|
rescue => e
|
||||||
render body: e.backtrace, content_type: "text/plain"
|
render body: e.backtrace, content_type: "text/plain" # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def show2
|
def show2
|
||||||
bt = caller()
|
bt = caller() # $ Source
|
||||||
render body: bt, content_type: "text/plain"
|
render body: bt, content_type: "text/plain" # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
def show3
|
def show3
|
||||||
not_a_method()
|
not_a_method()
|
||||||
rescue NoMethodError => e
|
rescue NoMethodError => e
|
||||||
render body: e.backtrace, content_type: "text/plain"
|
render body: e.backtrace, content_type: "text/plain" # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3,31 +3,31 @@ require "excon"
|
|||||||
def method1
|
def method1
|
||||||
# BAD
|
# BAD
|
||||||
Excon.defaults[:ssl_verify_peer] = false
|
Excon.defaults[:ssl_verify_peer] = false
|
||||||
Excon.get("http://example.com/")
|
Excon.get("http://example.com/") # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
def method2
|
def method2
|
||||||
# BAD
|
# BAD
|
||||||
Excon.ssl_verify_peer = false
|
Excon.ssl_verify_peer = false
|
||||||
Excon.get("http://example.com/")
|
Excon.get("http://example.com/") # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
def method3(secure)
|
def method3(secure)
|
||||||
# BAD
|
# BAD
|
||||||
Excon.defaults[:ssl_verify_peer] = (secure ? true : false)
|
Excon.defaults[:ssl_verify_peer] = (secure ? true : false)
|
||||||
Excon.get("http://example.com/")
|
Excon.get("http://example.com/") # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
def method4
|
def method4
|
||||||
# BAD
|
# BAD
|
||||||
conn = Excon::Connection.new("http://example.com/", ssl_verify_peer: false)
|
conn = Excon::Connection.new("http://example.com/", ssl_verify_peer: false)
|
||||||
conn.get
|
conn.get # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
def method5
|
def method5
|
||||||
# BAD
|
# BAD
|
||||||
Excon.ssl_verify_peer = true
|
Excon.ssl_verify_peer = true
|
||||||
Excon.new("http://example.com/", ssl_verify_peer: false).get
|
Excon.new("http://example.com/", ssl_verify_peer: false).get # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
def method6
|
def method6
|
||||||
@@ -65,4 +65,4 @@ def method10
|
|||||||
# GOOD
|
# GOOD
|
||||||
connection = Excon.new("foo")
|
connection = Excon.new("foo")
|
||||||
connection.get("bar")
|
connection.get("bar")
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ require "faraday"
|
|||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
connection = Faraday.new("http://example.com", ssl: { verify: false })
|
connection = Faraday.new("http://example.com", ssl: { verify: false })
|
||||||
response = connection.get("/")
|
response = connection.get("/") # $ Alert
|
||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
connection = Faraday.new("http://example.com", ssl: { verify_mode: OpenSSL::SSL::VERIFY_NONE })
|
connection = Faraday.new("http://example.com", ssl: { verify_mode: OpenSSL::SSL::VERIFY_NONE })
|
||||||
response = connection.get("/")
|
response = connection.get("/") # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
connection = Faraday.new("http://example.com")
|
connection = Faraday.new("http://example.com")
|
||||||
@@ -32,7 +32,7 @@ response = connection.get("/")
|
|||||||
def verify_as_arg(host, path, arg)
|
def verify_as_arg(host, path, arg)
|
||||||
# BAD, due to the call below
|
# BAD, due to the call below
|
||||||
connection = Faraday.new(host, ssl: { verify: arg })
|
connection = Faraday.new(host, ssl: { verify: arg })
|
||||||
response = connection.get(path)
|
response = connection.get(path) # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
verify_as_arg("http://example.com", "/", false)
|
verify_as_arg("http://example.com", "/", false)
|
||||||
@@ -41,7 +41,7 @@ verify_as_arg("http://example.com", "/", false)
|
|||||||
def verify_mode_as_arg(host, path, arg)
|
def verify_mode_as_arg(host, path, arg)
|
||||||
# BAD, due to the call below
|
# BAD, due to the call below
|
||||||
connection = Faraday.new(host, ssl: { verify_mode: arg })
|
connection = Faraday.new(host, ssl: { verify_mode: arg })
|
||||||
response = connection.get(path)
|
response = connection.get(path) # $ Alert
|
||||||
end
|
end
|
||||||
|
|
||||||
verify_mode_as_arg("http://example.com", "/", OpenSSL::SSL::VERIFY_NONE)
|
verify_mode_as_arg("http://example.com", "/", OpenSSL::SSL::VERIFY_NONE)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ require "httpclient"
|
|||||||
# BAD
|
# BAD
|
||||||
client = HTTPClient.new
|
client = HTTPClient.new
|
||||||
client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
||||||
client.get("https://example.com")
|
client.get("https://example.com") # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
client = HTTPClient.new
|
client = HTTPClient.new
|
||||||
@@ -15,4 +15,4 @@ client = HTTPClient.new
|
|||||||
client.get("https://example.com")
|
client.get("https://example.com")
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
HTTPClient.get("https://example.com/")
|
HTTPClient.get("https://example.com/")
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
require "httparty"
|
require "httparty"
|
||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
HTTParty.get("http://example.com/", verify: false)
|
HTTParty.get("http://example.com/", verify: false) # $ Alert
|
||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
HTTParty.get("http://example.com/", verify_peer: false)
|
HTTParty.get("http://example.com/", verify_peer: false) # $ Alert
|
||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
HTTParty.get("http://example.com/", { verify_peer: false })
|
HTTParty.get("http://example.com/", { verify_peer: false }) # $ Alert
|
||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
HTTParty.post("http://example.com/", body: "some_data", verify: false)
|
HTTParty.post("http://example.com/", body: "some_data", verify: false) # $ Alert
|
||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
HTTParty.post("http://example.com/", { body: "some_data", verify: false })
|
HTTParty.post("http://example.com/", { body: "some_data", verify: false }) # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
HTTParty.get("http://example.com/")
|
HTTParty.get("http://example.com/")
|
||||||
@@ -34,4 +34,4 @@ HTTParty.post("http://example.com/", body: "some_data", verify: true)
|
|||||||
HTTParty.post("http://example.com/", { body: "some_data" })
|
HTTParty.post("http://example.com/", { body: "some_data" })
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
HTTParty.post("http://example.com/", { body: "some_data", verify: true })
|
HTTParty.post("http://example.com/", { body: "some_data", verify: true })
|
||||||
|
|||||||
@@ -6,5 +6,5 @@ http = Net::HTTP.new uri.host, uri.port
|
|||||||
http.use_ssl = true
|
http.use_ssl = true
|
||||||
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
||||||
request = Net::HTTP::Get.new uri.request_uri
|
request = Net::HTTP::Get.new uri.request_uri
|
||||||
response = http.request request
|
response = http.request request # $ Alert
|
||||||
puts response.body
|
puts response.body
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
require "open-uri"
|
require "open-uri"
|
||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
Kernel.open("https://example.com", ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE)
|
Kernel.open("https://example.com", ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE) # $ Alert
|
||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
Kernel.open("https://example.com", { ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE })
|
Kernel.open("https://example.com", { ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE }) # $ Alert
|
||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
options = { ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE }
|
options = { ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE }
|
||||||
Kernel.open("https://example.com", options)
|
Kernel.open("https://example.com", options) # $ Alert
|
||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
URI.parse("https://example.com").open(ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE)
|
URI.parse("https://example.com").open(ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE) # $ Alert
|
||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
URI.parse("https://example.com").open({ ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE })
|
URI.parse("https://example.com").open({ ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE }) # $ Alert
|
||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
options = { ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE }
|
options = { ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE }
|
||||||
URI.parse("https://example.com").open(options)
|
URI.parse("https://example.com").open(options) # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
Kernel.open("https://example.com")
|
Kernel.open("https://example.com")
|
||||||
@@ -44,4 +44,4 @@ URI.parse("https://example.com").open({ ssl_verify_mode: OpenSSL::SSL::VERIFY_PE
|
|||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
options = { ssl_verify_mode: OpenSSL::SSL::VERIFY_PEER }
|
options = { ssl_verify_mode: OpenSSL::SSL::VERIFY_PEER }
|
||||||
URI.parse("https://example.com").open(options)
|
URI.parse("https://example.com").open(options)
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-295/RequestWithoutValidation.ql
|
query: queries/security/cwe-295/RequestWithoutValidation.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -2,21 +2,21 @@ require "rest-client"
|
|||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
resource = RestClient::Resource.new("https://example.com", verify_ssl: OpenSSL::SSL::VERIFY_NONE)
|
resource = RestClient::Resource.new("https://example.com", verify_ssl: OpenSSL::SSL::VERIFY_NONE)
|
||||||
response = resource.get
|
response = resource.get # $ Alert
|
||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
resource = RestClient::Resource.new("https://example.com", { verify_ssl: OpenSSL::SSL::VERIFY_NONE })
|
resource = RestClient::Resource.new("https://example.com", { verify_ssl: OpenSSL::SSL::VERIFY_NONE })
|
||||||
response = resource.get
|
response = resource.get # $ Alert
|
||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
options = { verify_ssl: OpenSSL::SSL::VERIFY_NONE }
|
options = { verify_ssl: OpenSSL::SSL::VERIFY_NONE }
|
||||||
resource = RestClient::Resource.new("https://example.com", options)
|
resource = RestClient::Resource.new("https://example.com", options)
|
||||||
response = resource.get
|
response = resource.get # $ Alert
|
||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
value = OpenSSL::SSL::VERIFY_NONE
|
value = OpenSSL::SSL::VERIFY_NONE
|
||||||
resource = RestClient::Resource.new("https://example.com", verify_ssl: value)
|
resource = RestClient::Resource.new("https://example.com", verify_ssl: value)
|
||||||
response = resource.get
|
response = resource.get # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
RestClient.get("https://example.com")
|
RestClient.get("https://example.com")
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
require "typhoeus"
|
require "typhoeus"
|
||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
Typhoeus.get("https://www.example.com", ssl_verifypeer: false)
|
Typhoeus.get("https://www.example.com", ssl_verifypeer: false) # $ Alert
|
||||||
|
|
||||||
# BAD
|
# BAD
|
||||||
post_options = { body: "some data", ssl_verifypeer: false }
|
post_options = { body: "some data", ssl_verifypeer: false }
|
||||||
Typhoeus.post("https://www.example.com", post_options)
|
Typhoeus.post("https://www.example.com", post_options) # $ Alert
|
||||||
|
|
||||||
# GOOD
|
# GOOD
|
||||||
Typhoeus.get("https://www.example.com")
|
Typhoeus.get("https://www.example.com")
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-312/CleartextLogging.ql
|
query: queries/security/cwe-312/CleartextLogging.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
queries/security/cwe-312/CleartextStorage.ql
|
query: queries/security/cwe-312/CleartextStorage.ql
|
||||||
|
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user