From 609bb762fe32849a92c0ca2243258cbcda5ce084 Mon Sep 17 00:00:00 2001 From: amammad <77095239+amammad@users.noreply.github.com> Date: Wed, 11 Oct 2023 12:04:11 +0200 Subject: [PATCH] fix a bug,modularize --- .../DecompressionBombs.ql | 159 ++------------- .../DecompressionBombs.qll | 167 +++++++++++++++ .../DecompressionBombs.expected | 193 ++++++++++-------- .../CWE-522-DecompressionBombs/gzipBombs.rb | 39 ++-- .../CWE-522-DecompressionBombs/zipBombs.rb | 94 ++++----- 5 files changed, 364 insertions(+), 288 deletions(-) create mode 100644 ruby/ql/src/experimental/CWE-522-DecompressionBombs/DecompressionBombs.qll diff --git a/ruby/ql/src/experimental/CWE-522-DecompressionBombs/DecompressionBombs.ql b/ruby/ql/src/experimental/CWE-522-DecompressionBombs/DecompressionBombs.ql index 3ed993bebd5..da9ffb5302e 100644 --- a/ruby/ql/src/experimental/CWE-522-DecompressionBombs/DecompressionBombs.ql +++ b/ruby/ql/src/experimental/CWE-522-DecompressionBombs/DecompressionBombs.ql @@ -11,124 +11,10 @@ * external/cwe/cwe-409 */ -import codeql.ruby.AST -import codeql.ruby.frameworks.Files -import codeql.ruby.ApiGraphs -import codeql.ruby.DataFlow -import codeql.ruby.dataflow.RemoteFlowSources -import codeql.ruby.TaintTracking -import DataFlow::PathGraph - -module DecompressionBombs { - abstract class DecompressionBombSink extends DataFlow::Node { } - - module Zlib { - /** - * `Zlib::GzipReader` - * > Note that if you use the lower level Zip::InputStream interface, rubyzip does not check the entry sizes. - * - * according to above warning from Doc we don't need to go forward after open() - * or new() methods, we just need the argument node of them - */ - private API::Node gzipReaderInstance() { - result = API::getTopLevelMember("Zlib").getMember("GzipReader") - } - - /** - * A return values of following methods - * `Zlib::GzipReader.open` - * `Zlib::GzipReader.zcat` - * `Zlib::GzipReader.new` - */ - class ZipSink extends DecompressionBombSink { - ZipSink() { - this = gzipReaderInstance().getMethod(["open", "new", "zcat"]).getReturn().asSource() - } - } - - predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { - exists(API::Node zipnode | zipnode = gzipReaderInstance().getMethod(["open", "new", "zcat"]) | - nodeFrom = zipnode.getParameter(0).asSink() and - nodeTo = zipnode.getReturn().asSource() - ) - } - } - - module ZipInputStream { - /** - * `Zip::InputStream` - * > Note that if you use the lower level Zip::InputStream interface, rubyzip does not check the entry sizes. - * - * according to above warning from Doc we don't need to go forward after open() - * or new() methods, we just need the argument node of them - */ - private API::Node zipInputStream() { - result = API::getTopLevelMember("Zip").getMember("InputStream") - } - - /** - * A return values of following methods - * `ZipIO.read` - * `ZipEntry.extract` - */ - class ZipSink extends DecompressionBombSink { - ZipSink() { - this = zipInputStream().getMethod(["open", "new"]).getReturn().asSource() and - not this.getLocation().getFile().getBaseName().matches("%spec%") - } - } - - predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { - exists(API::Node zipnode | zipnode = zipInputStream().getMethod(["open", "new"]) | - nodeFrom = zipnode.getParameter(0).asSink() and - nodeTo = zipnode.getReturn().asSource() - ) - } - } - - module ZipFile { - API::Node rubyZipNode() { - result = zipFile() - or - result = rubyZipNode().getMethod(_) - or - result = rubyZipNode().getReturn() - or - result = rubyZipNode().getParameter(_) - or - result = rubyZipNode().getAnElement() - or - result = rubyZipNode().getBlock() - } - - /** - * A return values of following methods - * `ZipIO.read` - * `ZipEntry.extract` - * sanitize the nodes which have `entry.size > someOBJ` - */ - class ZipSink extends DecompressionBombSink { - ZipSink() { - exists(API::Node zipnodes | zipnodes = rubyZipNode() | - this = zipnodes.getMethod(["extract", "read"]).getReturn().asSource() and - not exists(zipnodes.getMethod("size").getReturn().getMethod(">").getParameter(0)) - ) - } - } - - predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { - exists(API::Node zipnodes | zipnodes = rubyZipNode() | - nodeTo = zipnodes.getMethod(["extract", "read"]).getReturn().asSource() and - nodeFrom = zipnodes.getMethod(["new", "open"]).getParameter(0).asSink() - ) - } - - /** - * `Zip::File` - */ - API::Node zipFile() { result = API::getTopLevelCall("Zip").getMember("File") } - } -} +private import codeql.ruby.Concepts +private import codeql.ruby.DataFlow +private import codeql.ruby.TaintTracking +import DecompressionBombs /** * A call to `IO.copy_stream` @@ -139,30 +25,17 @@ class IoCopyStream extends DataFlow::CallNode { DataFlow::Node getAPathArgument() { result = this.getArgument(0) } } -class Bombs extends TaintTracking::Configuration { - Bombs() { this = "Decompression Bombs" } - - override predicate isSanitizer(DataFlow::Node node) { - not node.getLocation().hasLocationInfo("%spec%", _, _, _, _) +module BombsConfig implements DataFlow::ConfigSig { + predicate isBarrier(DataFlow::Node node) { + node.getLocation().hasLocationInfo("%spec%", _, _, _, _) } - override predicate isSource(DataFlow::Node source) { - source instanceof RemoteFlowSource - // or - // source instanceof DataFlow::LocalSourceNode - // source = API::getTopLevelCall("Zip").getMember("InputStream").getASuccessor*() - } + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - override predicate isSink(DataFlow::Node sink) { - sink instanceof DecompressionBombs::DecompressionBombSink - } + predicate isSink(DataFlow::Node sink) { sink instanceof DecompressionBomb::Sink } - override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { - DecompressionBombs::ZipFile::isAdditionalTaintStep(nodeFrom, nodeTo) - or - DecompressionBombs::ZipInputStream::isAdditionalTaintStep(nodeFrom, nodeTo) - or - DecompressionBombs::Zlib::isAdditionalTaintStep(nodeFrom, nodeTo) + predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + any(DecompressionBomb::AdditionalTaintStep ats).isAdditionalTaintStep(nodeFrom, nodeTo) or exists(API::Node n | n = API::root().getMember("File").getMethod("open") | nodeFrom = n.getParameter(0).asSink() and @@ -194,7 +67,11 @@ class Bombs extends TaintTracking::Configuration { } } -from Bombs cfg, DataFlow::PathNode source, DataFlow::PathNode sink -where cfg.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "This file extraction depends on a $@.", source.getNode(), +module Bombs = TaintTracking::Global; + +import Bombs::PathGraph + +from Bombs::PathNode source, Bombs::PathNode sink +where Bombs::flowPath(source, sink) +select sink.getNode(), source, sink, "This file Decompression depends on a $@.", source.getNode(), "potentially untrusted source" diff --git a/ruby/ql/src/experimental/CWE-522-DecompressionBombs/DecompressionBombs.qll b/ruby/ql/src/experimental/CWE-522-DecompressionBombs/DecompressionBombs.qll new file mode 100644 index 00000000000..d51dffe2d90 --- /dev/null +++ b/ruby/ql/src/experimental/CWE-522-DecompressionBombs/DecompressionBombs.qll @@ -0,0 +1,167 @@ +import codeql.ruby.AST +import codeql.ruby.frameworks.Files +import codeql.ruby.ApiGraphs +import codeql.ruby.DataFlow +import codeql.ruby.dataflow.RemoteFlowSources + +module DecompressionBomb { + /** + * The Sinks of uncontrolled data decompression + */ + class Sink extends DataFlow::Node { + Sink() { this = any(Range r).sink() } + } + + /** + * The additional taint steps that need for creating taint tracking or dataflow. + */ + abstract class AdditionalTaintStep extends string { + AdditionalTaintStep() { this = "AdditionalTaintStep" } + + /** + * Holds if there is a additional taint step between pred and succ. + */ + abstract predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ); + } + + /** + * A abstract class responsible for extending new decompression sinks + */ + abstract class Range extends API::Node { + /** + * Gets the sink of responsible for decompression node + * + * it can be a path, stream of compressed data, + * or a call to function that use pipe + */ + abstract DataFlow::Node sink(); + } +} + +module Zlib { + /** + * Gets a node of `Zlib::GzipReader` member + * + * Note that if you use the lower level Zip::InputStream interface, rubyzip does not check the entry sizes. + */ + private API::Node gzipReaderInstance() { + result = API::getTopLevelMember("Zlib").getMember("GzipReader") + } + + /** + * A return values of following methods + * `Zlib::GzipReader.open` + * `Zlib::GzipReader.zcat` + * `Zlib::GzipReader.new` + */ + class DecompressionBombSink extends DecompressionBomb::Range { + DecompressionBombSink() { this = gzipReaderInstance().getMethod(["open", "new", "zcat"]) } + + override DataFlow::Node sink() { result = this.getReturn().asSource() } + } + + /** + * The additional taint steps that need for creating taint tracking or dataflow for `Zlib`. + */ + class AdditionalTaintStep extends DecompressionBomb::AdditionalTaintStep { + AdditionalTaintStep() { this = "AdditionalTaintStep" } + + override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + exists(API::Node openOrNewOrZcat | + openOrNewOrZcat = gzipReaderInstance().getMethod(["open", "new", "zcat"]) + | + nodeFrom = openOrNewOrZcat.getParameter(0).asSink() and + nodeTo = openOrNewOrZcat.getReturn().asSource() + ) + } + } +} + +module ZipInputStream { + /** + * Gets a node of `Zip::InputStream` member + * + * Note that if you use the lower level Zip::InputStream interface, rubyzip does not check the entry sizes. + */ + private API::Node zipInputStream() { + result = API::getTopLevelMember("Zip").getMember("InputStream") + } + + /** + * The return values of following methods + * `ZipIO.read` + * `ZipEntry.extract` + */ + class DecompressionBombSink extends DecompressionBomb::Range { + DecompressionBombSink() { this = zipInputStream().getMethod(["open", "new"]) } + + override DataFlow::Node sink() { result = this.getReturn().asSource() } + } + + /** + * The additional taint steps that need for creating taint tracking or dataflow for `Zip`. + */ + class AdditionalTaintStep extends DecompressionBomb::AdditionalTaintStep { + AdditionalTaintStep() { this = "AdditionalTaintStep" } + + override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + exists(API::Node openOrNew | openOrNew = zipInputStream().getMethod(["open", "new"]) | + nodeFrom = openOrNew.getParameter(0).asSink() and + nodeTo = openOrNew.getReturn().asSource() + ) + } + } +} + +module ZipFile { + /** + * Gets a node of `Zip::File` member + */ + API::Node zipFile() { result = API::getTopLevelMember("Zip").getMember("File") } + + /** + * Gets nodes that have a `base` at the beginning + */ + API::Node rubyZipNode(API::Node base) { + result = base + or + result = rubyZipNode(base).getMethod(_) + or + result = rubyZipNode(base).getReturn() + or + result = rubyZipNode(base).getParameter(_) + or + result = rubyZipNode(base).getAnElement() + or + result = rubyZipNode(base).getBlock() + } + + /** + * The return values of following methods + * `ZipIO.read` + * `ZipEntry.extract` + * A sanitizer exists inside the nodes which have `entry.size > someOBJ` + */ + class DecompressionBombSink extends DecompressionBomb::Range { + DecompressionBombSink() { this = rubyZipNode(zipFile()) } + + override DataFlow::Node sink() { + result = this.getMethod(["extract", "read"]).getReturn().asSource() and + not exists(this.getMethod("size").getReturn().getMethod(">").getParameter(0)) + } + } + + /** + * The additional taint steps that need for creating taint tracking or dataflow for `Zip::File`. + */ + class AdditionalTaintStep extends DecompressionBomb::AdditionalTaintStep { + AdditionalTaintStep() { this = "AdditionalTaintStep" } + + override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + exists(API::Node zipFile | zipFile = zipFile().getMethod("open") | + nodeFrom = zipFile.getParameter(0).asSink() and + nodeTo = rubyZipNode(zipFile).getMethod(["extract", "read"]).getReturn().asSource() + ) + } + } +} diff --git a/ruby/ql/test/query-tests/experimental/CWE-522-DecompressionBombs/DecompressionBombs.expected b/ruby/ql/test/query-tests/experimental/CWE-522-DecompressionBombs/DecompressionBombs.expected index c9f13eb5272..3320a40a534 100644 --- a/ruby/ql/test/query-tests/experimental/CWE-522-DecompressionBombs/DecompressionBombs.expected +++ b/ruby/ql/test/query-tests/experimental/CWE-522-DecompressionBombs/DecompressionBombs.expected @@ -1,87 +1,114 @@ edges -| gzipBombs.rb:2:1:2:9 | gzip_path | gzipBombs.rb:3:1:3:32 | call to open | -| gzipBombs.rb:2:1:2:9 | gzip_path | gzipBombs.rb:4:1:6:3 | call to open | -| gzipBombs.rb:2:1:2:9 | gzip_path | gzipBombs.rb:7:1:11:3 | call to open | -| gzipBombs.rb:2:1:2:9 | gzip_path | gzipBombs.rb:12:20:12:51 | call to open | -| gzipBombs.rb:2:1:2:9 | gzip_path | gzipBombs.rb:17:1:17:48 | call to new | -| gzipBombs.rb:2:1:2:9 | gzip_path | gzipBombs.rb:18:1:18:48 | call to new | -| gzipBombs.rb:2:1:2:9 | gzip_path | gzipBombs.rb:22:1:22:38 | call to zcat | -| gzipBombs.rb:2:13:2:29 | "Path/To/bomb.gz" | gzipBombs.rb:2:1:2:9 | gzip_path | -| gzipBombs.rb:17:22:17:47 | call to open | gzipBombs.rb:17:1:17:48 | call to new | -| gzipBombs.rb:18:22:18:47 | call to open | gzipBombs.rb:18:1:18:48 | call to new | -| gzipBombs.rb:22:23:22:37 | call to open | gzipBombs.rb:22:1:22:38 | call to zcat | -| zipBombs.rb:2:1:2:12 | zipfile_path | zipBombs.rb:3:1:8:3 | call to open | -| zipBombs.rb:2:1:2:12 | zipfile_path | zipBombs.rb:9:1:11:3 | call to open | -| zipBombs.rb:2:1:2:12 | zipfile_path | zipBombs.rb:12:9:12:43 | call to open | -| zipBombs.rb:2:1:2:12 | zipfile_path | zipBombs.rb:14:1:14:40 | call to read | -| zipBombs.rb:2:1:2:12 | zipfile_path | zipBombs.rb:15:1:15:49 | call to extract | -| zipBombs.rb:2:1:2:12 | zipfile_path | zipBombs.rb:29:27:29:38 | zipfile_path | -| zipBombs.rb:2:1:2:12 | zipfile_path | zipBombs.rb:48:6:48:32 | call to read | -| zipBombs.rb:2:1:2:12 | zipfile_path | zipBombs.rb:50:27:50:38 | zipfile_path | -| zipBombs.rb:2:16:2:33 | "Path/To/bomb.zip" | zipBombs.rb:2:1:2:12 | zipfile_path | -| zipBombs.rb:29:27:29:38 | zipfile_path | zipBombs.rb:31:3:31:15 | call to extract | -| zipBombs.rb:29:27:29:38 | zipfile_path | zipBombs.rb:32:3:32:29 | call to read | -| zipBombs.rb:50:27:50:38 | zipfile_path | zipBombs.rb:52:3:52:29 | call to read | +| gzipBombs.rb:4:3:4:11 | gzip_path | gzipBombs.rb:6:25:6:33 | gzip_path | +| gzipBombs.rb:4:15:4:20 | call to params | gzipBombs.rb:4:15:4:27 | ...[...] | +| gzipBombs.rb:4:15:4:27 | ...[...] | gzipBombs.rb:4:3:4:11 | gzip_path | +| gzipBombs.rb:6:25:6:33 | gzip_path | gzipBombs.rb:6:3:6:34 | call to open | +| gzipBombs.rb:6:25:6:33 | gzip_path | gzipBombs.rb:7:25:7:33 | gzip_path | +| gzipBombs.rb:7:25:7:33 | gzip_path | gzipBombs.rb:7:3:9:5 | call to open | +| gzipBombs.rb:7:25:7:33 | gzip_path | gzipBombs.rb:10:25:10:33 | gzip_path | +| gzipBombs.rb:10:25:10:33 | gzip_path | gzipBombs.rb:10:3:14:5 | call to open | +| gzipBombs.rb:10:25:10:33 | gzip_path | gzipBombs.rb:15:44:15:52 | gzip_path | +| gzipBombs.rb:15:44:15:52 | gzip_path | gzipBombs.rb:15:22:15:53 | call to open | +| gzipBombs.rb:15:44:15:52 | gzip_path | gzipBombs.rb:20:34:20:42 | gzip_path | +| gzipBombs.rb:20:24:20:49 | call to open | gzipBombs.rb:20:3:20:50 | call to new | +| gzipBombs.rb:20:34:20:42 | gzip_path | gzipBombs.rb:20:24:20:49 | call to open | +| gzipBombs.rb:20:34:20:42 | gzip_path | gzipBombs.rb:21:34:21:42 | gzip_path | +| gzipBombs.rb:21:24:21:49 | call to open | gzipBombs.rb:21:3:21:50 | call to new | +| gzipBombs.rb:21:34:21:42 | gzip_path | gzipBombs.rb:21:24:21:49 | call to open | +| gzipBombs.rb:21:34:21:42 | gzip_path | gzipBombs.rb:25:30:25:38 | gzip_path | +| gzipBombs.rb:25:25:25:39 | call to open | gzipBombs.rb:25:3:25:40 | call to zcat | +| gzipBombs.rb:25:30:25:38 | gzip_path | gzipBombs.rb:25:25:25:39 | call to open | +| zipBombs.rb:4:3:4:14 | zipfile_path | zipBombs.rb:6:25:6:36 | zipfile_path | +| zipBombs.rb:4:18:4:23 | call to params | zipBombs.rb:4:18:4:30 | ...[...] | +| zipBombs.rb:4:18:4:30 | ...[...] | zipBombs.rb:4:3:4:14 | zipfile_path | +| zipBombs.rb:6:25:6:36 | zipfile_path | zipBombs.rb:6:3:11:5 | call to open | +| zipBombs.rb:6:25:6:36 | zipfile_path | zipBombs.rb:12:25:12:36 | zipfile_path | +| zipBombs.rb:12:25:12:36 | zipfile_path | zipBombs.rb:12:3:14:5 | call to open | +| zipBombs.rb:12:25:12:36 | zipfile_path | zipBombs.rb:15:33:15:44 | zipfile_path | +| zipBombs.rb:15:33:15:44 | zipfile_path | zipBombs.rb:15:11:15:45 | call to open | +| zipBombs.rb:15:33:15:44 | zipfile_path | zipBombs.rb:17:18:17:29 | zipfile_path | +| zipBombs.rb:17:18:17:29 | zipfile_path | zipBombs.rb:17:3:17:42 | call to read | +| zipBombs.rb:17:18:17:29 | zipfile_path | zipBombs.rb:18:18:18:29 | zipfile_path | +| zipBombs.rb:18:18:18:29 | zipfile_path | zipBombs.rb:18:3:18:51 | call to extract | +| zipBombs.rb:18:18:18:29 | zipfile_path | zipBombs.rb:20:18:20:29 | zipfile_path | +| zipBombs.rb:20:18:20:29 | zipfile_path | zipBombs.rb:28:7:28:33 | call to read | +| zipBombs.rb:20:18:20:29 | zipfile_path | zipBombs.rb:32:29:32:40 | zipfile_path | +| zipBombs.rb:32:29:32:40 | zipfile_path | zipBombs.rb:34:5:34:17 | call to extract | +| zipBombs.rb:32:29:32:40 | zipfile_path | zipBombs.rb:35:5:35:31 | call to read | +| zipBombs.rb:32:29:32:40 | zipfile_path | zipBombs.rb:39:18:39:29 | zipfile_path | +| zipBombs.rb:39:18:39:29 | zipfile_path | zipBombs.rb:41:7:41:31 | call to read | +| zipBombs.rb:39:18:39:29 | zipfile_path | zipBombs.rb:42:7:42:19 | call to extract | +| zipBombs.rb:39:18:39:29 | zipfile_path | zipBombs.rb:46:10:46:36 | call to read | +| zipBombs.rb:39:18:39:29 | zipfile_path | zipBombs.rb:49:29:49:40 | zipfile_path | +| zipBombs.rb:49:29:49:40 | zipfile_path | zipBombs.rb:51:8:51:34 | call to read | +| zipBombs.rb:49:29:49:40 | zipfile_path | zipBombs.rb:53:29:53:40 | zipfile_path | +| zipBombs.rb:53:29:53:40 | zipfile_path | zipBombs.rb:55:5:55:31 | call to read | nodes -| gzipBombs.rb:2:1:2:9 | gzip_path | semmle.label | gzip_path | -| gzipBombs.rb:2:13:2:29 | "Path/To/bomb.gz" | semmle.label | "Path/To/bomb.gz" | -| gzipBombs.rb:3:1:3:32 | call to open | semmle.label | call to open | -| gzipBombs.rb:4:1:6:3 | call to open | semmle.label | call to open | -| gzipBombs.rb:7:1:11:3 | call to open | semmle.label | call to open | -| gzipBombs.rb:12:20:12:51 | call to open | semmle.label | call to open | -| gzipBombs.rb:17:1:17:48 | call to new | semmle.label | call to new | -| gzipBombs.rb:17:22:17:47 | call to open | semmle.label | call to open | -| gzipBombs.rb:18:1:18:48 | call to new | semmle.label | call to new | -| gzipBombs.rb:18:22:18:47 | call to open | semmle.label | call to open | -| gzipBombs.rb:22:1:22:38 | call to zcat | semmle.label | call to zcat | -| gzipBombs.rb:22:23:22:37 | call to open | semmle.label | call to open | -| zipBombs.rb:2:1:2:12 | zipfile_path | semmle.label | zipfile_path | -| zipBombs.rb:2:16:2:33 | "Path/To/bomb.zip" | semmle.label | "Path/To/bomb.zip" | -| zipBombs.rb:3:1:8:3 | call to open | semmle.label | call to open | -| zipBombs.rb:9:1:11:3 | call to open | semmle.label | call to open | -| zipBombs.rb:12:9:12:43 | call to open | semmle.label | call to open | -| zipBombs.rb:14:1:14:40 | call to read | semmle.label | call to read | -| zipBombs.rb:15:1:15:49 | call to extract | semmle.label | call to extract | -| zipBombs.rb:29:27:29:38 | zipfile_path | semmle.label | zipfile_path | -| zipBombs.rb:31:3:31:15 | call to extract | semmle.label | call to extract | -| zipBombs.rb:32:3:32:29 | call to read | semmle.label | call to read | -| zipBombs.rb:48:6:48:32 | call to read | semmle.label | call to read | -| zipBombs.rb:50:27:50:38 | zipfile_path | semmle.label | zipfile_path | -| zipBombs.rb:52:3:52:29 | call to read | semmle.label | call to read | +| gzipBombs.rb:4:3:4:11 | gzip_path | semmle.label | gzip_path | +| gzipBombs.rb:4:15:4:20 | call to params | semmle.label | call to params | +| gzipBombs.rb:4:15:4:27 | ...[...] | semmle.label | ...[...] | +| gzipBombs.rb:6:3:6:34 | call to open | semmle.label | call to open | +| gzipBombs.rb:6:25:6:33 | gzip_path | semmle.label | gzip_path | +| gzipBombs.rb:7:3:9:5 | call to open | semmle.label | call to open | +| gzipBombs.rb:7:25:7:33 | gzip_path | semmle.label | gzip_path | +| gzipBombs.rb:10:3:14:5 | call to open | semmle.label | call to open | +| gzipBombs.rb:10:25:10:33 | gzip_path | semmle.label | gzip_path | +| gzipBombs.rb:15:22:15:53 | call to open | semmle.label | call to open | +| gzipBombs.rb:15:44:15:52 | gzip_path | semmle.label | gzip_path | +| gzipBombs.rb:20:3:20:50 | call to new | semmle.label | call to new | +| gzipBombs.rb:20:24:20:49 | call to open | semmle.label | call to open | +| gzipBombs.rb:20:34:20:42 | gzip_path | semmle.label | gzip_path | +| gzipBombs.rb:21:3:21:50 | call to new | semmle.label | call to new | +| gzipBombs.rb:21:24:21:49 | call to open | semmle.label | call to open | +| gzipBombs.rb:21:34:21:42 | gzip_path | semmle.label | gzip_path | +| gzipBombs.rb:25:3:25:40 | call to zcat | semmle.label | call to zcat | +| gzipBombs.rb:25:25:25:39 | call to open | semmle.label | call to open | +| gzipBombs.rb:25:30:25:38 | gzip_path | semmle.label | gzip_path | +| zipBombs.rb:4:3:4:14 | zipfile_path | semmle.label | zipfile_path | +| zipBombs.rb:4:18:4:23 | call to params | semmle.label | call to params | +| zipBombs.rb:4:18:4:30 | ...[...] | semmle.label | ...[...] | +| zipBombs.rb:6:3:11:5 | call to open | semmle.label | call to open | +| zipBombs.rb:6:25:6:36 | zipfile_path | semmle.label | zipfile_path | +| zipBombs.rb:12:3:14:5 | call to open | semmle.label | call to open | +| zipBombs.rb:12:25:12:36 | zipfile_path | semmle.label | zipfile_path | +| zipBombs.rb:15:11:15:45 | call to open | semmle.label | call to open | +| zipBombs.rb:15:33:15:44 | zipfile_path | semmle.label | zipfile_path | +| zipBombs.rb:17:3:17:42 | call to read | semmle.label | call to read | +| zipBombs.rb:17:18:17:29 | zipfile_path | semmle.label | zipfile_path | +| zipBombs.rb:18:3:18:51 | call to extract | semmle.label | call to extract | +| zipBombs.rb:18:18:18:29 | zipfile_path | semmle.label | zipfile_path | +| zipBombs.rb:20:18:20:29 | zipfile_path | semmle.label | zipfile_path | +| zipBombs.rb:28:7:28:33 | call to read | semmle.label | call to read | +| zipBombs.rb:32:29:32:40 | zipfile_path | semmle.label | zipfile_path | +| zipBombs.rb:34:5:34:17 | call to extract | semmle.label | call to extract | +| zipBombs.rb:35:5:35:31 | call to read | semmle.label | call to read | +| zipBombs.rb:39:18:39:29 | zipfile_path | semmle.label | zipfile_path | +| zipBombs.rb:41:7:41:31 | call to read | semmle.label | call to read | +| zipBombs.rb:42:7:42:19 | call to extract | semmle.label | call to extract | +| zipBombs.rb:46:10:46:36 | call to read | semmle.label | call to read | +| zipBombs.rb:49:29:49:40 | zipfile_path | semmle.label | zipfile_path | +| zipBombs.rb:51:8:51:34 | call to read | semmle.label | call to read | +| zipBombs.rb:53:29:53:40 | zipfile_path | semmle.label | zipfile_path | +| zipBombs.rb:55:5:55:31 | call to read | semmle.label | call to read | subpaths #select -| gzipBombs.rb:3:1:3:32 | call to open | gzipBombs.rb:2:13:2:29 | "Path/To/bomb.gz" | gzipBombs.rb:3:1:3:32 | call to open | This file extraction depends on a $@. | gzipBombs.rb:2:13:2:29 | "Path/To/bomb.gz" | potentially untrusted source | -| gzipBombs.rb:3:1:3:32 | call to open | gzipBombs.rb:3:1:3:32 | call to open | gzipBombs.rb:3:1:3:32 | call to open | This file extraction depends on a $@. | gzipBombs.rb:3:1:3:32 | call to open | potentially untrusted source | -| gzipBombs.rb:4:1:6:3 | call to open | gzipBombs.rb:2:13:2:29 | "Path/To/bomb.gz" | gzipBombs.rb:4:1:6:3 | call to open | This file extraction depends on a $@. | gzipBombs.rb:2:13:2:29 | "Path/To/bomb.gz" | potentially untrusted source | -| gzipBombs.rb:4:1:6:3 | call to open | gzipBombs.rb:4:1:6:3 | call to open | gzipBombs.rb:4:1:6:3 | call to open | This file extraction depends on a $@. | gzipBombs.rb:4:1:6:3 | call to open | potentially untrusted source | -| gzipBombs.rb:7:1:11:3 | call to open | gzipBombs.rb:2:13:2:29 | "Path/To/bomb.gz" | gzipBombs.rb:7:1:11:3 | call to open | This file extraction depends on a $@. | gzipBombs.rb:2:13:2:29 | "Path/To/bomb.gz" | potentially untrusted source | -| gzipBombs.rb:7:1:11:3 | call to open | gzipBombs.rb:7:1:11:3 | call to open | gzipBombs.rb:7:1:11:3 | call to open | This file extraction depends on a $@. | gzipBombs.rb:7:1:11:3 | call to open | potentially untrusted source | -| gzipBombs.rb:12:20:12:51 | call to open | gzipBombs.rb:2:13:2:29 | "Path/To/bomb.gz" | gzipBombs.rb:12:20:12:51 | call to open | This file extraction depends on a $@. | gzipBombs.rb:2:13:2:29 | "Path/To/bomb.gz" | potentially untrusted source | -| gzipBombs.rb:12:20:12:51 | call to open | gzipBombs.rb:12:20:12:51 | call to open | gzipBombs.rb:12:20:12:51 | call to open | This file extraction depends on a $@. | gzipBombs.rb:12:20:12:51 | call to open | potentially untrusted source | -| gzipBombs.rb:17:1:17:48 | call to new | gzipBombs.rb:2:13:2:29 | "Path/To/bomb.gz" | gzipBombs.rb:17:1:17:48 | call to new | This file extraction depends on a $@. | gzipBombs.rb:2:13:2:29 | "Path/To/bomb.gz" | potentially untrusted source | -| gzipBombs.rb:17:1:17:48 | call to new | gzipBombs.rb:17:1:17:48 | call to new | gzipBombs.rb:17:1:17:48 | call to new | This file extraction depends on a $@. | gzipBombs.rb:17:1:17:48 | call to new | potentially untrusted source | -| gzipBombs.rb:17:1:17:48 | call to new | gzipBombs.rb:17:22:17:47 | call to open | gzipBombs.rb:17:1:17:48 | call to new | This file extraction depends on a $@. | gzipBombs.rb:17:22:17:47 | call to open | potentially untrusted source | -| gzipBombs.rb:18:1:18:48 | call to new | gzipBombs.rb:2:13:2:29 | "Path/To/bomb.gz" | gzipBombs.rb:18:1:18:48 | call to new | This file extraction depends on a $@. | gzipBombs.rb:2:13:2:29 | "Path/To/bomb.gz" | potentially untrusted source | -| gzipBombs.rb:18:1:18:48 | call to new | gzipBombs.rb:18:1:18:48 | call to new | gzipBombs.rb:18:1:18:48 | call to new | This file extraction depends on a $@. | gzipBombs.rb:18:1:18:48 | call to new | potentially untrusted source | -| gzipBombs.rb:18:1:18:48 | call to new | gzipBombs.rb:18:22:18:47 | call to open | gzipBombs.rb:18:1:18:48 | call to new | This file extraction depends on a $@. | gzipBombs.rb:18:22:18:47 | call to open | potentially untrusted source | -| gzipBombs.rb:22:1:22:38 | call to zcat | gzipBombs.rb:2:13:2:29 | "Path/To/bomb.gz" | gzipBombs.rb:22:1:22:38 | call to zcat | This file extraction depends on a $@. | gzipBombs.rb:2:13:2:29 | "Path/To/bomb.gz" | potentially untrusted source | -| gzipBombs.rb:22:1:22:38 | call to zcat | gzipBombs.rb:22:1:22:38 | call to zcat | gzipBombs.rb:22:1:22:38 | call to zcat | This file extraction depends on a $@. | gzipBombs.rb:22:1:22:38 | call to zcat | potentially untrusted source | -| gzipBombs.rb:22:1:22:38 | call to zcat | gzipBombs.rb:22:23:22:37 | call to open | gzipBombs.rb:22:1:22:38 | call to zcat | This file extraction depends on a $@. | gzipBombs.rb:22:23:22:37 | call to open | potentially untrusted source | -| zipBombs.rb:3:1:8:3 | call to open | zipBombs.rb:2:16:2:33 | "Path/To/bomb.zip" | zipBombs.rb:3:1:8:3 | call to open | This file extraction depends on a $@. | zipBombs.rb:2:16:2:33 | "Path/To/bomb.zip" | potentially untrusted source | -| zipBombs.rb:3:1:8:3 | call to open | zipBombs.rb:3:1:8:3 | call to open | zipBombs.rb:3:1:8:3 | call to open | This file extraction depends on a $@. | zipBombs.rb:3:1:8:3 | call to open | potentially untrusted source | -| zipBombs.rb:9:1:11:3 | call to open | zipBombs.rb:2:16:2:33 | "Path/To/bomb.zip" | zipBombs.rb:9:1:11:3 | call to open | This file extraction depends on a $@. | zipBombs.rb:2:16:2:33 | "Path/To/bomb.zip" | potentially untrusted source | -| zipBombs.rb:9:1:11:3 | call to open | zipBombs.rb:9:1:11:3 | call to open | zipBombs.rb:9:1:11:3 | call to open | This file extraction depends on a $@. | zipBombs.rb:9:1:11:3 | call to open | potentially untrusted source | -| zipBombs.rb:12:9:12:43 | call to open | zipBombs.rb:2:16:2:33 | "Path/To/bomb.zip" | zipBombs.rb:12:9:12:43 | call to open | This file extraction depends on a $@. | zipBombs.rb:2:16:2:33 | "Path/To/bomb.zip" | potentially untrusted source | -| zipBombs.rb:12:9:12:43 | call to open | zipBombs.rb:12:9:12:43 | call to open | zipBombs.rb:12:9:12:43 | call to open | This file extraction depends on a $@. | zipBombs.rb:12:9:12:43 | call to open | potentially untrusted source | -| zipBombs.rb:14:1:14:40 | call to read | zipBombs.rb:2:16:2:33 | "Path/To/bomb.zip" | zipBombs.rb:14:1:14:40 | call to read | This file extraction depends on a $@. | zipBombs.rb:2:16:2:33 | "Path/To/bomb.zip" | potentially untrusted source | -| zipBombs.rb:14:1:14:40 | call to read | zipBombs.rb:14:1:14:40 | call to read | zipBombs.rb:14:1:14:40 | call to read | This file extraction depends on a $@. | zipBombs.rb:14:1:14:40 | call to read | potentially untrusted source | -| zipBombs.rb:15:1:15:49 | call to extract | zipBombs.rb:2:16:2:33 | "Path/To/bomb.zip" | zipBombs.rb:15:1:15:49 | call to extract | This file extraction depends on a $@. | zipBombs.rb:2:16:2:33 | "Path/To/bomb.zip" | potentially untrusted source | -| zipBombs.rb:15:1:15:49 | call to extract | zipBombs.rb:15:1:15:49 | call to extract | zipBombs.rb:15:1:15:49 | call to extract | This file extraction depends on a $@. | zipBombs.rb:15:1:15:49 | call to extract | potentially untrusted source | -| zipBombs.rb:31:3:31:15 | call to extract | zipBombs.rb:2:16:2:33 | "Path/To/bomb.zip" | zipBombs.rb:31:3:31:15 | call to extract | This file extraction depends on a $@. | zipBombs.rb:2:16:2:33 | "Path/To/bomb.zip" | potentially untrusted source | -| zipBombs.rb:31:3:31:15 | call to extract | zipBombs.rb:31:3:31:15 | call to extract | zipBombs.rb:31:3:31:15 | call to extract | This file extraction depends on a $@. | zipBombs.rb:31:3:31:15 | call to extract | potentially untrusted source | -| zipBombs.rb:32:3:32:29 | call to read | zipBombs.rb:2:16:2:33 | "Path/To/bomb.zip" | zipBombs.rb:32:3:32:29 | call to read | This file extraction depends on a $@. | zipBombs.rb:2:16:2:33 | "Path/To/bomb.zip" | potentially untrusted source | -| zipBombs.rb:32:3:32:29 | call to read | zipBombs.rb:32:3:32:29 | call to read | zipBombs.rb:32:3:32:29 | call to read | This file extraction depends on a $@. | zipBombs.rb:32:3:32:29 | call to read | potentially untrusted source | -| zipBombs.rb:48:6:48:32 | call to read | zipBombs.rb:2:16:2:33 | "Path/To/bomb.zip" | zipBombs.rb:48:6:48:32 | call to read | This file extraction depends on a $@. | zipBombs.rb:2:16:2:33 | "Path/To/bomb.zip" | potentially untrusted source | -| zipBombs.rb:48:6:48:32 | call to read | zipBombs.rb:48:6:48:32 | call to read | zipBombs.rb:48:6:48:32 | call to read | This file extraction depends on a $@. | zipBombs.rb:48:6:48:32 | call to read | potentially untrusted source | -| zipBombs.rb:52:3:52:29 | call to read | zipBombs.rb:2:16:2:33 | "Path/To/bomb.zip" | zipBombs.rb:52:3:52:29 | call to read | This file extraction depends on a $@. | zipBombs.rb:2:16:2:33 | "Path/To/bomb.zip" | potentially untrusted source | -| zipBombs.rb:52:3:52:29 | call to read | zipBombs.rb:52:3:52:29 | call to read | zipBombs.rb:52:3:52:29 | call to read | This file extraction depends on a $@. | zipBombs.rb:52:3:52:29 | call to read | potentially untrusted source | +| gzipBombs.rb:6:3:6:34 | call to open | gzipBombs.rb:4:15:4:20 | call to params | gzipBombs.rb:6:3:6:34 | call to open | This file Decompression depends on a $@. | gzipBombs.rb:4:15:4:20 | call to params | potentially untrusted source | +| gzipBombs.rb:7:3:9:5 | call to open | gzipBombs.rb:4:15:4:20 | call to params | gzipBombs.rb:7:3:9:5 | call to open | This file Decompression depends on a $@. | gzipBombs.rb:4:15:4:20 | call to params | potentially untrusted source | +| gzipBombs.rb:10:3:14:5 | call to open | gzipBombs.rb:4:15:4:20 | call to params | gzipBombs.rb:10:3:14:5 | call to open | This file Decompression depends on a $@. | gzipBombs.rb:4:15:4:20 | call to params | potentially untrusted source | +| gzipBombs.rb:15:22:15:53 | call to open | gzipBombs.rb:4:15:4:20 | call to params | gzipBombs.rb:15:22:15:53 | call to open | This file Decompression depends on a $@. | gzipBombs.rb:4:15:4:20 | call to params | potentially untrusted source | +| gzipBombs.rb:20:3:20:50 | call to new | gzipBombs.rb:4:15:4:20 | call to params | gzipBombs.rb:20:3:20:50 | call to new | This file Decompression depends on a $@. | gzipBombs.rb:4:15:4:20 | call to params | potentially untrusted source | +| gzipBombs.rb:21:3:21:50 | call to new | gzipBombs.rb:4:15:4:20 | call to params | gzipBombs.rb:21:3:21:50 | call to new | This file Decompression depends on a $@. | gzipBombs.rb:4:15:4:20 | call to params | potentially untrusted source | +| gzipBombs.rb:25:3:25:40 | call to zcat | gzipBombs.rb:4:15:4:20 | call to params | gzipBombs.rb:25:3:25:40 | call to zcat | This file Decompression depends on a $@. | gzipBombs.rb:4:15:4:20 | call to params | potentially untrusted source | +| zipBombs.rb:6:3:11:5 | call to open | zipBombs.rb:4:18:4:23 | call to params | zipBombs.rb:6:3:11:5 | call to open | This file Decompression depends on a $@. | zipBombs.rb:4:18:4:23 | call to params | potentially untrusted source | +| zipBombs.rb:12:3:14:5 | call to open | zipBombs.rb:4:18:4:23 | call to params | zipBombs.rb:12:3:14:5 | call to open | This file Decompression depends on a $@. | zipBombs.rb:4:18:4:23 | call to params | potentially untrusted source | +| zipBombs.rb:15:11:15:45 | call to open | zipBombs.rb:4:18:4:23 | call to params | zipBombs.rb:15:11:15:45 | call to open | This file Decompression depends on a $@. | zipBombs.rb:4:18:4:23 | call to params | potentially untrusted source | +| zipBombs.rb:17:3:17:42 | call to read | zipBombs.rb:4:18:4:23 | call to params | zipBombs.rb:17:3:17:42 | call to read | This file Decompression depends on a $@. | zipBombs.rb:4:18:4:23 | call to params | potentially untrusted source | +| zipBombs.rb:18:3:18:51 | call to extract | zipBombs.rb:4:18:4:23 | call to params | zipBombs.rb:18:3:18:51 | call to extract | This file Decompression depends on a $@. | zipBombs.rb:4:18:4:23 | call to params | potentially untrusted source | +| zipBombs.rb:28:7:28:33 | call to read | zipBombs.rb:4:18:4:23 | call to params | zipBombs.rb:28:7:28:33 | call to read | This file Decompression depends on a $@. | zipBombs.rb:4:18:4:23 | call to params | potentially untrusted source | +| zipBombs.rb:34:5:34:17 | call to extract | zipBombs.rb:4:18:4:23 | call to params | zipBombs.rb:34:5:34:17 | call to extract | This file Decompression depends on a $@. | zipBombs.rb:4:18:4:23 | call to params | potentially untrusted source | +| zipBombs.rb:35:5:35:31 | call to read | zipBombs.rb:4:18:4:23 | call to params | zipBombs.rb:35:5:35:31 | call to read | This file Decompression depends on a $@. | zipBombs.rb:4:18:4:23 | call to params | potentially untrusted source | +| zipBombs.rb:41:7:41:31 | call to read | zipBombs.rb:4:18:4:23 | call to params | zipBombs.rb:41:7:41:31 | call to read | This file Decompression depends on a $@. | zipBombs.rb:4:18:4:23 | call to params | potentially untrusted source | +| zipBombs.rb:42:7:42:19 | call to extract | zipBombs.rb:4:18:4:23 | call to params | zipBombs.rb:42:7:42:19 | call to extract | This file Decompression depends on a $@. | zipBombs.rb:4:18:4:23 | call to params | potentially untrusted source | +| zipBombs.rb:46:10:46:36 | call to read | zipBombs.rb:4:18:4:23 | call to params | zipBombs.rb:46:10:46:36 | call to read | This file Decompression depends on a $@. | zipBombs.rb:4:18:4:23 | call to params | potentially untrusted source | +| zipBombs.rb:51:8:51:34 | call to read | zipBombs.rb:4:18:4:23 | call to params | zipBombs.rb:51:8:51:34 | call to read | This file Decompression depends on a $@. | zipBombs.rb:4:18:4:23 | call to params | potentially untrusted source | +| zipBombs.rb:55:5:55:31 | call to read | zipBombs.rb:4:18:4:23 | call to params | zipBombs.rb:55:5:55:31 | call to read | This file Decompression depends on a $@. | zipBombs.rb:4:18:4:23 | call to params | potentially untrusted source | diff --git a/ruby/ql/test/query-tests/experimental/CWE-522-DecompressionBombs/gzipBombs.rb b/ruby/ql/test/query-tests/experimental/CWE-522-DecompressionBombs/gzipBombs.rb index ab038dd47ec..bf9bb7b329d 100644 --- a/ruby/ql/test/query-tests/experimental/CWE-522-DecompressionBombs/gzipBombs.rb +++ b/ruby/ql/test/query-tests/experimental/CWE-522-DecompressionBombs/gzipBombs.rb @@ -1,24 +1,27 @@ require 'zlib' -gzip_path = "Path/To/bomb.gz" -Zlib::GzipReader.open(gzip_path).read -Zlib::GzipReader.open(gzip_path) do |uncompressedfile| - puts uncompressedfile.read -end -Zlib::GzipReader.open(gzip_path) do |uncompressedfile| + +class TestController < ActionController::Base + gzip_path = params[:path] + + Zlib::GzipReader.open(gzip_path).read + Zlib::GzipReader.open(gzip_path) do |uncompressedfile| + puts uncompressedfile.read + end + Zlib::GzipReader.open(gzip_path) do |uncompressedfile| + uncompressedfile.each do |entry| + puts entry + end + end + uncompressedfile = Zlib::GzipReader.open(gzip_path) uncompressedfile.each do |entry| puts entry end -end -uncompressedfile = Zlib::GzipReader.open(gzip_path) -uncompressedfile.each do |entry| - puts entry + + Zlib::GzipReader.new(File.open(gzip_path, 'rb')).read + Zlib::GzipReader.new(File.open(gzip_path, 'rb')).each do |entry| + puts entry + end + + Zlib::GzipReader.zcat(open(gzip_path)) end -Zlib::GzipReader.new(File.open(gzip_path, 'rb')).read -Zlib::GzipReader.new(File.open(gzip_path, 'rb')).each do |entry| - puts entry -end - -Zlib::GzipReader.zcat(open(gzip_path)) - - diff --git a/ruby/ql/test/query-tests/experimental/CWE-522-DecompressionBombs/zipBombs.rb b/ruby/ql/test/query-tests/experimental/CWE-522-DecompressionBombs/zipBombs.rb index c0f15b86fce..5aab5ce6382 100644 --- a/ruby/ql/test/query-tests/experimental/CWE-522-DecompressionBombs/zipBombs.rb +++ b/ruby/ql/test/query-tests/experimental/CWE-522-DecompressionBombs/zipBombs.rb @@ -1,55 +1,57 @@ require 'zip' -zipfile_path = "Path/To/bomb.zip" -Zip::InputStream.open(zipfile_path) do |input| - while (entry = input.get_next_entry) - puts :file_name, entry.name - input + +class TestController < ActionController::Base + zipfile_path = params[:path] + + Zip::InputStream.open(zipfile_path) do |input| + while (entry = input.get_next_entry) + puts :file_name, entry.name + input + end end -end -Zip::InputStream.open(zipfile_path) do |input| - input.read -end -input = Zip::InputStream.open(zipfile_path) + Zip::InputStream.open(zipfile_path) do |input| + input.read + end + input = Zip::InputStream.open(zipfile_path) -Zip::File.open(zipfile_path).read "10GB" -Zip::File.open(zipfile_path).extract "10GB", "./" + Zip::File.open(zipfile_path).read "10GB" + Zip::File.open(zipfile_path).extract "10GB", "./" -Zip::File.open(zipfile_path) do |zip_file| - # Handle entries one by one + Zip::File.open(zipfile_path) do |zip_file| + # Handle entries one by one + zip_file.each do |entry| + puts "Extracting #{entry.name}" + raise 'File too large when extracted' if entry.size > MAX_SIZE + # Extract to file or directory based on name in the archive + entry.extract + # Read into memory + entry.get_input_stream.read + end + end + + zip_file = Zip::File.open(zipfile_path) zip_file.each do |entry| - puts "Extracting #{entry.name}" - raise 'File too large when extracted' if entry.size > MAX_SIZE - # Extract to file or directory based on name in the archive entry.extract - # Read into memory + entry.get_input_stream.read + end + + # Find specific entry + Zip::File.open(zipfile_path) do |zip_file| + zip_file.glob('*.xml').each do |entry| + zip_file.read(entry.name) + entry.extract + end + entry = zip_file.glob('*.csv').first + raise 'File too large when extracted' if entry.size > MAX_SIZE + puts entry.get_input_stream.read + end + + zip_file = Zip::File.open(zipfile_path) + entry = zip_file.glob('*.csv') + puts entry.get_input_stream.read + + zip_file = Zip::File.open(zipfile_path) + zip_file.glob('*') do |entry| entry.get_input_stream.read end end - -zip_file = Zip::File.open(zipfile_path) -zip_file.each do |entry| - entry.extract - entry.get_input_stream.read -end - -# Find specific entry -Zip::File.open(zipfile_path) do |zip_file| - zip_file.glob('*.xml').each do |entry| - zip_file.read(entry.name) - entry.extract - end - entry = zip_file.glob('*.csv').first - raise 'File too large when extracted' if entry.size > MAX_SIZE - puts entry.get_input_stream.read -end - -zip_file = Zip::File.open(zipfile_path) -entry = zip_file.glob('*.csv') -puts entry.get_input_stream.read - -zip_file = Zip::File.open(zipfile_path) -zip_file.glob('*') do |entry| - entry.get_input_stream.read -end - -