Ruby: Post-processing query for inline test expectations

This commit is contained in:
Tom Hvitved
2024-09-23 09:47:56 +02:00
parent e2b614d18a
commit 5b5ca05e87
5 changed files with 76 additions and 54 deletions

View File

@@ -0,0 +1,21 @@
/**
* @kind test-postprocess
*/
private import ruby
private import codeql.util.test.InlineExpectationsTest as T
private import internal.InlineExpectationsTestImpl
import T::TestPostProcessing
import T::TestPostProcessing::Make<Impl, Input>
private module Input implements T::TestPostProcessing::InputSig<Impl> {
string getRelativeUrl(Location location) {
exists(File f, int startline, int startcolumn, int endline, int endcolumn |
location.hasLocationInfo(_, startline, startcolumn, endline, endcolumn) and
f = location.getFile()
|
result =
f.getRelativePath() + ":" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn
)
}
}

View File

@@ -2,17 +2,17 @@ class TestContoller < ActionController::Base
# this is vulnerable
def upload
untar params[:file], params[:filename]
untar params[:file], params[:filename] # $ Source=upload
end
# this is vulnerable
def unpload_zip
unzip params[:file]
unzip params[:file] # $ Source=upload_zip
end
# this is vulnerable
def create_new_zip
zip params[:filename], files
zip params[:filename], files # $ Source=create_new_zip
end
# these are not vulnerable because of the string compare sanitizer
@@ -56,7 +56,7 @@ class TestContoller < ActionController::Base
else
destination_directory = File.dirname(destination_file)
FileUtils.mkdir_p destination_directory unless File.directory?(destination_directory)
File.open destination_file, "wb" do |f|
File.open destination_file, "wb" do |f| # $ Alert=upload
f.print tarfile.read
end
end
@@ -65,7 +65,7 @@ class TestContoller < ActionController::Base
end
def unzip(file)
Zip::File.open(file) do |zip_file|
Zip::File.open(file) do |zip_file| # $ Alert=upload_zip
zip_file.each do |entry|
entry.extract
end
@@ -73,7 +73,7 @@ class TestContoller < ActionController::Base
end
def zip(filename, files = [])
Zip::File.new(filename) do |zf|
Zip::File.new(filename) do |zf| # $ Alert=create_new_zip
files.each do |f|
zf.add f
end

View File

@@ -1,3 +1,22 @@
#select
| ArchiveApiPathTraversal.rb:59:21:59:36 | destination_file | ArchiveApiPathTraversal.rb:5:26:5:31 | call to params | ArchiveApiPathTraversal.rb:59:21:59:36 | destination_file | This path depends on a $@. | ArchiveApiPathTraversal.rb:5:26:5:31 | call to params | user-provided value |
| ArchiveApiPathTraversal.rb:68:20:68:23 | file | ArchiveApiPathTraversal.rb:10:11:10:16 | call to params | ArchiveApiPathTraversal.rb:68:20:68:23 | file | This path depends on a $@. | ArchiveApiPathTraversal.rb:10:11:10:16 | call to params | user-provided value |
| ArchiveApiPathTraversal.rb:76:19:76:26 | filename | ArchiveApiPathTraversal.rb:15:9:15:14 | call to params | ArchiveApiPathTraversal.rb:76:19:76:26 | filename | This path depends on a $@. | ArchiveApiPathTraversal.rb:15:9:15:14 | call to params | user-provided value |
| tainted_path.rb:5:26:5:29 | path | tainted_path.rb:4:12:4:17 | call to params | tainted_path.rb:5:26:5:29 | path | This path depends on a $@. | tainted_path.rb:4:12:4:17 | call to params | user-provided value |
| tainted_path.rb:11:26:11:29 | path | tainted_path.rb:10:31:10:36 | call to params | tainted_path.rb:11:26:11:29 | path | This path depends on a $@. | tainted_path.rb:10:31:10:36 | call to params | user-provided value |
| tainted_path.rb:17:26:17:29 | path | tainted_path.rb:16:28:16:33 | call to params | tainted_path.rb:17:26:17:29 | path | This path depends on a $@. | tainted_path.rb:16:28:16:33 | call to params | user-provided value |
| tainted_path.rb:23:26:23:29 | path | tainted_path.rb:22:29:22:34 | call to params | tainted_path.rb:23:26:23:29 | path | This path depends on a $@. | tainted_path.rb:22:29:22:34 | call to params | user-provided value |
| tainted_path.rb:29:26:29:29 | path | tainted_path.rb:28:22:28:27 | call to params | tainted_path.rb:29:26:29:29 | path | This path depends on a $@. | tainted_path.rb:28:22:28:27 | call to params | user-provided value |
| tainted_path.rb:35:26:35:29 | path | tainted_path.rb:34:29:34:34 | call to params | tainted_path.rb:35:26:35:29 | path | This path depends on a $@. | tainted_path.rb:34:29:34:34 | call to params | user-provided value |
| tainted_path.rb:41:26:41:29 | path | tainted_path.rb:40:26:40:31 | call to params | tainted_path.rb:41:26:41:29 | path | This path depends on a $@. | tainted_path.rb:40:26:40:31 | call to params | user-provided value |
| tainted_path.rb:48:26:48:29 | path | tainted_path.rb:47:43:47:48 | call to params | tainted_path.rb:48:26:48:29 | path | This path depends on a $@. | tainted_path.rb:47:43:47:48 | call to params | user-provided value |
| tainted_path.rb:60:26:60:29 | path | tainted_path.rb:59:40:59:45 | call to params | tainted_path.rb:60:26:60:29 | path | This path depends on a $@. | tainted_path.rb:59:40:59:45 | call to params | user-provided value |
| tainted_path.rb:72:15:72:18 | path | tainted_path.rb:71:40:71:45 | call to params | tainted_path.rb:72:15:72:18 | path | This path depends on a $@. | tainted_path.rb:71:40:71:45 | call to params | user-provided value |
| tainted_path.rb:78:19:78:22 | path | tainted_path.rb:77:40:77:45 | call to params | tainted_path.rb:78:19:78:22 | path | This path depends on a $@. | tainted_path.rb:77:40:77:45 | call to params | user-provided value |
| tainted_path.rb:79:14:79:17 | path | tainted_path.rb:77:40:77:45 | call to params | tainted_path.rb:79:14:79:17 | path | This path depends on a $@. | tainted_path.rb:77:40:77:45 | call to params | user-provided value |
| tainted_path.rb:85:10:85:13 | path | tainted_path.rb:84:40:84:45 | call to params | tainted_path.rb:85:10:85:13 | path | This path depends on a $@. | tainted_path.rb:84:40:84:45 | call to params | user-provided value |
| tainted_path.rb:86:25:86:28 | path | tainted_path.rb:84:40:84:45 | call to params | tainted_path.rb:86:25:86:28 | path | This path depends on a $@. | tainted_path.rb:84:40:84:45 | call to params | user-provided value |
| tainted_path.rb:92:11:92:14 | path | tainted_path.rb:90:40:90:45 | call to params | tainted_path.rb:92:11:92:14 | path | This path depends on a $@. | tainted_path.rb:90:40:90:45 | call to params | user-provided value |
edges
| ArchiveApiPathTraversal.rb:5:26:5:31 | call to params | ArchiveApiPathTraversal.rb:5:26:5:42 | ...[...] | provenance | |
| ArchiveApiPathTraversal.rb:5:26:5:42 | ...[...] | ArchiveApiPathTraversal.rb:49:17:49:27 | destination | provenance | |
@@ -152,22 +171,3 @@ nodes
| tainted_path.rb:90:40:90:52 | ...[...] | semmle.label | ...[...] |
| tainted_path.rb:92:11:92:14 | path | semmle.label | path |
subpaths
#select
| ArchiveApiPathTraversal.rb:59:21:59:36 | destination_file | ArchiveApiPathTraversal.rb:5:26:5:31 | call to params | ArchiveApiPathTraversal.rb:59:21:59:36 | destination_file | This path depends on a $@. | ArchiveApiPathTraversal.rb:5:26:5:31 | call to params | user-provided value |
| ArchiveApiPathTraversal.rb:68:20:68:23 | file | ArchiveApiPathTraversal.rb:10:11:10:16 | call to params | ArchiveApiPathTraversal.rb:68:20:68:23 | file | This path depends on a $@. | ArchiveApiPathTraversal.rb:10:11:10:16 | call to params | user-provided value |
| ArchiveApiPathTraversal.rb:76:19:76:26 | filename | ArchiveApiPathTraversal.rb:15:9:15:14 | call to params | ArchiveApiPathTraversal.rb:76:19:76:26 | filename | This path depends on a $@. | ArchiveApiPathTraversal.rb:15:9:15:14 | call to params | user-provided value |
| tainted_path.rb:5:26:5:29 | path | tainted_path.rb:4:12:4:17 | call to params | tainted_path.rb:5:26:5:29 | path | This path depends on a $@. | tainted_path.rb:4:12:4:17 | call to params | user-provided value |
| tainted_path.rb:11:26:11:29 | path | tainted_path.rb:10:31:10:36 | call to params | tainted_path.rb:11:26:11:29 | path | This path depends on a $@. | tainted_path.rb:10:31:10:36 | call to params | user-provided value |
| tainted_path.rb:17:26:17:29 | path | tainted_path.rb:16:28:16:33 | call to params | tainted_path.rb:17:26:17:29 | path | This path depends on a $@. | tainted_path.rb:16:28:16:33 | call to params | user-provided value |
| tainted_path.rb:23:26:23:29 | path | tainted_path.rb:22:29:22:34 | call to params | tainted_path.rb:23:26:23:29 | path | This path depends on a $@. | tainted_path.rb:22:29:22:34 | call to params | user-provided value |
| tainted_path.rb:29:26:29:29 | path | tainted_path.rb:28:22:28:27 | call to params | tainted_path.rb:29:26:29:29 | path | This path depends on a $@. | tainted_path.rb:28:22:28:27 | call to params | user-provided value |
| tainted_path.rb:35:26:35:29 | path | tainted_path.rb:34:29:34:34 | call to params | tainted_path.rb:35:26:35:29 | path | This path depends on a $@. | tainted_path.rb:34:29:34:34 | call to params | user-provided value |
| tainted_path.rb:41:26:41:29 | path | tainted_path.rb:40:26:40:31 | call to params | tainted_path.rb:41:26:41:29 | path | This path depends on a $@. | tainted_path.rb:40:26:40:31 | call to params | user-provided value |
| tainted_path.rb:48:26:48:29 | path | tainted_path.rb:47:43:47:48 | call to params | tainted_path.rb:48:26:48:29 | path | This path depends on a $@. | tainted_path.rb:47:43:47:48 | call to params | user-provided value |
| tainted_path.rb:60:26:60:29 | path | tainted_path.rb:59:40:59:45 | call to params | tainted_path.rb:60:26:60:29 | path | This path depends on a $@. | tainted_path.rb:59:40:59:45 | call to params | user-provided value |
| tainted_path.rb:72:15:72:18 | path | tainted_path.rb:71:40:71:45 | call to params | tainted_path.rb:72:15:72:18 | path | This path depends on a $@. | tainted_path.rb:71:40:71:45 | call to params | user-provided value |
| tainted_path.rb:78:19:78:22 | path | tainted_path.rb:77:40:77:45 | call to params | tainted_path.rb:78:19:78:22 | path | This path depends on a $@. | tainted_path.rb:77:40:77:45 | call to params | user-provided value |
| tainted_path.rb:79:14:79:17 | path | tainted_path.rb:77:40:77:45 | call to params | tainted_path.rb:79:14:79:17 | path | This path depends on a $@. | tainted_path.rb:77:40:77:45 | call to params | user-provided value |
| tainted_path.rb:85:10:85:13 | path | tainted_path.rb:84:40:84:45 | call to params | tainted_path.rb:85:10:85:13 | path | This path depends on a $@. | tainted_path.rb:84:40:84:45 | call to params | user-provided value |
| tainted_path.rb:86:25:86:28 | path | tainted_path.rb:84:40:84:45 | call to params | tainted_path.rb:86:25:86:28 | path | This path depends on a $@. | tainted_path.rb:84:40:84:45 | call to params | user-provided value |
| tainted_path.rb:92:11:92:14 | path | tainted_path.rb:90:40:90:45 | call to params | tainted_path.rb:92:11:92:14 | path | This path depends on a $@. | tainted_path.rb:90:40:90:45 | call to params | user-provided value |

View File

@@ -1 +1,2 @@
queries/security/cwe-022/PathInjection.ql
query: queries/security/cwe-022/PathInjection.ql
postprocess: TestUtilities/InlineExpectationsTestQuery.ql

View File

@@ -1,51 +1,51 @@
class FooController < ActionController::Base
# BAD
def route0
path = params[:path]
@content = File.read path
path = params[:path] # $ Source=path1
@content = File.read path # $ Alert=path1
end
# BAD - File.absolute_path preserves taint
def route1
path = File.absolute_path params[:path]
@content = File.read path
path = File.absolute_path params[:path] # $ Source=path2
@content = File.read path # $ Alert=path2
end
# BAD - File.dirname preserves taint
def route2
path = "#{File.dirname(params[:path])}/foo"
@content = File.read path
path = "#{File.dirname(params[:path])}/foo" # $ Source=path3
@content = File.read path # $ Alert=path3
end
# BAD - File.expand_path preserves taint
def route3
path = File.expand_path params[:path]
@content = File.read path
path = File.expand_path params[:path] # $ Source=path4
@content = File.read path # $ Alert=path4
end
# BAD - File.path preserves taint
def route4
path = File.path params[:path]
@content = File.read path
path = File.path params[:path] # $ Source=path5
@content = File.read path # $ Alert=path5
end
# BAD - File.realdirpath preserves taint
def route5
path = File.realdirpath params[:path]
@content = File.read path
path = File.realdirpath params[:path] # $ Source=path6
@content = File.read path # $ Alert=path6
end
# BAD - File.realpath preserves taint
def route6
path = File.realpath params[:path]
@content = File.read path
path = File.realpath params[:path] # $ Source=path7
@content = File.read path # $ Alert=path7
end
# BAD - tainted arguments in any position propagate to the return value of
# File.join
def route7
path = File.join("foo", "bar", "baz", params[:path], "qux")
@content = File.read path
path = File.join("foo", "bar", "baz", params[:path], "qux") # $ Source=path8
@content = File.read path # $ Alert=path8
end
# GOOD - File.basename does not preserve taint
@@ -56,8 +56,8 @@ class FooController < ActionController::Base
# BAD
def route9
path = ActiveStorage::Filename.new(params[:path])
@content = File.read path
path = ActiveStorage::Filename.new(params[:path]) # $ Source=path9
@content = File.read path # $ Alert=path9
end
# GOOD - explicitly sanitized
@@ -68,27 +68,27 @@ class FooController < ActionController::Base
# BAD
def route11
path = ActiveStorage::Filename.new(params[:path])
send_file path
path = ActiveStorage::Filename.new(params[:path]) # $ Source=path10
send_file path # $ Alert=path10
end
# BAD
def route12
path = ActiveStorage::Filename.new(params[:path])
bla (Dir.glob path)
bla (Dir[path])
path = ActiveStorage::Filename.new(params[:path]) # $ Source=path11
bla (Dir.glob path) # $ Alert=path11
bla (Dir[path]) # $ Alert=path11
end
# BAD
def route13
path = ActiveStorage::Filename.new(params[:path])
load(path)
autoload(:MyModule, path)
path = ActiveStorage::Filename.new(params[:path]) # $ Source=path12
load(path) # $ Alert=path12
autoload(:MyModule, path) # $ Alert=path12
end
def require_relative()
path = ActiveStorage::Filename.new(params[:path])
path = ActiveStorage::Filename.new(params[:path]) # $ Source=path13
puts "Debug: require_relative(#{path})"
super(path)
super(path) # $ Alert=path13
end
end