From e7e0cf5cb3f21f04e45a4373141e0900ed0993ed Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Tue, 16 May 2023 14:45:59 +0100 Subject: [PATCH 01/23] ruby: add Rack::ResponseNode class --- .../codeql/ruby/dataflow/internal/DataFlowPublic.qll | 11 ++++++++--- ruby/ql/lib/codeql/ruby/frameworks/Rack.qll | 6 +++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll index 9d668e0b3001..c076d6d66985 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll @@ -1279,13 +1279,18 @@ class HashLiteralNode extends LocalSourceNode, ExprNode { * into calls to `Array.[]`, so this includes both desugared calls as well as * explicit calls. */ -class ArrayLiteralNode extends LocalSourceNode, ExprNode { - ArrayLiteralNode() { super.getExprNode() instanceof CfgNodes::ExprNodes::ArrayLiteralCfgNode } +class ArrayLiteralNode extends LocalSourceNode, CallNode { + private CfgNodes::ExprNodes::ArrayLiteralCfgNode arrayNode; + + ArrayLiteralNode() { super.getExprNode() = arrayNode } /** * Gets an element of the array. */ - Node getAnElement() { result = this.(CallNode).getPositionalArgument(_) } + Node getAnElement() { result = this.getElement(_) } + + /** Gets the `i`th element of the array. */ + Node getElement(int i) { result = this.getPositionalArgument(i) } } /** diff --git a/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll b/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll index 693cd4c197ce..b5a6242c35af 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll @@ -30,14 +30,14 @@ module Rack { DataFlow::ParameterNode getEnv() { result = call.getParameter(0) } } - private predicate isRackResponse(DataFlow::Node r) { + class ResponseNode extends DataFlow::ArrayLiteralNode { // [status, headers, body] - r.asExpr().(ArrayLiteralCfgNode).getNumberOfArguments() = 3 + ResponseNode() { this.getNumberOfArguments() = 3 } } private DataFlow::LocalSourceNode trackRackResponse(TypeTracker t) { t.start() and - isRackResponse(result) + result instanceof ResponseNode or exists(TypeTracker t2 | result = trackRackResponse(t2).track(t2, t)) } From c87c26687190a898edd0b65f5eb6acde8a2a87ab Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Tue, 16 May 2023 14:47:36 +0100 Subject: [PATCH 02/23] ruby: add Rack::ResponseNode#getAStatusCode --- ruby/ql/lib/codeql/ruby/frameworks/Rack.qll | 16 ++++++++++++++++ .../library-tests/frameworks/rack/Rack.expected | 15 +++++++++++---- .../test/library-tests/frameworks/rack/Rack.ql | 4 ++++ .../test/library-tests/frameworks/rack/rack.rb | 6 +++++- 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll b/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll index b5a6242c35af..ec3673207acf 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll @@ -30,9 +30,25 @@ module Rack { DataFlow::ParameterNode getEnv() { result = call.getParameter(0) } } + private DataFlow::LocalSourceNode trackStatusCode(TypeTracker t, int i) { + t.start() and + result.getConstantValue().isInt(i) + or + exists(TypeTracker t2 | result = trackStatusCode(t2, i).track(t2, t)) + } + + private DataFlow::Node trackStatusCode(int i) { + trackStatusCode(TypeTracker::end(), i).flowsTo(result) + } + class ResponseNode extends DataFlow::ArrayLiteralNode { // [status, headers, body] ResponseNode() { this.getNumberOfArguments() = 3 } + + /** + * Gets an HTTP status code that may be returned in this response. + */ + int getAStatusCode() { this.getElement(0) = trackStatusCode(result) } } private DataFlow::LocalSourceNode trackRackResponse(TypeTracker t) { diff --git a/ruby/ql/test/library-tests/frameworks/rack/Rack.expected b/ruby/ql/test/library-tests/frameworks/rack/Rack.expected index 5613aabd7a48..db76f4545b6f 100644 --- a/ruby/ql/test/library-tests/frameworks/rack/Rack.expected +++ b/ruby/ql/test/library-tests/frameworks/rack/Rack.expected @@ -1,4 +1,11 @@ -| rack.rb:1:1:5:3 | HelloWorld | rack.rb:2:12:2:14 | env | -| rack.rb:7:1:16:3 | Proxy | rack.rb:12:12:12:18 | the_env | -| rack.rb:18:1:31:3 | Logger | rack.rb:24:12:24:14 | env | -| rack.rb:45:1:61:3 | Baz | rack.rb:46:12:46:14 | env | +rackApps +| rack.rb:1:1:9:3 | HelloWorld | rack.rb:2:12:2:14 | env | +| rack.rb:11:1:20:3 | Proxy | rack.rb:16:12:16:18 | the_env | +| rack.rb:22:1:35:3 | Logger | rack.rb:28:12:28:14 | env | +| rack.rb:49:1:65:3 | Baz | rack.rb:50:12:50:14 | env | +rackResponseStatusCodes +| rack.rb:7:5:7:63 | call to [] | 200 | +| rack.rb:7:5:7:63 | call to [] | 500 | +| rack.rb:39:5:39:13 | call to [] | 1 | +| rack.rb:56:7:56:22 | call to [] | 200 | +| rack.rb:63:5:63:21 | call to [] | 400 | diff --git a/ruby/ql/test/library-tests/frameworks/rack/Rack.ql b/ruby/ql/test/library-tests/frameworks/rack/Rack.ql index 560b81c3839b..25c8303853d8 100644 --- a/ruby/ql/test/library-tests/frameworks/rack/Rack.ql +++ b/ruby/ql/test/library-tests/frameworks/rack/Rack.ql @@ -2,3 +2,7 @@ private import codeql.ruby.frameworks.Rack private import codeql.ruby.DataFlow query predicate rackApps(Rack::AppCandidate c, DataFlow::ParameterNode env) { env = c.getEnv() } + +query predicate rackResponseStatusCodes(Rack::ResponseNode resp, int status) { + status = resp.getAStatusCode() +} diff --git a/ruby/ql/test/library-tests/frameworks/rack/rack.rb b/ruby/ql/test/library-tests/frameworks/rack/rack.rb index 03955455787a..c3b7729812b3 100644 --- a/ruby/ql/test/library-tests/frameworks/rack/rack.rb +++ b/ruby/ql/test/library-tests/frameworks/rack/rack.rb @@ -1,6 +1,10 @@ class HelloWorld def call(env) - [200, {'Content-Type' => 'text/plain'}, ['Hello World']] + status = 200 + if something_goes_wrong(env) + status = 500 + end + [status, {'Content-Type' => 'text/plain'}, ['Hello World']] end end From f8d2cbbe7932c11bd97c7bbd7fb064427cc8f601 Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Tue, 16 May 2023 16:40:41 +0100 Subject: [PATCH 03/23] ruby: rack responses implement are HTTP responses --- ruby/ql/lib/codeql/ruby/frameworks/Rack.qll | 44 +++++++++++++------ .../frameworks/rack/Rack.expected | 3 +- .../library-tests/frameworks/rack/Rack.ql | 6 ++- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll b/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll index ec3673207acf..503af8e8533e 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll @@ -2,6 +2,7 @@ * Provides modeling for the Rack library. */ +private import codeql.ruby.Concepts private import codeql.ruby.controlflow.CfgNodes::ExprNodes private import codeql.ruby.DataFlow private import codeql.ruby.typetracking.TypeTracker @@ -17,48 +18,63 @@ module Rack { */ class AppCandidate extends DataFlow::ClassNode { private DataFlow::MethodNode call; + private PotentialResponseNode resp; AppCandidate() { call = this.getInstanceMethod("call") and call.getNumberOfParameters() = 1 and - call.getReturn() = trackRackResponse() + call.getReturn() = trackRackResponse(resp) } /** * Gets the environment of the request, which is the lone parameter to the `call` method. */ DataFlow::ParameterNode getEnv() { result = call.getParameter(0) } + + /** Gets the response returned from the request. */ + PotentialResponseNode getResponse() { result = resp } } - private DataFlow::LocalSourceNode trackStatusCode(TypeTracker t, int i) { + private DataFlow::LocalSourceNode trackInt(TypeTracker t, int i) { t.start() and result.getConstantValue().isInt(i) or - exists(TypeTracker t2 | result = trackStatusCode(t2, i).track(t2, t)) + exists(TypeTracker t2 | result = trackInt(t2, i).track(t2, t)) } - private DataFlow::Node trackStatusCode(int i) { - trackStatusCode(TypeTracker::end(), i).flowsTo(result) - } + private DataFlow::Node trackInt(int i) { trackInt(TypeTracker::end(), i).flowsTo(result) } - class ResponseNode extends DataFlow::ArrayLiteralNode { + private class PotentialResponseNode extends DataFlow::ArrayLiteralNode { // [status, headers, body] - ResponseNode() { this.getNumberOfArguments() = 3 } + PotentialResponseNode() { this.getNumberOfArguments() = 3 } /** * Gets an HTTP status code that may be returned in this response. */ - int getAStatusCode() { this.getElement(0) = trackStatusCode(result) } + int getAStatusCode() { this.getElement(0) = trackInt(result) } } - private DataFlow::LocalSourceNode trackRackResponse(TypeTracker t) { + private DataFlow::LocalSourceNode trackRackResponse(TypeTracker t, PotentialResponseNode n) { t.start() and - result instanceof ResponseNode + result = n or - exists(TypeTracker t2 | result = trackRackResponse(t2).track(t2, t)) + exists(TypeTracker t2 | result = trackRackResponse(t2, n).track(t2, t)) + } + + private DataFlow::Node trackRackResponse(PotentialResponseNode n) { + trackRackResponse(TypeTracker::end(), n).flowsTo(result) } - private DataFlow::Node trackRackResponse() { - trackRackResponse(TypeTracker::end()).flowsTo(result) + /** A `DataFlow::Node` returned from a rack request. */ + class ResponseNode extends PotentialResponseNode, Http::Server::HttpResponse::Range { + ResponseNode() { this = any(AppCandidate app).getResponse() } + + override DataFlow::Node getBody() { result = this.getElement(2) } + + // TODO + override DataFlow::Node getMimetypeOrContentTypeArg() { none() } + + // TODO + override string getMimetypeDefault() { none() } } } diff --git a/ruby/ql/test/library-tests/frameworks/rack/Rack.expected b/ruby/ql/test/library-tests/frameworks/rack/Rack.expected index db76f4545b6f..23fec9a8266e 100644 --- a/ruby/ql/test/library-tests/frameworks/rack/Rack.expected +++ b/ruby/ql/test/library-tests/frameworks/rack/Rack.expected @@ -6,6 +6,7 @@ rackApps rackResponseStatusCodes | rack.rb:7:5:7:63 | call to [] | 200 | | rack.rb:7:5:7:63 | call to [] | 500 | -| rack.rb:39:5:39:13 | call to [] | 1 | +| rack.rb:18:5:18:27 | call to [] | | +| rack.rb:33:5:33:26 | call to [] | | | rack.rb:56:7:56:22 | call to [] | 200 | | rack.rb:63:5:63:21 | call to [] | 400 | diff --git a/ruby/ql/test/library-tests/frameworks/rack/Rack.ql b/ruby/ql/test/library-tests/frameworks/rack/Rack.ql index 25c8303853d8..6e18162a5e15 100644 --- a/ruby/ql/test/library-tests/frameworks/rack/Rack.ql +++ b/ruby/ql/test/library-tests/frameworks/rack/Rack.ql @@ -3,6 +3,8 @@ private import codeql.ruby.DataFlow query predicate rackApps(Rack::AppCandidate c, DataFlow::ParameterNode env) { env = c.getEnv() } -query predicate rackResponseStatusCodes(Rack::ResponseNode resp, int status) { - status = resp.getAStatusCode() +query predicate rackResponseStatusCodes(Rack::ResponseNode resp, string status) { + if exists(resp.getAStatusCode()) + then status = resp.getAStatusCode().toString() + else status = "" } From c3ab867595b79920a4ccbcfd183864831c6aa114 Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Mon, 22 May 2023 09:32:40 +0100 Subject: [PATCH 04/23] ruby: start restructuring rack --- ruby/ql/lib/codeql/ruby/frameworks/Rack.qll | 76 +- .../lib/codeql/ruby/frameworks/rack/Rack.qll | 120 ++ .../frameworks/rack/internal/MimeTypes.qll | 1285 +++++++++++++++++ .../library-tests/frameworks/rack/Rack.ql | 7 + .../library-tests/frameworks/rack/rack.rb | 4 +- 5 files changed, 1416 insertions(+), 76 deletions(-) create mode 100644 ruby/ql/lib/codeql/ruby/frameworks/rack/Rack.qll create mode 100644 ruby/ql/lib/codeql/ruby/frameworks/rack/internal/MimeTypes.qll diff --git a/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll b/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll index 503af8e8533e..ba969ae4c453 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll @@ -1,80 +1,6 @@ -/** - * Provides modeling for the Rack library. - */ - -private import codeql.ruby.Concepts -private import codeql.ruby.controlflow.CfgNodes::ExprNodes -private import codeql.ruby.DataFlow -private import codeql.ruby.typetracking.TypeTracker - /** * Provides modeling for the Rack library. */ module Rack { - /** - * A class that may be a rack application. - * This is a class that has a `call` method that takes a single argument - * (traditionally called `env`) and returns a rack-compatible response. - */ - class AppCandidate extends DataFlow::ClassNode { - private DataFlow::MethodNode call; - private PotentialResponseNode resp; - - AppCandidate() { - call = this.getInstanceMethod("call") and - call.getNumberOfParameters() = 1 and - call.getReturn() = trackRackResponse(resp) - } - - /** - * Gets the environment of the request, which is the lone parameter to the `call` method. - */ - DataFlow::ParameterNode getEnv() { result = call.getParameter(0) } - - /** Gets the response returned from the request. */ - PotentialResponseNode getResponse() { result = resp } - } - - private DataFlow::LocalSourceNode trackInt(TypeTracker t, int i) { - t.start() and - result.getConstantValue().isInt(i) - or - exists(TypeTracker t2 | result = trackInt(t2, i).track(t2, t)) - } - - private DataFlow::Node trackInt(int i) { trackInt(TypeTracker::end(), i).flowsTo(result) } - - private class PotentialResponseNode extends DataFlow::ArrayLiteralNode { - // [status, headers, body] - PotentialResponseNode() { this.getNumberOfArguments() = 3 } - - /** - * Gets an HTTP status code that may be returned in this response. - */ - int getAStatusCode() { this.getElement(0) = trackInt(result) } - } - - private DataFlow::LocalSourceNode trackRackResponse(TypeTracker t, PotentialResponseNode n) { - t.start() and - result = n - or - exists(TypeTracker t2 | result = trackRackResponse(t2, n).track(t2, t)) - } - - private DataFlow::Node trackRackResponse(PotentialResponseNode n) { - trackRackResponse(TypeTracker::end(), n).flowsTo(result) - } - - /** A `DataFlow::Node` returned from a rack request. */ - class ResponseNode extends PotentialResponseNode, Http::Server::HttpResponse::Range { - ResponseNode() { this = any(AppCandidate app).getResponse() } - - override DataFlow::Node getBody() { result = this.getElement(2) } - - // TODO - override DataFlow::Node getMimetypeOrContentTypeArg() { none() } - - // TODO - override string getMimetypeDefault() { none() } - } + import rack.Rack } diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/Rack.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/Rack.qll new file mode 100644 index 000000000000..b570f276c511 --- /dev/null +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/Rack.qll @@ -0,0 +1,120 @@ +/** + * Provides modeling for the Rack library. + */ + +private import codeql.ruby.AST +private import codeql.ruby.ApiGraphs +private import codeql.ruby.Concepts +private import codeql.ruby.controlflow.CfgNodes::ExprNodes +private import codeql.ruby.DataFlow +private import codeql.ruby.typetracking.TypeTracker +private import internal.MimeTypes + +/** + * A class that may be a rack application. + * This is a class that has a `call` method that takes a single argument + * (traditionally called `env`) and returns a rack-compatible response. + */ +class AppCandidate extends DataFlow::ClassNode { + private DataFlow::MethodNode call; + private PotentialResponseNode resp; + + AppCandidate() { + call = this.getInstanceMethod("call") and + call.getNumberOfParameters() = 1 and + call.getReturn() = trackRackResponse(resp) + } + + /** + * Gets the environment of the request, which is the lone parameter to the `call` method. + */ + DataFlow::ParameterNode getEnv() { result = call.getParameter(0) } + + /** Gets the response returned from the request. */ + PotentialResponseNode getResponse() { result = resp } +} + +private DataFlow::LocalSourceNode trackInt(TypeTracker t, int i) { + t.start() and + result.getConstantValue().isInt(i) + or + exists(TypeTracker t2 | result = trackInt(t2, i).track(t2, t)) +} + +private DataFlow::Node trackInt(int i) { trackInt(TypeTracker::end(), i).flowsTo(result) } + +private class PotentialResponseNode extends DataFlow::ArrayLiteralNode { + // [status, headers, body] + PotentialResponseNode() { this.getNumberOfArguments() = 3 } + + /** + * Gets an HTTP status code that may be returned in this response. + */ + int getAStatusCode() { this.getElement(0) = trackInt(result) } + + /** Gets the headers returned with this response. */ + DataFlow::Node getHeaders() { result = this.getElement(1) } + + /** Gets the body of this response. */ + DataFlow::Node getBody() { result = this.getElement(2) } +} + +private DataFlow::LocalSourceNode trackRackResponse(TypeTracker t, PotentialResponseNode n) { + t.start() and + result = n + or + exists(TypeTracker t2 | result = trackRackResponse(t2, n).track(t2, t)) +} + +private DataFlow::Node trackRackResponse(PotentialResponseNode n) { + trackRackResponse(TypeTracker::end(), n).flowsTo(result) +} + +class MimetypeCall extends DataFlow::CallNode { + MimetypeCall() { + this = API::getTopLevelMember("Rack").getMember("Mime").getAMethodCall("mime_type") + } + + private string getExtension() { + result = this.getArgument(0).getConstantValue().getStringlikeValue() + } + + string getMimeType() { mimeTypeMatches(this.getExtension(), result) } +} + +/** A `DataFlow::Node` returned from a rack request. */ +class ResponseNode extends PotentialResponseNode, Http::Server::HttpResponse::Range { + ResponseNode() { this = any(AppCandidate app).getResponse() } + + override DataFlow::Node getBody() { result = this.getElement(2) } + + override DataFlow::Node getMimetypeOrContentTypeArg() { + exists(DataFlow::Node headers | headers = this.getHeaders() | + // set via `headers.content_type=` + exists( + DataFlow::CallNode contentTypeAssignment, Assignment assignment, + DataFlow::PostUpdateNode postUpdateHeaders + | + contentTypeAssignment.getMethodName() = "content_type=" and + assignment = + contentTypeAssignment.getArgument(0).(DataFlow::OperationNode).asOperationAstNode() and + postUpdateHeaders.(DataFlow::LocalSourceNode).flowsTo(headers) and + postUpdateHeaders.getPreUpdateNode() = contentTypeAssignment.getReceiver() + | + result.asExpr().getExpr() = assignment.getRightOperand() + ) + or + // set within a hash + exists(DataFlow::HashLiteralNode headersHash | headersHash.flowsTo(headers) | + result = + headersHash + .getElementFromKey(any(ConstantValue v | + v.getStringlikeValue().toLowerCase() = "content-type" + )) + ) + ) + } + + // TODO + override string getMimetypeDefault() { none() } +} diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/MimeTypes.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/MimeTypes.qll new file mode 100644 index 000000000000..ed5bad4b8a61 --- /dev/null +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/MimeTypes.qll @@ -0,0 +1,1285 @@ +predicate mimeTypeMatches(string ext, string mimeType) { + ext = ".123" and mimeType = "application/vnd.lotus-1-2-3" + or + ext = ".3dml" and mimeType = "text/vnd.in3d.3dml" + or + ext = ".3g2" and mimeType = "video/3gpp2" + or + ext = ".3gp" and mimeType = "video/3gpp" + or + ext = ".a" and mimeType = "application/octet-stream" + or + ext = ".acc" and mimeType = "application/vnd.americandynamics.acc" + or + ext = ".ace" and mimeType = "application/x-ace-compressed" + or + ext = ".acu" and mimeType = "application/vnd.acucobol" + or + ext = ".aep" and mimeType = "application/vnd.audiograph" + or + ext = ".afp" and mimeType = "application/vnd.ibm.modcap" + or + ext = ".ai" and mimeType = "application/postscript" + or + ext = ".aif" and mimeType = "audio/x-aiff" + or + ext = ".aiff" and mimeType = "audio/x-aiff" + or + ext = ".ami" and mimeType = "application/vnd.amiga.ami" + or + ext = ".apng" and mimeType = "image/apng" + or + ext = ".appcache" and mimeType = "text/cache-manifest" + or + ext = ".apr" and mimeType = "application/vnd.lotus-approach" + or + ext = ".asc" and mimeType = "application/pgp-signature" + or + ext = ".asf" and mimeType = "video/x-ms-asf" + or + ext = ".asm" and mimeType = "text/x-asm" + or + ext = ".aso" and mimeType = "application/vnd.accpac.simply.aso" + or + ext = ".asx" and mimeType = "video/x-ms-asf" + or + ext = ".atc" and mimeType = "application/vnd.acucorp" + or + ext = ".atom" and mimeType = "application/atom+xml" + or + ext = ".atomcat" and mimeType = "application/atomcat+xml" + or + ext = ".atomsvc" and mimeType = "application/atomsvc+xml" + or + ext = ".atx" and mimeType = "application/vnd.antix.game-component" + or + ext = ".au" and mimeType = "audio/basic" + or + ext = ".avi" and mimeType = "video/x-msvideo" + or + ext = ".avif" and mimeType = "image/avif" + or + ext = ".bat" and mimeType = "application/x-msdownload" + or + ext = ".bcpio" and mimeType = "application/x-bcpio" + or + ext = ".bdm" and mimeType = "application/vnd.syncml.dm+wbxml" + or + ext = ".bh2" and mimeType = "application/vnd.fujitsu.oasysprs" + or + ext = ".bin" and mimeType = "application/octet-stream" + or + ext = ".bmi" and mimeType = "application/vnd.bmi" + or + ext = ".bmp" and mimeType = "image/bmp" + or + ext = ".box" and mimeType = "application/vnd.previewsystems.box" + or + ext = ".btif" and mimeType = "image/prs.btif" + or + ext = ".bz" and mimeType = "application/x-bzip" + or + ext = ".bz2" and mimeType = "application/x-bzip2" + or + ext = ".c" and mimeType = "text/x-c" + or + ext = ".c4g" and mimeType = "application/vnd.clonk.c4group" + or + ext = ".cab" and mimeType = "application/vnd.ms-cab-compressed" + or + ext = ".cc" and mimeType = "text/x-c" + or + ext = ".ccxml" and mimeType = "application/ccxml+xml" + or + ext = ".cdbcmsg" and mimeType = "application/vnd.contact.cmsg" + or + ext = ".cdkey" and mimeType = "application/vnd.mediastation.cdkey" + or + ext = ".cdx" and mimeType = "chemical/x-cdx" + or + ext = ".cdxml" and mimeType = "application/vnd.chemdraw+xml" + or + ext = ".cdy" and mimeType = "application/vnd.cinderella" + or + ext = ".cer" and mimeType = "application/pkix-cert" + or + ext = ".cgm" and mimeType = "image/cgm" + or + ext = ".chat" and mimeType = "application/x-chat" + or + ext = ".chm" and mimeType = "application/vnd.ms-htmlhelp" + or + ext = ".chrt" and mimeType = "application/vnd.kde.kchart" + or + ext = ".cif" and mimeType = "chemical/x-cif" + or + ext = ".cii" and mimeType = "application/vnd.anser-web-certificate-issue-initiation" + or + ext = ".cil" and mimeType = "application/vnd.ms-artgalry" + or + ext = ".cla" and mimeType = "application/vnd.claymore" + or + ext = ".class" and mimeType = "application/octet-stream" + or + ext = ".clkk" and mimeType = "application/vnd.crick.clicker.keyboard" + or + ext = ".clkp" and mimeType = "application/vnd.crick.clicker.palette" + or + ext = ".clkt" and mimeType = "application/vnd.crick.clicker.template" + or + ext = ".clkw" and mimeType = "application/vnd.crick.clicker.wordbank" + or + ext = ".clkx" and mimeType = "application/vnd.crick.clicker" + or + ext = ".clp" and mimeType = "application/x-msclip" + or + ext = ".cmc" and mimeType = "application/vnd.cosmocaller" + or + ext = ".cmdf" and mimeType = "chemical/x-cmdf" + or + ext = ".cml" and mimeType = "chemical/x-cml" + or + ext = ".cmp" and mimeType = "application/vnd.yellowriver-custom-menu" + or + ext = ".cmx" and mimeType = "image/x-cmx" + or + ext = ".com" and mimeType = "application/x-msdownload" + or + ext = ".conf" and mimeType = "text/plain" + or + ext = ".cpio" and mimeType = "application/x-cpio" + or + ext = ".cpp" and mimeType = "text/x-c" + or + ext = ".cpt" and mimeType = "application/mac-compactpro" + or + ext = ".crd" and mimeType = "application/x-mscardfile" + or + ext = ".crl" and mimeType = "application/pkix-crl" + or + ext = ".crt" and mimeType = "application/x-x509-ca-cert" + or + ext = ".csh" and mimeType = "application/x-csh" + or + ext = ".csml" and mimeType = "chemical/x-csml" + or + ext = ".csp" and mimeType = "application/vnd.commonspace" + or + ext = ".css" and mimeType = "text/css" + or + ext = ".csv" and mimeType = "text/csv" + or + ext = ".curl" and mimeType = "application/vnd.curl" + or + ext = ".cww" and mimeType = "application/prs.cww" + or + ext = ".cxx" and mimeType = "text/x-c" + or + ext = ".daf" and mimeType = "application/vnd.mobius.daf" + or + ext = ".davmount" and mimeType = "application/davmount+xml" + or + ext = ".dcr" and mimeType = "application/x-director" + or + ext = ".dd2" and mimeType = "application/vnd.oma.dd2+xml" + or + ext = ".ddd" and mimeType = "application/vnd.fujixerox.ddd" + or + ext = ".deb" and mimeType = "application/x-debian-package" + or + ext = ".der" and mimeType = "application/x-x509-ca-cert" + or + ext = ".dfac" and mimeType = "application/vnd.dreamfactory" + or + ext = ".diff" and mimeType = "text/x-diff" + or + ext = ".dis" and mimeType = "application/vnd.mobius.dis" + or + ext = ".djv" and mimeType = "image/vnd.djvu" + or + ext = ".djvu" and mimeType = "image/vnd.djvu" + or + ext = ".dll" and mimeType = "application/x-msdownload" + or + ext = ".dmg" and mimeType = "application/octet-stream" + or + ext = ".dna" and mimeType = "application/vnd.dna" + or + ext = ".doc" and mimeType = "application/msword" + or + ext = ".docm" and mimeType = "application/vnd.ms-word.document.macroEnabled.12" + or + ext = ".docx" and + mimeType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document" + or + ext = ".dot" and mimeType = "application/msword" + or + ext = ".dotm" and mimeType = "application/vnd.ms-word.template.macroEnabled.12" + or + ext = ".dotx" and + mimeType = "application/vnd.openxmlformats-officedocument.wordprocessingml.template" + or + ext = ".dp" and mimeType = "application/vnd.osgi.dp" + or + ext = ".dpg" and mimeType = "application/vnd.dpgraph" + or + ext = ".dsc" and mimeType = "text/prs.lines.tag" + or + ext = ".dtd" and mimeType = "application/xml-dtd" + or + ext = ".dts" and mimeType = "audio/vnd.dts" + or + ext = ".dtshd" and mimeType = "audio/vnd.dts.hd" + or + ext = ".dv" and mimeType = "video/x-dv" + or + ext = ".dvi" and mimeType = "application/x-dvi" + or + ext = ".dwf" and mimeType = "model/vnd.dwf" + or + ext = ".dwg" and mimeType = "image/vnd.dwg" + or + ext = ".dxf" and mimeType = "image/vnd.dxf" + or + ext = ".dxp" and mimeType = "application/vnd.spotfire.dxp" + or + ext = ".ear" and mimeType = "application/java-archive" + or + ext = ".ecelp4800" and mimeType = "audio/vnd.nuera.ecelp4800" + or + ext = ".ecelp7470" and mimeType = "audio/vnd.nuera.ecelp7470" + or + ext = ".ecelp9600" and mimeType = "audio/vnd.nuera.ecelp9600" + or + ext = ".ecma" and mimeType = "application/ecmascript" + or + ext = ".edm" and mimeType = "application/vnd.novadigm.edm" + or + ext = ".edx" and mimeType = "application/vnd.novadigm.edx" + or + ext = ".efif" and mimeType = "application/vnd.picsel" + or + ext = ".ei6" and mimeType = "application/vnd.pg.osasli" + or + ext = ".eml" and mimeType = "message/rfc822" + or + ext = ".eol" and mimeType = "audio/vnd.digital-winds" + or + ext = ".eot" and mimeType = "application/vnd.ms-fontobject" + or + ext = ".eps" and mimeType = "application/postscript" + or + ext = ".es3" and mimeType = "application/vnd.eszigno3+xml" + or + ext = ".esf" and mimeType = "application/vnd.epson.esf" + or + ext = ".etx" and mimeType = "text/x-setext" + or + ext = ".exe" and mimeType = "application/x-msdownload" + or + ext = ".ext" and mimeType = "application/vnd.novadigm.ext" + or + ext = ".ez" and mimeType = "application/andrew-inset" + or + ext = ".ez2" and mimeType = "application/vnd.ezpix-album" + or + ext = ".ez3" and mimeType = "application/vnd.ezpix-package" + or + ext = ".f" and mimeType = "text/x-fortran" + or + ext = ".f77" and mimeType = "text/x-fortran" + or + ext = ".f90" and mimeType = "text/x-fortran" + or + ext = ".fbs" and mimeType = "image/vnd.fastbidsheet" + or + ext = ".fdf" and mimeType = "application/vnd.fdf" + or + ext = ".fe_launch" and mimeType = "application/vnd.denovo.fcselayout-link" + or + ext = ".fg5" and mimeType = "application/vnd.fujitsu.oasysgp" + or + ext = ".fli" and mimeType = "video/x-fli" + or + ext = ".flif" and mimeType = "image/flif" + or + ext = ".flo" and mimeType = "application/vnd.micrografx.flo" + or + ext = ".flv" and mimeType = "video/x-flv" + or + ext = ".flw" and mimeType = "application/vnd.kde.kivio" + or + ext = ".flx" and mimeType = "text/vnd.fmi.flexstor" + or + ext = ".fly" and mimeType = "text/vnd.fly" + or + ext = ".fm" and mimeType = "application/vnd.framemaker" + or + ext = ".fnc" and mimeType = "application/vnd.frogans.fnc" + or + ext = ".for" and mimeType = "text/x-fortran" + or + ext = ".fpx" and mimeType = "image/vnd.fpx" + or + ext = ".fsc" and mimeType = "application/vnd.fsc.weblaunch" + or + ext = ".fst" and mimeType = "image/vnd.fst" + or + ext = ".ftc" and mimeType = "application/vnd.fluxtime.clip" + or + ext = ".fti" and mimeType = "application/vnd.anser-web-funds-transfer-initiation" + or + ext = ".fvt" and mimeType = "video/vnd.fvt" + or + ext = ".fzs" and mimeType = "application/vnd.fuzzysheet" + or + ext = ".g3" and mimeType = "image/g3fax" + or + ext = ".gac" and mimeType = "application/vnd.groove-account" + or + ext = ".gdl" and mimeType = "model/vnd.gdl" + or + ext = ".gem" and mimeType = "application/octet-stream" + or + ext = ".gemspec" and mimeType = "text/x-script.ruby" + or + ext = ".ghf" and mimeType = "application/vnd.groove-help" + or + ext = ".gif" and mimeType = "image/gif" + or + ext = ".gim" and mimeType = "application/vnd.groove-identity-message" + or + ext = ".gmx" and mimeType = "application/vnd.gmx" + or + ext = ".gph" and mimeType = "application/vnd.flographit" + or + ext = ".gqf" and mimeType = "application/vnd.grafeq" + or + ext = ".gram" and mimeType = "application/srgs" + or + ext = ".grv" and mimeType = "application/vnd.groove-injector" + or + ext = ".grxml" and mimeType = "application/srgs+xml" + or + ext = ".gtar" and mimeType = "application/x-gtar" + or + ext = ".gtm" and mimeType = "application/vnd.groove-tool-message" + or + ext = ".gtw" and mimeType = "model/vnd.gtw" + or + ext = ".gv" and mimeType = "text/vnd.graphviz" + or + ext = ".gz" and mimeType = "application/x-gzip" + or + ext = ".h" and mimeType = "text/x-c" + or + ext = ".h261" and mimeType = "video/h261" + or + ext = ".h263" and mimeType = "video/h263" + or + ext = ".h264" and mimeType = "video/h264" + or + ext = ".hbci" and mimeType = "application/vnd.hbci" + or + ext = ".hdf" and mimeType = "application/x-hdf" + or + ext = ".heic" and mimeType = "image/heic" + or + ext = ".heics" and mimeType = "image/heic-sequence" + or + ext = ".heif" and mimeType = "image/heif" + or + ext = ".heifs" and mimeType = "image/heif-sequence" + or + ext = ".hh" and mimeType = "text/x-c" + or + ext = ".hlp" and mimeType = "application/winhlp" + or + ext = ".hpgl" and mimeType = "application/vnd.hp-hpgl" + or + ext = ".hpid" and mimeType = "application/vnd.hp-hpid" + or + ext = ".hps" and mimeType = "application/vnd.hp-hps" + or + ext = ".hqx" and mimeType = "application/mac-binhex40" + or + ext = ".htc" and mimeType = "text/x-component" + or + ext = ".htke" and mimeType = "application/vnd.kenameaapp" + or + ext = ".htm" and mimeType = "text/html" + or + ext = ".html" and mimeType = "text/html" + or + ext = ".hvd" and mimeType = "application/vnd.yamaha.hv-dic" + or + ext = ".hvp" and mimeType = "application/vnd.yamaha.hv-voice" + or + ext = ".hvs" and mimeType = "application/vnd.yamaha.hv-script" + or + ext = ".icc" and mimeType = "application/vnd.iccprofile" + or + ext = ".ice" and mimeType = "x-conference/x-cooltalk" + or + ext = ".ico" and mimeType = "image/vnd.microsoft.icon" + or + ext = ".ics" and mimeType = "text/calendar" + or + ext = ".ief" and mimeType = "image/ief" + or + ext = ".ifb" and mimeType = "text/calendar" + or + ext = ".ifm" and mimeType = "application/vnd.shana.informed.formdata" + or + ext = ".igl" and mimeType = "application/vnd.igloader" + or + ext = ".igs" and mimeType = "model/iges" + or + ext = ".igx" and mimeType = "application/vnd.micrografx.igx" + or + ext = ".iif" and mimeType = "application/vnd.shana.informed.interchange" + or + ext = ".imp" and mimeType = "application/vnd.accpac.simply.imp" + or + ext = ".ims" and mimeType = "application/vnd.ms-ims" + or + ext = ".ipk" and mimeType = "application/vnd.shana.informed.package" + or + ext = ".irm" and mimeType = "application/vnd.ibm.rights-management" + or + ext = ".irp" and mimeType = "application/vnd.irepository.package+xml" + or + ext = ".iso" and mimeType = "application/octet-stream" + or + ext = ".itp" and mimeType = "application/vnd.shana.informed.formtemplate" + or + ext = ".ivp" and mimeType = "application/vnd.immervision-ivp" + or + ext = ".ivu" and mimeType = "application/vnd.immervision-ivu" + or + ext = ".jad" and mimeType = "text/vnd.sun.j2me.app-descriptor" + or + ext = ".jam" and mimeType = "application/vnd.jam" + or + ext = ".jar" and mimeType = "application/java-archive" + or + ext = ".java" and mimeType = "text/x-java-source" + or + ext = ".jisp" and mimeType = "application/vnd.jisp" + or + ext = ".jlt" and mimeType = "application/vnd.hp-jlyt" + or + ext = ".jnlp" and mimeType = "application/x-java-jnlp-file" + or + ext = ".joda" and mimeType = "application/vnd.joost.joda-archive" + or + ext = ".jp2" and mimeType = "image/jp2" + or + ext = ".jpeg" and mimeType = "image/jpeg" + or + ext = ".jpg" and mimeType = "image/jpeg" + or + ext = ".jpgv" and mimeType = "video/jpeg" + or + ext = ".jpm" and mimeType = "video/jpm" + or + ext = ".js" and mimeType = "application/javascript" + or + ext = ".json" and mimeType = "application/json" + or + ext = ".karbon" and mimeType = "application/vnd.kde.karbon" + or + ext = ".kfo" and mimeType = "application/vnd.kde.kformula" + or + ext = ".kia" and mimeType = "application/vnd.kidspiration" + or + ext = ".kml" and mimeType = "application/vnd.google-earth.kml+xml" + or + ext = ".kmz" and mimeType = "application/vnd.google-earth.kmz" + or + ext = ".kne" and mimeType = "application/vnd.kinar" + or + ext = ".kon" and mimeType = "application/vnd.kde.kontour" + or + ext = ".kpr" and mimeType = "application/vnd.kde.kpresenter" + or + ext = ".ksp" and mimeType = "application/vnd.kde.kspread" + or + ext = ".ktz" and mimeType = "application/vnd.kahootz" + or + ext = ".kwd" and mimeType = "application/vnd.kde.kword" + or + ext = ".latex" and mimeType = "application/x-latex" + or + ext = ".lbd" and mimeType = "application/vnd.llamagraphics.life-balance.desktop" + or + ext = ".lbe" and mimeType = "application/vnd.llamagraphics.life-balance.exchange+xml" + or + ext = ".les" and mimeType = "application/vnd.hhe.lesson-player" + or + ext = ".link66" and mimeType = "application/vnd.route66.link66+xml" + or + ext = ".log" and mimeType = "text/plain" + or + ext = ".lostxml" and mimeType = "application/lost+xml" + or + ext = ".lrm" and mimeType = "application/vnd.ms-lrm" + or + ext = ".ltf" and mimeType = "application/vnd.frogans.ltf" + or + ext = ".lvp" and mimeType = "audio/vnd.lucent.voice" + or + ext = ".lwp" and mimeType = "application/vnd.lotus-wordpro" + or + ext = ".m3u" and mimeType = "audio/x-mpegurl" + or + ext = ".m3u8" and mimeType = "application/x-mpegurl" + or + ext = ".m4a" and mimeType = "audio/mp4a-latm" + or + ext = ".m4v" and mimeType = "video/mp4" + or + ext = ".ma" and mimeType = "application/mathematica" + or + ext = ".mag" and mimeType = "application/vnd.ecowin.chart" + or + ext = ".man" and mimeType = "text/troff" + or + ext = ".manifest" and mimeType = "text/cache-manifest" + or + ext = ".mathml" and mimeType = "application/mathml+xml" + or + ext = ".mbk" and mimeType = "application/vnd.mobius.mbk" + or + ext = ".mbox" and mimeType = "application/mbox" + or + ext = ".mc1" and mimeType = "application/vnd.medcalcdata" + or + ext = ".mcd" and mimeType = "application/vnd.mcd" + or + ext = ".mdb" and mimeType = "application/x-msaccess" + or + ext = ".mdi" and mimeType = "image/vnd.ms-modi" + or + ext = ".mdoc" and mimeType = "text/troff" + or + ext = ".me" and mimeType = "text/troff" + or + ext = ".mfm" and mimeType = "application/vnd.mfmp" + or + ext = ".mgz" and mimeType = "application/vnd.proteus.magazine" + or + ext = ".mid" and mimeType = "audio/midi" + or + ext = ".midi" and mimeType = "audio/midi" + or + ext = ".mif" and mimeType = "application/vnd.mif" + or + ext = ".mime" and mimeType = "message/rfc822" + or + ext = ".mj2" and mimeType = "video/mj2" + or + ext = ".mlp" and mimeType = "application/vnd.dolby.mlp" + or + ext = ".mmd" and mimeType = "application/vnd.chipnuts.karaoke-mmd" + or + ext = ".mmf" and mimeType = "application/vnd.smaf" + or + ext = ".mml" and mimeType = "application/mathml+xml" + or + ext = ".mmr" and mimeType = "image/vnd.fujixerox.edmics-mmr" + or + ext = ".mng" and mimeType = "video/x-mng" + or + ext = ".mny" and mimeType = "application/x-msmoney" + or + ext = ".mov" and mimeType = "video/quicktime" + or + ext = ".movie" and mimeType = "video/x-sgi-movie" + or + ext = ".mp3" and mimeType = "audio/mpeg" + or + ext = ".mp4" and mimeType = "video/mp4" + or + ext = ".mp4a" and mimeType = "audio/mp4" + or + ext = ".mp4s" and mimeType = "application/mp4" + or + ext = ".mp4v" and mimeType = "video/mp4" + or + ext = ".mpc" and mimeType = "application/vnd.mophun.certificate" + or + ext = ".mpd" and mimeType = "application/dash+xml" + or + ext = ".mpeg" and mimeType = "video/mpeg" + or + ext = ".mpg" and mimeType = "video/mpeg" + or + ext = ".mpga" and mimeType = "audio/mpeg" + or + ext = ".mpkg" and mimeType = "application/vnd.apple.installer+xml" + or + ext = ".mpm" and mimeType = "application/vnd.blueice.multipass" + or + ext = ".mpn" and mimeType = "application/vnd.mophun.application" + or + ext = ".mpp" and mimeType = "application/vnd.ms-project" + or + ext = ".mpy" and mimeType = "application/vnd.ibm.minipay" + or + ext = ".mqy" and mimeType = "application/vnd.mobius.mqy" + or + ext = ".mrc" and mimeType = "application/marc" + or + ext = ".ms" and mimeType = "text/troff" + or + ext = ".mscml" and mimeType = "application/mediaservercontrol+xml" + or + ext = ".mseq" and mimeType = "application/vnd.mseq" + or + ext = ".msf" and mimeType = "application/vnd.epson.msf" + or + ext = ".msh" and mimeType = "model/mesh" + or + ext = ".msi" and mimeType = "application/x-msdownload" + or + ext = ".msl" and mimeType = "application/vnd.mobius.msl" + or + ext = ".msty" and mimeType = "application/vnd.muvee.style" + or + ext = ".mts" and mimeType = "model/vnd.mts" + or + ext = ".mus" and mimeType = "application/vnd.musician" + or + ext = ".mvb" and mimeType = "application/x-msmediaview" + or + ext = ".mwf" and mimeType = "application/vnd.mfer" + or + ext = ".mxf" and mimeType = "application/mxf" + or + ext = ".mxl" and mimeType = "application/vnd.recordare.musicxml" + or + ext = ".mxml" and mimeType = "application/xv+xml" + or + ext = ".mxs" and mimeType = "application/vnd.triscape.mxs" + or + ext = ".mxu" and mimeType = "video/vnd.mpegurl" + or + ext = ".n" and mimeType = "application/vnd.nokia.n-gage.symbian.install" + or + ext = ".nc" and mimeType = "application/x-netcdf" + or + ext = ".ngdat" and mimeType = "application/vnd.nokia.n-gage.data" + or + ext = ".nlu" and mimeType = "application/vnd.neurolanguage.nlu" + or + ext = ".nml" and mimeType = "application/vnd.enliven" + or + ext = ".nnd" and mimeType = "application/vnd.noblenet-directory" + or + ext = ".nns" and mimeType = "application/vnd.noblenet-sealer" + or + ext = ".nnw" and mimeType = "application/vnd.noblenet-web" + or + ext = ".npx" and mimeType = "image/vnd.net-fpx" + or + ext = ".nsf" and mimeType = "application/vnd.lotus-notes" + or + ext = ".oa2" and mimeType = "application/vnd.fujitsu.oasys2" + or + ext = ".oa3" and mimeType = "application/vnd.fujitsu.oasys3" + or + ext = ".oas" and mimeType = "application/vnd.fujitsu.oasys" + or + ext = ".obd" and mimeType = "application/x-msbinder" + or + ext = ".oda" and mimeType = "application/oda" + or + ext = ".odc" and mimeType = "application/vnd.oasis.opendocument.chart" + or + ext = ".odf" and mimeType = "application/vnd.oasis.opendocument.formula" + or + ext = ".odg" and mimeType = "application/vnd.oasis.opendocument.graphics" + or + ext = ".odi" and mimeType = "application/vnd.oasis.opendocument.image" + or + ext = ".odp" and mimeType = "application/vnd.oasis.opendocument.presentation" + or + ext = ".ods" and mimeType = "application/vnd.oasis.opendocument.spreadsheet" + or + ext = ".odt" and mimeType = "application/vnd.oasis.opendocument.text" + or + ext = ".oga" and mimeType = "audio/ogg" + or + ext = ".ogg" and mimeType = "application/ogg" + or + ext = ".ogv" and mimeType = "video/ogg" + or + ext = ".ogx" and mimeType = "application/ogg" + or + ext = ".org" and mimeType = "application/vnd.lotus-organizer" + or + ext = ".otc" and mimeType = "application/vnd.oasis.opendocument.chart-template" + or + ext = ".otf" and mimeType = "application/vnd.oasis.opendocument.formula-template" + or + ext = ".otg" and mimeType = "application/vnd.oasis.opendocument.graphics-template" + or + ext = ".oth" and mimeType = "application/vnd.oasis.opendocument.text-web" + or + ext = ".oti" and mimeType = "application/vnd.oasis.opendocument.image-template" + or + ext = ".otm" and mimeType = "application/vnd.oasis.opendocument.text-master" + or + ext = ".ots" and mimeType = "application/vnd.oasis.opendocument.spreadsheet-template" + or + ext = ".ott" and mimeType = "application/vnd.oasis.opendocument.text-template" + or + ext = ".oxt" and mimeType = "application/vnd.openofficeorg.extension" + or + ext = ".p" and mimeType = "text/x-pascal" + or + ext = ".p10" and mimeType = "application/pkcs10" + or + ext = ".p12" and mimeType = "application/x-pkcs12" + or + ext = ".p7b" and mimeType = "application/x-pkcs7-certificates" + or + ext = ".p7m" and mimeType = "application/pkcs7-mime" + or + ext = ".p7r" and mimeType = "application/x-pkcs7-certreqresp" + or + ext = ".p7s" and mimeType = "application/pkcs7-signature" + or + ext = ".pas" and mimeType = "text/x-pascal" + or + ext = ".pbd" and mimeType = "application/vnd.powerbuilder6" + or + ext = ".pbm" and mimeType = "image/x-portable-bitmap" + or + ext = ".pcl" and mimeType = "application/vnd.hp-pcl" + or + ext = ".pclxl" and mimeType = "application/vnd.hp-pclxl" + or + ext = ".pcx" and mimeType = "image/x-pcx" + or + ext = ".pdb" and mimeType = "chemical/x-pdb" + or + ext = ".pdf" and mimeType = "application/pdf" + or + ext = ".pem" and mimeType = "application/x-x509-ca-cert" + or + ext = ".pfr" and mimeType = "application/font-tdpfr" + or + ext = ".pgm" and mimeType = "image/x-portable-graymap" + or + ext = ".pgn" and mimeType = "application/x-chess-pgn" + or + ext = ".pgp" and mimeType = "application/pgp-encrypted" + or + ext = ".pic" and mimeType = "image/x-pict" + or + ext = ".pict" and mimeType = "image/pict" + or + ext = ".pkg" and mimeType = "application/octet-stream" + or + ext = ".pki" and mimeType = "application/pkixcmp" + or + ext = ".pkipath" and mimeType = "application/pkix-pkipath" + or + ext = ".pl" and mimeType = "text/x-script.perl" + or + ext = ".plb" and mimeType = "application/vnd.3gpp.pic-bw-large" + or + ext = ".plc" and mimeType = "application/vnd.mobius.plc" + or + ext = ".plf" and mimeType = "application/vnd.pocketlearn" + or + ext = ".pls" and mimeType = "application/pls+xml" + or + ext = ".pm" and mimeType = "text/x-script.perl-module" + or + ext = ".pml" and mimeType = "application/vnd.ctc-posml" + or + ext = ".png" and mimeType = "image/png" + or + ext = ".pnm" and mimeType = "image/x-portable-anymap" + or + ext = ".pntg" and mimeType = "image/x-macpaint" + or + ext = ".portpkg" and mimeType = "application/vnd.macports.portpkg" + or + ext = ".pot" and mimeType = "application/vnd.ms-powerpoint" + or + ext = ".potm" and mimeType = "application/vnd.ms-powerpoint.template.macroEnabled.12" + or + ext = ".potx" and + mimeType = "application/vnd.openxmlformats-officedocument.presentationml.template" + or + ext = ".ppa" and mimeType = "application/vnd.ms-powerpoint" + or + ext = ".ppam" and mimeType = "application/vnd.ms-powerpoint.addin.macroEnabled.12" + or + ext = ".ppd" and mimeType = "application/vnd.cups-ppd" + or + ext = ".ppm" and mimeType = "image/x-portable-pixmap" + or + ext = ".pps" and mimeType = "application/vnd.ms-powerpoint" + or + ext = ".ppsm" and mimeType = "application/vnd.ms-powerpoint.slideshow.macroEnabled.12" + or + ext = ".ppsx" and + mimeType = "application/vnd.openxmlformats-officedocument.presentationml.slideshow" + or + ext = ".ppt" and mimeType = "application/vnd.ms-powerpoint" + or + ext = ".pptm" and mimeType = "application/vnd.ms-powerpoint.presentation.macroEnabled.12" + or + ext = ".pptx" and + mimeType = "application/vnd.openxmlformats-officedocument.presentationml.presentation" + or + ext = ".prc" and mimeType = "application/vnd.palm" + or + ext = ".pre" and mimeType = "application/vnd.lotus-freelance" + or + ext = ".prf" and mimeType = "application/pics-rules" + or + ext = ".ps" and mimeType = "application/postscript" + or + ext = ".psb" and mimeType = "application/vnd.3gpp.pic-bw-small" + or + ext = ".psd" and mimeType = "image/vnd.adobe.photoshop" + or + ext = ".ptid" and mimeType = "application/vnd.pvi.ptid1" + or + ext = ".pub" and mimeType = "application/x-mspublisher" + or + ext = ".pvb" and mimeType = "application/vnd.3gpp.pic-bw-var" + or + ext = ".pwn" and mimeType = "application/vnd.3m.post-it-notes" + or + ext = ".py" and mimeType = "text/x-script.python" + or + ext = ".pya" and mimeType = "audio/vnd.ms-playready.media.pya" + or + ext = ".pyv" and mimeType = "video/vnd.ms-playready.media.pyv" + or + ext = ".qam" and mimeType = "application/vnd.epson.quickanime" + or + ext = ".qbo" and mimeType = "application/vnd.intu.qbo" + or + ext = ".qfx" and mimeType = "application/vnd.intu.qfx" + or + ext = ".qps" and mimeType = "application/vnd.publishare-delta-tree" + or + ext = ".qt" and mimeType = "video/quicktime" + or + ext = ".qtif" and mimeType = "image/x-quicktime" + or + ext = ".qxd" and mimeType = "application/vnd.quark.quarkxpress" + or + ext = ".ra" and mimeType = "audio/x-pn-realaudio" + or + ext = ".rake" and mimeType = "text/x-script.ruby" + or + ext = ".ram" and mimeType = "audio/x-pn-realaudio" + or + ext = ".rar" and mimeType = "application/x-rar-compressed" + or + ext = ".ras" and mimeType = "image/x-cmu-raster" + or + ext = ".rb" and mimeType = "text/x-script.ruby" + or + ext = ".rcprofile" and mimeType = "application/vnd.ipunplugged.rcprofile" + or + ext = ".rdf" and mimeType = "application/rdf+xml" + or + ext = ".rdz" and mimeType = "application/vnd.data-vision.rdz" + or + ext = ".rep" and mimeType = "application/vnd.businessobjects" + or + ext = ".rgb" and mimeType = "image/x-rgb" + or + ext = ".rif" and mimeType = "application/reginfo+xml" + or + ext = ".rl" and mimeType = "application/resource-lists+xml" + or + ext = ".rlc" and mimeType = "image/vnd.fujixerox.edmics-rlc" + or + ext = ".rld" and mimeType = "application/resource-lists-diff+xml" + or + ext = ".rm" and mimeType = "application/vnd.rn-realmedia" + or + ext = ".rmp" and mimeType = "audio/x-pn-realaudio-plugin" + or + ext = ".rms" and mimeType = "application/vnd.jcp.javame.midlet-rms" + or + ext = ".rnc" and mimeType = "application/relax-ng-compact-syntax" + or + ext = ".roff" and mimeType = "text/troff" + or + ext = ".rpm" and mimeType = "application/x-redhat-package-manager" + or + ext = ".rpss" and mimeType = "application/vnd.nokia.radio-presets" + or + ext = ".rpst" and mimeType = "application/vnd.nokia.radio-preset" + or + ext = ".rq" and mimeType = "application/sparql-query" + or + ext = ".rs" and mimeType = "application/rls-services+xml" + or + ext = ".rsd" and mimeType = "application/rsd+xml" + or + ext = ".rss" and mimeType = "application/rss+xml" + or + ext = ".rtf" and mimeType = "application/rtf" + or + ext = ".rtx" and mimeType = "text/richtext" + or + ext = ".ru" and mimeType = "text/x-script.ruby" + or + ext = ".s" and mimeType = "text/x-asm" + or + ext = ".saf" and mimeType = "application/vnd.yamaha.smaf-audio" + or + ext = ".sbml" and mimeType = "application/sbml+xml" + or + ext = ".sc" and mimeType = "application/vnd.ibm.secure-container" + or + ext = ".scd" and mimeType = "application/x-msschedule" + or + ext = ".scm" and mimeType = "application/vnd.lotus-screencam" + or + ext = ".scq" and mimeType = "application/scvp-cv-request" + or + ext = ".scs" and mimeType = "application/scvp-cv-response" + or + ext = ".sdkm" and mimeType = "application/vnd.solent.sdkm+xml" + or + ext = ".sdp" and mimeType = "application/sdp" + or + ext = ".see" and mimeType = "application/vnd.seemail" + or + ext = ".sema" and mimeType = "application/vnd.sema" + or + ext = ".semd" and mimeType = "application/vnd.semd" + or + ext = ".semf" and mimeType = "application/vnd.semf" + or + ext = ".setpay" and mimeType = "application/set-payment-initiation" + or + ext = ".setreg" and mimeType = "application/set-registration-initiation" + or + ext = ".sfd" and mimeType = "application/vnd.hydrostatix.sof-data" + or + ext = ".sfs" and mimeType = "application/vnd.spotfire.sfs" + or + ext = ".sgm" and mimeType = "text/sgml" + or + ext = ".sgml" and mimeType = "text/sgml" + or + ext = ".sh" and mimeType = "application/x-sh" + or + ext = ".shar" and mimeType = "application/x-shar" + or + ext = ".shf" and mimeType = "application/shf+xml" + or + ext = ".sig" and mimeType = "application/pgp-signature" + or + ext = ".sit" and mimeType = "application/x-stuffit" + or + ext = ".sitx" and mimeType = "application/x-stuffitx" + or + ext = ".skp" and mimeType = "application/vnd.koan" + or + ext = ".slt" and mimeType = "application/vnd.epson.salt" + or + ext = ".smi" and mimeType = "application/smil+xml" + or + ext = ".snd" and mimeType = "audio/basic" + or + ext = ".so" and mimeType = "application/octet-stream" + or + ext = ".spf" and mimeType = "application/vnd.yamaha.smaf-phrase" + or + ext = ".spl" and mimeType = "application/x-futuresplash" + or + ext = ".spot" and mimeType = "text/vnd.in3d.spot" + or + ext = ".spp" and mimeType = "application/scvp-vp-response" + or + ext = ".spq" and mimeType = "application/scvp-vp-request" + or + ext = ".src" and mimeType = "application/x-wais-source" + or + ext = ".srt" and mimeType = "text/srt" + or + ext = ".srx" and mimeType = "application/sparql-results+xml" + or + ext = ".sse" and mimeType = "application/vnd.kodak-descriptor" + or + ext = ".ssf" and mimeType = "application/vnd.epson.ssf" + or + ext = ".ssml" and mimeType = "application/ssml+xml" + or + ext = ".stf" and mimeType = "application/vnd.wt.stf" + or + ext = ".stk" and mimeType = "application/hyperstudio" + or + ext = ".str" and mimeType = "application/vnd.pg.format" + or + ext = ".sus" and mimeType = "application/vnd.sus-calendar" + or + ext = ".sv4cpio" and mimeType = "application/x-sv4cpio" + or + ext = ".sv4crc" and mimeType = "application/x-sv4crc" + or + ext = ".svd" and mimeType = "application/vnd.svd" + or + ext = ".svg" and mimeType = "image/svg+xml" + or + ext = ".svgz" and mimeType = "image/svg+xml" + or + ext = ".swf" and mimeType = "application/x-shockwave-flash" + or + ext = ".swi" and mimeType = "application/vnd.arastra.swi" + or + ext = ".t" and mimeType = "text/troff" + or + ext = ".tao" and mimeType = "application/vnd.tao.intent-module-archive" + or + ext = ".tar" and mimeType = "application/x-tar" + or + ext = ".tbz" and mimeType = "application/x-bzip-compressed-tar" + or + ext = ".tcap" and mimeType = "application/vnd.3gpp2.tcap" + or + ext = ".tcl" and mimeType = "application/x-tcl" + or + ext = ".tex" and mimeType = "application/x-tex" + or + ext = ".texi" and mimeType = "application/x-texinfo" + or + ext = ".texinfo" and mimeType = "application/x-texinfo" + or + ext = ".text" and mimeType = "text/plain" + or + ext = ".tif" and mimeType = "image/tiff" + or + ext = ".tiff" and mimeType = "image/tiff" + or + ext = ".tmo" and mimeType = "application/vnd.tmobile-livetv" + or + ext = ".torrent" and mimeType = "application/x-bittorrent" + or + ext = ".tpl" and mimeType = "application/vnd.groove-tool-template" + or + ext = ".tpt" and mimeType = "application/vnd.trid.tpt" + or + ext = ".tr" and mimeType = "text/troff" + or + ext = ".tra" and mimeType = "application/vnd.trueapp" + or + ext = ".trm" and mimeType = "application/x-msterminal" + or + ext = ".ts" and mimeType = "video/mp2t" + or + ext = ".tsv" and mimeType = "text/tab-separated-values" + or + ext = ".ttf" and mimeType = "application/octet-stream" + or + ext = ".twd" and mimeType = "application/vnd.simtech-mindmapper" + or + ext = ".txd" and mimeType = "application/vnd.genomatix.tuxedo" + or + ext = ".txf" and mimeType = "application/vnd.mobius.txf" + or + ext = ".txt" and mimeType = "text/plain" + or + ext = ".ufd" and mimeType = "application/vnd.ufdl" + or + ext = ".umj" and mimeType = "application/vnd.umajin" + or + ext = ".unityweb" and mimeType = "application/vnd.unity" + or + ext = ".uoml" and mimeType = "application/vnd.uoml+xml" + or + ext = ".uri" and mimeType = "text/uri-list" + or + ext = ".ustar" and mimeType = "application/x-ustar" + or + ext = ".utz" and mimeType = "application/vnd.uiq.theme" + or + ext = ".uu" and mimeType = "text/x-uuencode" + or + ext = ".vcd" and mimeType = "application/x-cdlink" + or + ext = ".vcf" and mimeType = "text/x-vcard" + or + ext = ".vcg" and mimeType = "application/vnd.groove-vcard" + or + ext = ".vcs" and mimeType = "text/x-vcalendar" + or + ext = ".vcx" and mimeType = "application/vnd.vcx" + or + ext = ".vis" and mimeType = "application/vnd.visionary" + or + ext = ".viv" and mimeType = "video/vnd.vivo" + or + ext = ".vrml" and mimeType = "model/vrml" + or + ext = ".vsd" and mimeType = "application/vnd.visio" + or + ext = ".vsf" and mimeType = "application/vnd.vsf" + or + ext = ".vtt" and mimeType = "text/vtt" + or + ext = ".vtu" and mimeType = "model/vnd.vtu" + or + ext = ".vxml" and mimeType = "application/voicexml+xml" + or + ext = ".war" and mimeType = "application/java-archive" + or + ext = ".wasm" and mimeType = "application/wasm" + or + ext = ".wav" and mimeType = "audio/x-wav" + or + ext = ".wax" and mimeType = "audio/x-ms-wax" + or + ext = ".wbmp" and mimeType = "image/vnd.wap.wbmp" + or + ext = ".wbs" and mimeType = "application/vnd.criticaltools.wbs+xml" + or + ext = ".wbxml" and mimeType = "application/vnd.wap.wbxml" + or + ext = ".webm" and mimeType = "video/webm" + or + ext = ".webp" and mimeType = "image/webp" + or + ext = ".wm" and mimeType = "video/x-ms-wm" + or + ext = ".wma" and mimeType = "audio/x-ms-wma" + or + ext = ".wmd" and mimeType = "application/x-ms-wmd" + or + ext = ".wmf" and mimeType = "application/x-msmetafile" + or + ext = ".wml" and mimeType = "text/vnd.wap.wml" + or + ext = ".wmlc" and mimeType = "application/vnd.wap.wmlc" + or + ext = ".wmls" and mimeType = "text/vnd.wap.wmlscript" + or + ext = ".wmlsc" and mimeType = "application/vnd.wap.wmlscriptc" + or + ext = ".wmv" and mimeType = "video/x-ms-wmv" + or + ext = ".wmx" and mimeType = "video/x-ms-wmx" + or + ext = ".wmz" and mimeType = "application/x-ms-wmz" + or + ext = ".woff" and mimeType = "application/font-woff" + or + ext = ".woff2" and mimeType = "application/font-woff2" + or + ext = ".wpd" and mimeType = "application/vnd.wordperfect" + or + ext = ".wpl" and mimeType = "application/vnd.ms-wpl" + or + ext = ".wps" and mimeType = "application/vnd.ms-works" + or + ext = ".wqd" and mimeType = "application/vnd.wqd" + or + ext = ".wri" and mimeType = "application/x-mswrite" + or + ext = ".wrl" and mimeType = "model/vrml" + or + ext = ".wsdl" and mimeType = "application/wsdl+xml" + or + ext = ".wspolicy" and mimeType = "application/wspolicy+xml" + or + ext = ".wtb" and mimeType = "application/vnd.webturbo" + or + ext = ".wvx" and mimeType = "video/x-ms-wvx" + or + ext = ".x3d" and mimeType = "application/vnd.hzn-3d-crossword" + or + ext = ".xar" and mimeType = "application/vnd.xara" + or + ext = ".xbd" and mimeType = "application/vnd.fujixerox.docuworks.binder" + or + ext = ".xbm" and mimeType = "image/x-xbitmap" + or + ext = ".xdm" and mimeType = "application/vnd.syncml.dm+xml" + or + ext = ".xdp" and mimeType = "application/vnd.adobe.xdp+xml" + or + ext = ".xdw" and mimeType = "application/vnd.fujixerox.docuworks" + or + ext = ".xenc" and mimeType = "application/xenc+xml" + or + ext = ".xer" and mimeType = "application/patch-ops-error+xml" + or + ext = ".xfdf" and mimeType = "application/vnd.adobe.xfdf" + or + ext = ".xfdl" and mimeType = "application/vnd.xfdl" + or + ext = ".xhtml" and mimeType = "application/xhtml+xml" + or + ext = ".xif" and mimeType = "image/vnd.xiff" + or + ext = ".xla" and mimeType = "application/vnd.ms-excel" + or + ext = ".xlam" and mimeType = "application/vnd.ms-excel.addin.macroEnabled.12" + or + ext = ".xls" and mimeType = "application/vnd.ms-excel" + or + ext = ".xlsb" and mimeType = "application/vnd.ms-excel.sheet.binary.macroEnabled.12" + or + ext = ".xlsx" and mimeType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + or + ext = ".xlsm" and mimeType = "application/vnd.ms-excel.sheet.macroEnabled.12" + or + ext = ".xlt" and mimeType = "application/vnd.ms-excel" + or + ext = ".xltx" and + mimeType = "application/vnd.openxmlformats-officedocument.spreadsheetml.template" + or + ext = ".xml" and mimeType = "application/xml" + or + ext = ".xo" and mimeType = "application/vnd.olpc-sugar" + or + ext = ".xop" and mimeType = "application/xop+xml" + or + ext = ".xpm" and mimeType = "image/x-xpixmap" + or + ext = ".xpr" and mimeType = "application/vnd.is-xpr" + or + ext = ".xps" and mimeType = "application/vnd.ms-xpsdocument" + or + ext = ".xpw" and mimeType = "application/vnd.intercon.formnet" + or + ext = ".xsl" and mimeType = "application/xml" + or + ext = ".xslt" and mimeType = "application/xslt+xml" + or + ext = ".xsm" and mimeType = "application/vnd.syncml+xml" + or + ext = ".xspf" and mimeType = "application/xspf+xml" + or + ext = ".xul" and mimeType = "application/vnd.mozilla.xul+xml" + or + ext = ".xwd" and mimeType = "image/x-xwindowdump" + or + ext = ".xyz" and mimeType = "chemical/x-xyz" + or + ext = ".yaml" and mimeType = "text/yaml" + or + ext = ".yml" and mimeType = "text/yaml" + or + ext = ".zaz" and mimeType = "application/vnd.zzazz.deck+xml" + or + ext = ".zip" and mimeType = "application/zip" + or + ext = ".zmm" and mimeType = "application/vnd.handheld-entertainment+xml" +} diff --git a/ruby/ql/test/library-tests/frameworks/rack/Rack.ql b/ruby/ql/test/library-tests/frameworks/rack/Rack.ql index 6e18162a5e15..489531bdba4c 100644 --- a/ruby/ql/test/library-tests/frameworks/rack/Rack.ql +++ b/ruby/ql/test/library-tests/frameworks/rack/Rack.ql @@ -1,3 +1,4 @@ +private import codeql.ruby.AST private import codeql.ruby.frameworks.Rack private import codeql.ruby.DataFlow @@ -8,3 +9,9 @@ query predicate rackResponseStatusCodes(Rack::ResponseNode resp, string status) then status = resp.getAStatusCode().toString() else status = "" } + +query predicate rackResponseContentTypes(Rack::ResponseNode resp, DataFlow::Node contentType) { + contentType = resp.getMimetypeOrContentTypeArg() +} + +query predicate mimetypeCalls(Rack::MimetypeCall c, string mimetype) { mimetype = c.getMimeType() } diff --git a/ruby/ql/test/library-tests/frameworks/rack/rack.rb b/ruby/ql/test/library-tests/frameworks/rack/rack.rb index c3b7729812b3..2478faee3fc9 100644 --- a/ruby/ql/test/library-tests/frameworks/rack/rack.rb +++ b/ruby/ql/test/library-tests/frameworks/rack/rack.rb @@ -4,7 +4,8 @@ def call(env) if something_goes_wrong(env) status = 500 end - [status, {'Content-Type' => 'text/plain'}, ['Hello World']] + headers = {'Content-Type' => 'text/plain'} + [status, headers, ['Hello World']] end end @@ -15,6 +16,7 @@ def initialize(app) def call(the_env) status, headers, body = @app.call(the_env) + headers.content_type = Rack::Mime.mime_type(".gz") [status, headers, body] end end From b2958f87b2e7bdde32f182030888befffb872bdf Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Mon, 22 May 2023 13:56:53 +0100 Subject: [PATCH 05/23] ruby: rack - add redirect responses --- .../lib/codeql/ruby/frameworks/rack/Rack.qll | 59 +++++++++++-------- .../library-tests/frameworks/rack/Rack.ql | 4 ++ .../library-tests/frameworks/rack/rack.rb | 8 +++ 3 files changed, 47 insertions(+), 24 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/Rack.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/Rack.qll index b570f276c511..a36c4ba043f1 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/rack/Rack.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/Rack.qll @@ -82,6 +82,34 @@ class MimetypeCall extends DataFlow::CallNode { string getMimeType() { mimeTypeMatches(this.getExtension(), result) } } +bindingset[headerName] +private DataFlow::Node getHeaderValue(ResponseNode resp, string headerName) { + exists(DataFlow::Node headers | headers = resp.getHeaders() | + // set via `headers.=` + exists( + DataFlow::CallNode contentTypeAssignment, Assignment assignment, + DataFlow::PostUpdateNode postUpdateHeaders + | + contentTypeAssignment.getMethodName() = headerName.replaceAll("-", "_").toLowerCase() + "=" and + assignment = + contentTypeAssignment.getArgument(0).(DataFlow::OperationNode).asOperationAstNode() and + postUpdateHeaders.(DataFlow::LocalSourceNode).flowsTo(headers) and + postUpdateHeaders.getPreUpdateNode() = contentTypeAssignment.getReceiver() + | + result.asExpr().getExpr() = assignment.getRightOperand() + ) + or + // set within a hash + exists(DataFlow::HashLiteralNode headersHash | headersHash.flowsTo(headers) | + result = + headersHash + .getElementFromKey(any(ConstantValue v | + v.getStringlikeValue().toLowerCase() = headerName.toLowerCase() + )) + ) + ) +} + /** A `DataFlow::Node` returned from a rack request. */ class ResponseNode extends PotentialResponseNode, Http::Server::HttpResponse::Range { ResponseNode() { this = any(AppCandidate app).getResponse() } @@ -89,32 +117,15 @@ class ResponseNode extends PotentialResponseNode, Http::Server::HttpResponse::Ra override DataFlow::Node getBody() { result = this.getElement(2) } override DataFlow::Node getMimetypeOrContentTypeArg() { - exists(DataFlow::Node headers | headers = this.getHeaders() | - // set via `headers.content_type=` - exists( - DataFlow::CallNode contentTypeAssignment, Assignment assignment, - DataFlow::PostUpdateNode postUpdateHeaders - | - contentTypeAssignment.getMethodName() = "content_type=" and - assignment = - contentTypeAssignment.getArgument(0).(DataFlow::OperationNode).asOperationAstNode() and - postUpdateHeaders.(DataFlow::LocalSourceNode).flowsTo(headers) and - postUpdateHeaders.getPreUpdateNode() = contentTypeAssignment.getReceiver() - | - result.asExpr().getExpr() = assignment.getRightOperand() - ) - or - // set within a hash - exists(DataFlow::HashLiteralNode headersHash | headersHash.flowsTo(headers) | - result = - headersHash - .getElementFromKey(any(ConstantValue v | - v.getStringlikeValue().toLowerCase() = "content-type" - )) - ) - ) + result = getHeaderValue(this, "content-type") } // TODO override string getMimetypeDefault() { none() } } + +class RedirectResponse extends ResponseNode, Http::Server::HttpRedirectResponse::Range { + RedirectResponse() { this.getAStatusCode() = [300, 301, 302, 303, 307, 308] } + + override DataFlow::Node getRedirectLocation() { result = getHeaderValue(this, "location") } +} diff --git a/ruby/ql/test/library-tests/frameworks/rack/Rack.ql b/ruby/ql/test/library-tests/frameworks/rack/Rack.ql index 489531bdba4c..b4299d9d6f9c 100644 --- a/ruby/ql/test/library-tests/frameworks/rack/Rack.ql +++ b/ruby/ql/test/library-tests/frameworks/rack/Rack.ql @@ -15,3 +15,7 @@ query predicate rackResponseContentTypes(Rack::ResponseNode resp, DataFlow::Node } query predicate mimetypeCalls(Rack::MimetypeCall c, string mimetype) { mimetype = c.getMimeType() } + +query predicate redirectResponses(Rack::RedirectResponse resp, DataFlow::Node location) { + location = resp.getRedirectLocation() +} diff --git a/ruby/ql/test/library-tests/frameworks/rack/rack.rb b/ruby/ql/test/library-tests/frameworks/rack/rack.rb index 2478faee3fc9..c2e2598e5ec8 100644 --- a/ruby/ql/test/library-tests/frameworks/rack/rack.rb +++ b/ruby/ql/test/library-tests/frameworks/rack/rack.rb @@ -36,6 +36,14 @@ def call(env) end end +class Redirector + def call(env) + status = 302 + headers = {'location' => '/foo.html'} + [status, headers, ['this is a redirect']] + end +end + class Foo def not_call(env) [1, 2, 3] From a5a15f380400c4999057ec13cbf2a1d69443d960 Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Wed, 24 May 2023 15:49:59 +0100 Subject: [PATCH 06/23] Ruby: restructure rack model --- .../ruby/frameworks/ActionController.qll | 2 +- ruby/ql/lib/codeql/ruby/frameworks/Rack.qll | 7 +- .../lib/codeql/ruby/frameworks/rack/Rack.qll | 131 ------------------ .../ruby/frameworks/rack/internal/App.qll | 41 ++++++ .../rack/internal/{MimeTypes.qll => Mime.qll} | 17 +++ .../frameworks/rack/internal/Response.qll | 84 +++++++++++ .../library-tests/frameworks/rack/Rack.ql | 16 ++- 7 files changed, 160 insertions(+), 138 deletions(-) delete mode 100644 ruby/ql/lib/codeql/ruby/frameworks/rack/Rack.qll create mode 100644 ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll rename ruby/ql/lib/codeql/ruby/frameworks/rack/internal/{MimeTypes.qll => Mime.qll} (98%) create mode 100644 ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll diff --git a/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll b/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll index 480a1f780350..5899f38411d3 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll @@ -326,7 +326,7 @@ private module Request { private import codeql.ruby.frameworks.Rack private class RackEnv extends Env { - RackEnv() { this = any(Rack::AppCandidate app).getEnv().getALocalUse() } + RackEnv() { this = any(Rack::App::AppCandidate app).getEnv().getALocalUse() } } /** diff --git a/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll b/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll index ba969ae4c453..64ca7cc0b601 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll @@ -2,5 +2,10 @@ * Provides modeling for the Rack library. */ module Rack { - import rack.Rack + import rack.internal.App + import rack.internal.Mime + import rack.internal.Response::Public as Response + + /** DEPRECATED: Alias for App::AppCandidate */ + deprecated class AppCandidate = App::AppCandidate; } diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/Rack.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/Rack.qll deleted file mode 100644 index a36c4ba043f1..000000000000 --- a/ruby/ql/lib/codeql/ruby/frameworks/rack/Rack.qll +++ /dev/null @@ -1,131 +0,0 @@ -/** - * Provides modeling for the Rack library. - */ - -private import codeql.ruby.AST -private import codeql.ruby.ApiGraphs -private import codeql.ruby.Concepts -private import codeql.ruby.controlflow.CfgNodes::ExprNodes -private import codeql.ruby.DataFlow -private import codeql.ruby.typetracking.TypeTracker -private import internal.MimeTypes - -/** - * A class that may be a rack application. - * This is a class that has a `call` method that takes a single argument - * (traditionally called `env`) and returns a rack-compatible response. - */ -class AppCandidate extends DataFlow::ClassNode { - private DataFlow::MethodNode call; - private PotentialResponseNode resp; - - AppCandidate() { - call = this.getInstanceMethod("call") and - call.getNumberOfParameters() = 1 and - call.getReturn() = trackRackResponse(resp) - } - - /** - * Gets the environment of the request, which is the lone parameter to the `call` method. - */ - DataFlow::ParameterNode getEnv() { result = call.getParameter(0) } - - /** Gets the response returned from the request. */ - PotentialResponseNode getResponse() { result = resp } -} - -private DataFlow::LocalSourceNode trackInt(TypeTracker t, int i) { - t.start() and - result.getConstantValue().isInt(i) - or - exists(TypeTracker t2 | result = trackInt(t2, i).track(t2, t)) -} - -private DataFlow::Node trackInt(int i) { trackInt(TypeTracker::end(), i).flowsTo(result) } - -private class PotentialResponseNode extends DataFlow::ArrayLiteralNode { - // [status, headers, body] - PotentialResponseNode() { this.getNumberOfArguments() = 3 } - - /** - * Gets an HTTP status code that may be returned in this response. - */ - int getAStatusCode() { this.getElement(0) = trackInt(result) } - - /** Gets the headers returned with this response. */ - DataFlow::Node getHeaders() { result = this.getElement(1) } - - /** Gets the body of this response. */ - DataFlow::Node getBody() { result = this.getElement(2) } -} - -private DataFlow::LocalSourceNode trackRackResponse(TypeTracker t, PotentialResponseNode n) { - t.start() and - result = n - or - exists(TypeTracker t2 | result = trackRackResponse(t2, n).track(t2, t)) -} - -private DataFlow::Node trackRackResponse(PotentialResponseNode n) { - trackRackResponse(TypeTracker::end(), n).flowsTo(result) -} - -class MimetypeCall extends DataFlow::CallNode { - MimetypeCall() { - this = API::getTopLevelMember("Rack").getMember("Mime").getAMethodCall("mime_type") - } - - private string getExtension() { - result = this.getArgument(0).getConstantValue().getStringlikeValue() - } - - string getMimeType() { mimeTypeMatches(this.getExtension(), result) } -} - -bindingset[headerName] -private DataFlow::Node getHeaderValue(ResponseNode resp, string headerName) { - exists(DataFlow::Node headers | headers = resp.getHeaders() | - // set via `headers.=` - exists( - DataFlow::CallNode contentTypeAssignment, Assignment assignment, - DataFlow::PostUpdateNode postUpdateHeaders - | - contentTypeAssignment.getMethodName() = headerName.replaceAll("-", "_").toLowerCase() + "=" and - assignment = - contentTypeAssignment.getArgument(0).(DataFlow::OperationNode).asOperationAstNode() and - postUpdateHeaders.(DataFlow::LocalSourceNode).flowsTo(headers) and - postUpdateHeaders.getPreUpdateNode() = contentTypeAssignment.getReceiver() - | - result.asExpr().getExpr() = assignment.getRightOperand() - ) - or - // set within a hash - exists(DataFlow::HashLiteralNode headersHash | headersHash.flowsTo(headers) | - result = - headersHash - .getElementFromKey(any(ConstantValue v | - v.getStringlikeValue().toLowerCase() = headerName.toLowerCase() - )) - ) - ) -} - -/** A `DataFlow::Node` returned from a rack request. */ -class ResponseNode extends PotentialResponseNode, Http::Server::HttpResponse::Range { - ResponseNode() { this = any(AppCandidate app).getResponse() } - - override DataFlow::Node getBody() { result = this.getElement(2) } - - override DataFlow::Node getMimetypeOrContentTypeArg() { - result = getHeaderValue(this, "content-type") - } - - // TODO - override string getMimetypeDefault() { none() } -} - -class RedirectResponse extends ResponseNode, Http::Server::HttpRedirectResponse::Range { - RedirectResponse() { this.getAStatusCode() = [300, 301, 302, 303, 307, 308] } - - override DataFlow::Node getRedirectLocation() { result = getHeaderValue(this, "location") } -} diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll new file mode 100644 index 000000000000..7dbd7c7a840d --- /dev/null +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll @@ -0,0 +1,41 @@ +private import codeql.ruby.ApiGraphs +private import codeql.ruby.DataFlow +private import codeql.ruby.typetracking.TypeTracker +private import Response::Private as RP + +private DataFlow::LocalSourceNode trackRackResponse(TypeTracker t, RP::PotentialResponseNode n) { + t.start() and + result = n + or + exists(TypeTracker t2 | result = trackRackResponse(t2, n).track(t2, t)) +} + +private DataFlow::Node trackRackResponse(RP::PotentialResponseNode n) { + trackRackResponse(TypeTracker::end(), n).flowsTo(result) +} + +module App { + /** + * A class that may be a rack application. + * This is a class that has a `call` method that takes a single argument + * (traditionally called `env`) and returns a rack-compatible response. + */ + class AppCandidate extends DataFlow::ClassNode { + private DataFlow::MethodNode call; + private RP::PotentialResponseNode resp; + + AppCandidate() { + call = this.getInstanceMethod("call") and + call.getNumberOfParameters() = 1 and + call.getReturn() = trackRackResponse(resp) + } + + /** + * Gets the environment of the request, which is the lone parameter to the `call` method. + */ + DataFlow::ParameterNode getEnv() { result = call.getParameter(0) } + + /** Gets the response returned from the request. */ + RP::PotentialResponseNode getResponse() { result = resp } + } +} diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/MimeTypes.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll similarity index 98% rename from ruby/ql/lib/codeql/ruby/frameworks/rack/internal/MimeTypes.qll rename to ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll index ed5bad4b8a61..502fe72fa51f 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/MimeTypes.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll @@ -1,3 +1,6 @@ +private import codeql.ruby.ApiGraphs +private import codeql.ruby.DataFlow + predicate mimeTypeMatches(string ext, string mimeType) { ext = ".123" and mimeType = "application/vnd.lotus-1-2-3" or @@ -1283,3 +1286,17 @@ predicate mimeTypeMatches(string ext, string mimeType) { or ext = ".zmm" and mimeType = "application/vnd.handheld-entertainment+xml" } + +module Mime { + class MimetypeCall extends DataFlow::CallNode { + MimetypeCall() { + this = API::getTopLevelMember("Rack").getMember("Mime").getAMethodCall("mime_type") + } + + private string getExtension() { + result = this.getArgument(0).getConstantValue().getStringlikeValue() + } + + string getMimeType() { mimeTypeMatches(this.getExtension(), result) } + } +} diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll new file mode 100644 index 000000000000..f7fb1d31177f --- /dev/null +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll @@ -0,0 +1,84 @@ +private import codeql.ruby.AST +private import codeql.ruby.ApiGraphs +private import codeql.ruby.Concepts +private import codeql.ruby.controlflow.CfgNodes::ExprNodes +private import codeql.ruby.DataFlow +private import codeql.ruby.typetracking.TypeTracker +private import App as A + +module Private { + private DataFlow::LocalSourceNode trackInt(TypeTracker t, int i) { + t.start() and + result.getConstantValue().isInt(i) + or + exists(TypeTracker t2 | result = trackInt(t2, i).track(t2, t)) + } + + private DataFlow::Node trackInt(int i) { trackInt(TypeTracker::end(), i).flowsTo(result) } + + class PotentialResponseNode extends DataFlow::ArrayLiteralNode { + // [status, headers, body] + PotentialResponseNode() { this.getNumberOfArguments() = 3 } + + /** + * Gets an HTTP status code that may be returned in this response. + */ + int getAStatusCode() { this.getElement(0) = trackInt(result) } + + /** Gets the headers returned with this response. */ + DataFlow::Node getHeaders() { result = this.getElement(1) } + + /** Gets the body of this response. */ + DataFlow::Node getBody() { result = this.getElement(2) } + } +} + +module Public { + bindingset[headerName] + private DataFlow::Node getHeaderValue(ResponseNode resp, string headerName) { + exists(DataFlow::Node headers | headers = resp.getHeaders() | + // set via `headers.=` + exists( + DataFlow::CallNode contentTypeAssignment, Assignment assignment, + DataFlow::PostUpdateNode postUpdateHeaders + | + contentTypeAssignment.getMethodName() = headerName.replaceAll("-", "_").toLowerCase() + "=" and + assignment = + contentTypeAssignment.getArgument(0).(DataFlow::OperationNode).asOperationAstNode() and + postUpdateHeaders.(DataFlow::LocalSourceNode).flowsTo(headers) and + postUpdateHeaders.getPreUpdateNode() = contentTypeAssignment.getReceiver() + | + result.asExpr().getExpr() = assignment.getRightOperand() + ) + or + // set within a hash + exists(DataFlow::HashLiteralNode headersHash | headersHash.flowsTo(headers) | + result = + headersHash + .getElementFromKey(any(ConstantValue v | + v.getStringlikeValue().toLowerCase() = headerName.toLowerCase() + )) + ) + ) + } + + /** A `DataFlow::Node` returned from a rack request. */ + class ResponseNode extends Private::PotentialResponseNode, Http::Server::HttpResponse::Range { + ResponseNode() { this = any(A::App::AppCandidate app).getResponse() } + + override DataFlow::Node getBody() { result = this.getElement(2) } + + override DataFlow::Node getMimetypeOrContentTypeArg() { + result = getHeaderValue(this, "content-type") + } + + // TODO + override string getMimetypeDefault() { none() } + } + + class RedirectResponse extends ResponseNode, Http::Server::HttpRedirectResponse::Range { + RedirectResponse() { this.getAStatusCode() = [300, 301, 302, 303, 307, 308] } + + override DataFlow::Node getRedirectLocation() { result = getHeaderValue(this, "location") } + } +} diff --git a/ruby/ql/test/library-tests/frameworks/rack/Rack.ql b/ruby/ql/test/library-tests/frameworks/rack/Rack.ql index b4299d9d6f9c..8e0bcee42440 100644 --- a/ruby/ql/test/library-tests/frameworks/rack/Rack.ql +++ b/ruby/ql/test/library-tests/frameworks/rack/Rack.ql @@ -2,20 +2,26 @@ private import codeql.ruby.AST private import codeql.ruby.frameworks.Rack private import codeql.ruby.DataFlow -query predicate rackApps(Rack::AppCandidate c, DataFlow::ParameterNode env) { env = c.getEnv() } +query predicate rackApps(Rack::App::AppCandidate c, DataFlow::ParameterNode env) { + env = c.getEnv() +} -query predicate rackResponseStatusCodes(Rack::ResponseNode resp, string status) { +query predicate rackResponseStatusCodes(Rack::Response::ResponseNode resp, string status) { if exists(resp.getAStatusCode()) then status = resp.getAStatusCode().toString() else status = "" } -query predicate rackResponseContentTypes(Rack::ResponseNode resp, DataFlow::Node contentType) { +query predicate rackResponseContentTypes( + Rack::Response::ResponseNode resp, DataFlow::Node contentType +) { contentType = resp.getMimetypeOrContentTypeArg() } -query predicate mimetypeCalls(Rack::MimetypeCall c, string mimetype) { mimetype = c.getMimeType() } +query predicate mimetypeCalls(Rack::Mime::MimetypeCall c, string mimetype) { + mimetype = c.getMimeType() +} -query predicate redirectResponses(Rack::RedirectResponse resp, DataFlow::Node location) { +query predicate redirectResponses(Rack::Response::RedirectResponse resp, DataFlow::Node location) { location = resp.getRedirectLocation() } From 19664879c877f61630525ce287f115778b1c5732 Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Thu, 25 May 2023 14:18:09 +0100 Subject: [PATCH 07/23] ruby: slightly expand a TODO --- ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll index f7fb1d31177f..c5d5b197382d 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll @@ -72,7 +72,7 @@ module Public { result = getHeaderValue(this, "content-type") } - // TODO + // TODO: is there a sensible value for this? override string getMimetypeDefault() { none() } } From 4905a70e21271fe2c7ffabf63173ccf979b01207 Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Thu, 25 May 2023 14:18:51 +0100 Subject: [PATCH 08/23] Ruby: update rack test output --- .../frameworks/rack/Rack.expected | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/ruby/ql/test/library-tests/frameworks/rack/Rack.expected b/ruby/ql/test/library-tests/frameworks/rack/Rack.expected index 23fec9a8266e..157168f0bd8b 100644 --- a/ruby/ql/test/library-tests/frameworks/rack/Rack.expected +++ b/ruby/ql/test/library-tests/frameworks/rack/Rack.expected @@ -1,12 +1,21 @@ rackApps -| rack.rb:1:1:9:3 | HelloWorld | rack.rb:2:12:2:14 | env | -| rack.rb:11:1:20:3 | Proxy | rack.rb:16:12:16:18 | the_env | -| rack.rb:22:1:35:3 | Logger | rack.rb:28:12:28:14 | env | -| rack.rb:49:1:65:3 | Baz | rack.rb:50:12:50:14 | env | +| rack.rb:1:1:10:3 | HelloWorld | rack.rb:2:12:2:14 | env | +| rack.rb:12:1:22:3 | Proxy | rack.rb:17:12:17:18 | the_env | +| rack.rb:24:1:37:3 | Logger | rack.rb:30:12:30:14 | env | +| rack.rb:39:1:45:3 | Redirector | rack.rb:40:12:40:14 | env | +| rack.rb:59:1:75:3 | Baz | rack.rb:60:12:60:14 | env | rackResponseStatusCodes -| rack.rb:7:5:7:63 | call to [] | 200 | -| rack.rb:7:5:7:63 | call to [] | 500 | -| rack.rb:18:5:18:27 | call to [] | | -| rack.rb:33:5:33:26 | call to [] | | -| rack.rb:56:7:56:22 | call to [] | 200 | -| rack.rb:63:5:63:21 | call to [] | 400 | +| rack.rb:8:5:8:38 | call to [] | 200 | +| rack.rb:8:5:8:38 | call to [] | 500 | +| rack.rb:20:5:20:27 | call to [] | | +| rack.rb:35:5:35:26 | call to [] | | +| rack.rb:43:5:43:45 | call to [] | 302 | +| rack.rb:66:7:66:22 | call to [] | 200 | +| rack.rb:73:5:73:21 | call to [] | 400 | +rackResponseContentTypes +| rack.rb:8:5:8:38 | call to [] | rack.rb:7:34:7:45 | "text/plain" | +| rack.rb:20:5:20:27 | call to [] | rack.rb:19:28:19:54 | call to mime_type | +mimetypeCalls +| rack.rb:19:28:19:54 | call to mime_type | application/x-gzip | +redirectResponses +| rack.rb:43:5:43:45 | call to [] | rack.rb:42:30:42:40 | "/foo.html" | From 40da7d45c2c127045ddc94fa98d9523d57a1d7af Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Thu, 25 May 2023 14:20:55 +0100 Subject: [PATCH 09/23] ruby: make a predicate private --- ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll index 502fe72fa51f..df09146c315a 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll @@ -1,7 +1,7 @@ private import codeql.ruby.ApiGraphs private import codeql.ruby.DataFlow -predicate mimeTypeMatches(string ext, string mimeType) { +private predicate mimeTypeMatches(string ext, string mimeType) { ext = ".123" and mimeType = "application/vnd.lotus-1-2-3" or ext = ".3dml" and mimeType = "text/vnd.in3d.3dml" From 24635df1a363c2685fb4e6be1a79bff322922921 Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Thu, 25 May 2023 14:21:45 +0100 Subject: [PATCH 10/23] ruby: add some qldoc for rack --- ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll | 3 +++ ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll | 3 +++ ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll index 7dbd7c7a840d..78666b7fe1d1 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll @@ -14,6 +14,9 @@ private DataFlow::Node trackRackResponse(RP::PotentialResponseNode n) { trackRackResponse(TypeTracker::end(), n).flowsTo(result) } +/** + * Provides modeling for Rack applications. + */ module App { /** * A class that may be a rack application. diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll index df09146c315a..d40895a2f131 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll @@ -1287,6 +1287,9 @@ private predicate mimeTypeMatches(string ext, string mimeType) { ext = ".zmm" and mimeType = "application/vnd.handheld-entertainment+xml" } +/** + * Provides modeling for the `Response` component of the `Rack` library. + */ module Mime { class MimetypeCall extends DataFlow::CallNode { MimetypeCall() { diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll index c5d5b197382d..4cb3e99c6399 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll @@ -6,6 +6,7 @@ private import codeql.ruby.DataFlow private import codeql.ruby.typetracking.TypeTracker private import App as A +/** Contains implementation details for modelling `Rack::Response`. */ module Private { private DataFlow::LocalSourceNode trackInt(TypeTracker t, int i) { t.start() and @@ -33,6 +34,9 @@ module Private { } } +/** + * Provides modeling for the `Response` component of the `Rack` library. + */ module Public { bindingset[headerName] private DataFlow::Node getHeaderValue(ResponseNode resp, string headerName) { From 23e22799a9fe0c65a6a8da4cf64d3de806f1279a Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Fri, 26 May 2023 11:38:32 +0100 Subject: [PATCH 11/23] ruby: rack - modelling -> modeling --- ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll index 4cb3e99c6399..65322dbac055 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll @@ -6,7 +6,7 @@ private import codeql.ruby.DataFlow private import codeql.ruby.typetracking.TypeTracker private import App as A -/** Contains implementation details for modelling `Rack::Response`. */ +/** Contains implementation details for modeling `Rack::Response`. */ module Private { private DataFlow::LocalSourceNode trackInt(TypeTracker t, int i) { t.start() and From b62a02f0ad38682d7fd1550484aae6d0dd3f997e Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Fri, 26 May 2023 11:39:59 +0100 Subject: [PATCH 12/23] ruby: remove unused field --- ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll index c076d6d66985..f995bc5af443 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll @@ -1280,9 +1280,7 @@ class HashLiteralNode extends LocalSourceNode, ExprNode { * explicit calls. */ class ArrayLiteralNode extends LocalSourceNode, CallNode { - private CfgNodes::ExprNodes::ArrayLiteralCfgNode arrayNode; - - ArrayLiteralNode() { super.getExprNode() = arrayNode } + ArrayLiteralNode() { super.getExprNode() instanceof CfgNodes::ExprNodes::ArrayLiteralCfgNode } /** * Gets an element of the array. From 57508b2b3b7623eec9924d983ea1e8ec68200401 Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Tue, 30 May 2023 13:30:05 +0100 Subject: [PATCH 13/23] ruby: Limit rack PotentialResponseNode to things that look like they occur in a rack application --- ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll | 2 +- .../ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll index 78666b7fe1d1..35a12c8e3ebe 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll @@ -30,7 +30,7 @@ module App { AppCandidate() { call = this.getInstanceMethod("call") and call.getNumberOfParameters() = 1 and - call.getReturn() = trackRackResponse(resp) + call.getAReturningNode() = trackRackResponse(resp) } /** diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll index 65322dbac055..983d50aaeece 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll @@ -19,7 +19,10 @@ module Private { class PotentialResponseNode extends DataFlow::ArrayLiteralNode { // [status, headers, body] - PotentialResponseNode() { this.getNumberOfArguments() = 3 } + PotentialResponseNode() { + this.getNumberOfArguments() = 3 and + this.asExpr().getExpr().getEnclosingModule+().getAMethod().getName() = "call" + } /** * Gets an HTTP status code that may be returned in this response. From a5d8db6317d99656ab15993ebfcdf6a050905596 Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Wed, 7 Jun 2023 15:55:01 +0100 Subject: [PATCH 14/23] Ruby: fix qldoc --- ruby/ql/lib/codeql/ruby/frameworks/Rack.qll | 4 ++++ ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll | 4 ++++ ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll | 7 ++++++- .../lib/codeql/ruby/frameworks/rack/internal/Response.qll | 6 ++++++ 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll b/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll index 64ca7cc0b601..74553476d17a 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll @@ -1,3 +1,7 @@ +/** + * Provides modeling for the Rack library. + */ + /** * Provides modeling for the Rack library. */ diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll index 35a12c8e3ebe..0a344f46dc80 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll @@ -1,3 +1,7 @@ +/** + * Provides modeling for Rack applications. + */ + private import codeql.ruby.ApiGraphs private import codeql.ruby.DataFlow private import codeql.ruby.typetracking.TypeTracker diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll index d40895a2f131..2aceebffbcdf 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll @@ -1,3 +1,7 @@ +/** + * Provides modeling for the `Mime` component of the `Rack` library. + */ + private import codeql.ruby.ApiGraphs private import codeql.ruby.DataFlow @@ -1288,7 +1292,7 @@ private predicate mimeTypeMatches(string ext, string mimeType) { } /** - * Provides modeling for the `Response` component of the `Rack` library. + * Provides modeling for the `Mime` component of the `Rack` library. */ module Mime { class MimetypeCall extends DataFlow::CallNode { @@ -1300,6 +1304,7 @@ module Mime { result = this.getArgument(0).getConstantValue().getStringlikeValue() } + /** Gets the canonical MIME type string returned by this call. */ string getMimeType() { mimeTypeMatches(this.getExtension(), result) } } } diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll index 983d50aaeece..26162a8d3063 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll @@ -1,3 +1,7 @@ +/** + * Provides modeling for the `Response` component of the `Rack` library. + */ + private import codeql.ruby.AST private import codeql.ruby.ApiGraphs private import codeql.ruby.Concepts @@ -17,6 +21,7 @@ module Private { private DataFlow::Node trackInt(int i) { trackInt(TypeTracker::end(), i).flowsTo(result) } + /** A `DataFlow::Node` that may be a rack response. This is detected heuristically, if something "looks like" a rack response syntactically then we consider it to be a potential response node. */ class PotentialResponseNode extends DataFlow::ArrayLiteralNode { // [status, headers, body] PotentialResponseNode() { @@ -83,6 +88,7 @@ module Public { override string getMimetypeDefault() { none() } } + /** A `DataFlow::Node` returned from a rack request that has a redirect HTTP status code. */ class RedirectResponse extends ResponseNode, Http::Server::HttpRedirectResponse::Range { RedirectResponse() { this.getAStatusCode() = [300, 301, 302, 303, 307, 308] } From 0a7ae587101b857557a82ea3aafb14c4310c2bdb Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Wed, 7 Jun 2023 16:30:53 +0100 Subject: [PATCH 15/23] Ruby: revert to simpler Rack PotentialResponseNode def and use TypeBackTracker to track instances --- .../ruby/frameworks/rack/internal/App.qll | 21 ++++++++++++------- .../frameworks/rack/internal/Response.qll | 5 +---- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll index 0a344f46dc80..eb8b283fa169 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll @@ -7,15 +7,20 @@ private import codeql.ruby.DataFlow private import codeql.ruby.typetracking.TypeTracker private import Response::Private as RP -private DataFlow::LocalSourceNode trackRackResponse(TypeTracker t, RP::PotentialResponseNode n) { +/** A method node for a method named `call`. */ +private class CallMethodNode extends DataFlow::MethodNode { + CallMethodNode() { this.getMethodName() = "call" } +} + +private DataFlow::LocalSourceNode trackRackResponse(TypeBackTracker t, CallMethodNode call) { t.start() and - result = n + result = call.getAReturningNode() or - exists(TypeTracker t2 | result = trackRackResponse(t2, n).track(t2, t)) + exists(TypeBackTracker t2 | result = trackRackResponse(t2, call).backtrack(t2, t)) } -private DataFlow::Node trackRackResponse(RP::PotentialResponseNode n) { - trackRackResponse(TypeTracker::end(), n).flowsTo(result) +private RP::PotentialResponseNode trackRackResponse(CallMethodNode call) { + result = trackRackResponse(TypeBackTracker::end(), call) } /** @@ -28,13 +33,13 @@ module App { * (traditionally called `env`) and returns a rack-compatible response. */ class AppCandidate extends DataFlow::ClassNode { - private DataFlow::MethodNode call; + private CallMethodNode call; private RP::PotentialResponseNode resp; AppCandidate() { call = this.getInstanceMethod("call") and call.getNumberOfParameters() = 1 and - call.getAReturningNode() = trackRackResponse(resp) + resp = trackRackResponse(call) } /** @@ -42,7 +47,7 @@ module App { */ DataFlow::ParameterNode getEnv() { result = call.getParameter(0) } - /** Gets the response returned from the request. */ + /** Gets the response returned from a request to this application. */ RP::PotentialResponseNode getResponse() { result = resp } } } diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll index 26162a8d3063..d5ca488fcda1 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll @@ -24,10 +24,7 @@ module Private { /** A `DataFlow::Node` that may be a rack response. This is detected heuristically, if something "looks like" a rack response syntactically then we consider it to be a potential response node. */ class PotentialResponseNode extends DataFlow::ArrayLiteralNode { // [status, headers, body] - PotentialResponseNode() { - this.getNumberOfArguments() = 3 and - this.asExpr().getExpr().getEnclosingModule+().getAMethod().getName() = "call" - } + PotentialResponseNode() { this.getNumberOfArguments() = 3 } /** * Gets an HTTP status code that may be returned in this response. From c531b94594c782d1a0e67f4bb4839b03104c2d49 Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Thu, 8 Jun 2023 11:59:10 +0100 Subject: [PATCH 16/23] Ruby: add a change note for rack redirect support --- ruby/ql/lib/change-notes/2023-06-08-rack-redirect.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 ruby/ql/lib/change-notes/2023-06-08-rack-redirect.md diff --git a/ruby/ql/lib/change-notes/2023-06-08-rack-redirect.md b/ruby/ql/lib/change-notes/2023-06-08-rack-redirect.md new file mode 100644 index 000000000000..09687fa95be2 --- /dev/null +++ b/ruby/ql/lib/change-notes/2023-06-08-rack-redirect.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* HTTP redirect responses from Rack applications are now recognized as a potential sink for open redirect alerts. From 21b4f885a634ca921089e0f79e566a744594785b Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Thu, 8 Jun 2023 12:01:42 +0100 Subject: [PATCH 17/23] ruby: fix qldoc --- ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll index 2aceebffbcdf..f9bd42c15b0e 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll @@ -1295,6 +1295,7 @@ private predicate mimeTypeMatches(string ext, string mimeType) { * Provides modeling for the `Mime` component of the `Rack` library. */ module Mime { + /** A call to `Rack::Mime.mime_type`. This method maps file extensions to MIME types. */ class MimetypeCall extends DataFlow::CallNode { MimetypeCall() { this = API::getTopLevelMember("Rack").getMember("Mime").getAMethodCall("mime_type") From b4620042a5c356f84c726e9c68edb65d294e61cb Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Thu, 8 Jun 2023 12:09:22 +0100 Subject: [PATCH 18/23] Ruby: fix use of deprecated predicate --- ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll index eb8b283fa169..5ea8ad38f298 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll @@ -14,7 +14,7 @@ private class CallMethodNode extends DataFlow::MethodNode { private DataFlow::LocalSourceNode trackRackResponse(TypeBackTracker t, CallMethodNode call) { t.start() and - result = call.getAReturningNode() + result = call.getAReturnNode() or exists(TypeBackTracker t2 | result = trackRackResponse(t2, call).backtrack(t2, t)) } From af1ca7fec74d9011a78fce06460af3905da0ce42 Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Tue, 13 Jun 2023 12:37:31 +0100 Subject: [PATCH 19/23] Update ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll Co-authored-by: Asger F --- ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll index 5ea8ad38f298..bfdd988ac191 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll @@ -14,7 +14,7 @@ private class CallMethodNode extends DataFlow::MethodNode { private DataFlow::LocalSourceNode trackRackResponse(TypeBackTracker t, CallMethodNode call) { t.start() and - result = call.getAReturnNode() + result = call.getAReturnNode().getALocalSource() or exists(TypeBackTracker t2 | result = trackRackResponse(t2, call).backtrack(t2, t)) } From 977ceb89fd8538b75cbf58584d4c24d009ae2f26 Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Tue, 13 Jun 2023 12:42:46 +0100 Subject: [PATCH 20/23] Ruby: rack - remove PotentialResponseNode#getAStatusCode --- .../frameworks/rack/internal/Response.qll | 20 ++++--------------- .../frameworks/rack/Rack.expected | 8 -------- .../library-tests/frameworks/rack/Rack.ql | 6 ------ 3 files changed, 4 insertions(+), 30 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll index d5ca488fcda1..9d998c780aef 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Response.qll @@ -12,25 +12,11 @@ private import App as A /** Contains implementation details for modeling `Rack::Response`. */ module Private { - private DataFlow::LocalSourceNode trackInt(TypeTracker t, int i) { - t.start() and - result.getConstantValue().isInt(i) - or - exists(TypeTracker t2 | result = trackInt(t2, i).track(t2, t)) - } - - private DataFlow::Node trackInt(int i) { trackInt(TypeTracker::end(), i).flowsTo(result) } - /** A `DataFlow::Node` that may be a rack response. This is detected heuristically, if something "looks like" a rack response syntactically then we consider it to be a potential response node. */ class PotentialResponseNode extends DataFlow::ArrayLiteralNode { // [status, headers, body] PotentialResponseNode() { this.getNumberOfArguments() = 3 } - /** - * Gets an HTTP status code that may be returned in this response. - */ - int getAStatusCode() { this.getElement(0) = trackInt(result) } - /** Gets the headers returned with this response. */ DataFlow::Node getHeaders() { result = this.getElement(1) } @@ -87,8 +73,10 @@ module Public { /** A `DataFlow::Node` returned from a rack request that has a redirect HTTP status code. */ class RedirectResponse extends ResponseNode, Http::Server::HttpRedirectResponse::Range { - RedirectResponse() { this.getAStatusCode() = [300, 301, 302, 303, 307, 308] } + private DataFlow::Node redirectLocation; + + RedirectResponse() { redirectLocation = getHeaderValue(this, "location") } - override DataFlow::Node getRedirectLocation() { result = getHeaderValue(this, "location") } + override DataFlow::Node getRedirectLocation() { result = redirectLocation } } } diff --git a/ruby/ql/test/library-tests/frameworks/rack/Rack.expected b/ruby/ql/test/library-tests/frameworks/rack/Rack.expected index 157168f0bd8b..a2671c95cb7a 100644 --- a/ruby/ql/test/library-tests/frameworks/rack/Rack.expected +++ b/ruby/ql/test/library-tests/frameworks/rack/Rack.expected @@ -4,14 +4,6 @@ rackApps | rack.rb:24:1:37:3 | Logger | rack.rb:30:12:30:14 | env | | rack.rb:39:1:45:3 | Redirector | rack.rb:40:12:40:14 | env | | rack.rb:59:1:75:3 | Baz | rack.rb:60:12:60:14 | env | -rackResponseStatusCodes -| rack.rb:8:5:8:38 | call to [] | 200 | -| rack.rb:8:5:8:38 | call to [] | 500 | -| rack.rb:20:5:20:27 | call to [] | | -| rack.rb:35:5:35:26 | call to [] | | -| rack.rb:43:5:43:45 | call to [] | 302 | -| rack.rb:66:7:66:22 | call to [] | 200 | -| rack.rb:73:5:73:21 | call to [] | 400 | rackResponseContentTypes | rack.rb:8:5:8:38 | call to [] | rack.rb:7:34:7:45 | "text/plain" | | rack.rb:20:5:20:27 | call to [] | rack.rb:19:28:19:54 | call to mime_type | diff --git a/ruby/ql/test/library-tests/frameworks/rack/Rack.ql b/ruby/ql/test/library-tests/frameworks/rack/Rack.ql index 8e0bcee42440..1b019cdd3a0b 100644 --- a/ruby/ql/test/library-tests/frameworks/rack/Rack.ql +++ b/ruby/ql/test/library-tests/frameworks/rack/Rack.ql @@ -6,12 +6,6 @@ query predicate rackApps(Rack::App::AppCandidate c, DataFlow::ParameterNode env) env = c.getEnv() } -query predicate rackResponseStatusCodes(Rack::Response::ResponseNode resp, string status) { - if exists(resp.getAStatusCode()) - then status = resp.getAStatusCode().toString() - else status = "" -} - query predicate rackResponseContentTypes( Rack::Response::ResponseNode resp, DataFlow::Node contentType ) { From 75ccbe58ee27d656b8ae99c39d6a0f48592b489e Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Tue, 13 Jun 2023 12:44:29 +0100 Subject: [PATCH 21/23] Ruby: rack - use Mimetype rather than MimeType in predicate names for consistency with concepts --- ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll | 4 ++-- ruby/ql/test/library-tests/frameworks/rack/Rack.ql | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll index f9bd42c15b0e..c7682c256383 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll @@ -5,7 +5,7 @@ private import codeql.ruby.ApiGraphs private import codeql.ruby.DataFlow -private predicate mimeTypeMatches(string ext, string mimeType) { +private predicate mimetypeMatches(string ext, string mimeType) { ext = ".123" and mimeType = "application/vnd.lotus-1-2-3" or ext = ".3dml" and mimeType = "text/vnd.in3d.3dml" @@ -1306,6 +1306,6 @@ module Mime { } /** Gets the canonical MIME type string returned by this call. */ - string getMimeType() { mimeTypeMatches(this.getExtension(), result) } + string getMimetype() { mimetypeMatches(this.getExtension(), result) } } } diff --git a/ruby/ql/test/library-tests/frameworks/rack/Rack.ql b/ruby/ql/test/library-tests/frameworks/rack/Rack.ql index 1b019cdd3a0b..e1f1c506994d 100644 --- a/ruby/ql/test/library-tests/frameworks/rack/Rack.ql +++ b/ruby/ql/test/library-tests/frameworks/rack/Rack.ql @@ -13,7 +13,7 @@ query predicate rackResponseContentTypes( } query predicate mimetypeCalls(Rack::Mime::MimetypeCall c, string mimetype) { - mimetype = c.getMimeType() + mimetype = c.getMimetype() } query predicate redirectResponses(Rack::Response::RedirectResponse resp, DataFlow::Node location) { From 7aec22c1e4f36bdcc720ae8504109d6ba153a71c Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Tue, 20 Jun 2023 14:57:23 +0100 Subject: [PATCH 22/23] Ruby: rack - remove MIME modelling --- ruby/ql/lib/codeql/ruby/frameworks/Rack.qll | 7 +- .../ruby/frameworks/rack/internal/Mime.qll | 1311 ----------------- .../frameworks/rack/Rack.expected | 4 +- .../library-tests/frameworks/rack/Rack.ql | 4 - .../library-tests/frameworks/rack/rack.rb | 2 +- 5 files changed, 5 insertions(+), 1323 deletions(-) delete mode 100644 ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll diff --git a/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll b/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll index 74553476d17a..4d9342d88054 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll @@ -7,9 +7,8 @@ */ module Rack { import rack.internal.App - import rack.internal.Mime - import rack.internal.Response::Public as Response +import rack.internal.Response::Public as Response - /** DEPRECATED: Alias for App::AppCandidate */ - deprecated class AppCandidate = App::AppCandidate; +/** DEPRECATED: Alias for App::AppCandidate */ +deprecated class AppCandidate = App::AppCandidate; } diff --git a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll b/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll deleted file mode 100644 index c7682c256383..000000000000 --- a/ruby/ql/lib/codeql/ruby/frameworks/rack/internal/Mime.qll +++ /dev/null @@ -1,1311 +0,0 @@ -/** - * Provides modeling for the `Mime` component of the `Rack` library. - */ - -private import codeql.ruby.ApiGraphs -private import codeql.ruby.DataFlow - -private predicate mimetypeMatches(string ext, string mimeType) { - ext = ".123" and mimeType = "application/vnd.lotus-1-2-3" - or - ext = ".3dml" and mimeType = "text/vnd.in3d.3dml" - or - ext = ".3g2" and mimeType = "video/3gpp2" - or - ext = ".3gp" and mimeType = "video/3gpp" - or - ext = ".a" and mimeType = "application/octet-stream" - or - ext = ".acc" and mimeType = "application/vnd.americandynamics.acc" - or - ext = ".ace" and mimeType = "application/x-ace-compressed" - or - ext = ".acu" and mimeType = "application/vnd.acucobol" - or - ext = ".aep" and mimeType = "application/vnd.audiograph" - or - ext = ".afp" and mimeType = "application/vnd.ibm.modcap" - or - ext = ".ai" and mimeType = "application/postscript" - or - ext = ".aif" and mimeType = "audio/x-aiff" - or - ext = ".aiff" and mimeType = "audio/x-aiff" - or - ext = ".ami" and mimeType = "application/vnd.amiga.ami" - or - ext = ".apng" and mimeType = "image/apng" - or - ext = ".appcache" and mimeType = "text/cache-manifest" - or - ext = ".apr" and mimeType = "application/vnd.lotus-approach" - or - ext = ".asc" and mimeType = "application/pgp-signature" - or - ext = ".asf" and mimeType = "video/x-ms-asf" - or - ext = ".asm" and mimeType = "text/x-asm" - or - ext = ".aso" and mimeType = "application/vnd.accpac.simply.aso" - or - ext = ".asx" and mimeType = "video/x-ms-asf" - or - ext = ".atc" and mimeType = "application/vnd.acucorp" - or - ext = ".atom" and mimeType = "application/atom+xml" - or - ext = ".atomcat" and mimeType = "application/atomcat+xml" - or - ext = ".atomsvc" and mimeType = "application/atomsvc+xml" - or - ext = ".atx" and mimeType = "application/vnd.antix.game-component" - or - ext = ".au" and mimeType = "audio/basic" - or - ext = ".avi" and mimeType = "video/x-msvideo" - or - ext = ".avif" and mimeType = "image/avif" - or - ext = ".bat" and mimeType = "application/x-msdownload" - or - ext = ".bcpio" and mimeType = "application/x-bcpio" - or - ext = ".bdm" and mimeType = "application/vnd.syncml.dm+wbxml" - or - ext = ".bh2" and mimeType = "application/vnd.fujitsu.oasysprs" - or - ext = ".bin" and mimeType = "application/octet-stream" - or - ext = ".bmi" and mimeType = "application/vnd.bmi" - or - ext = ".bmp" and mimeType = "image/bmp" - or - ext = ".box" and mimeType = "application/vnd.previewsystems.box" - or - ext = ".btif" and mimeType = "image/prs.btif" - or - ext = ".bz" and mimeType = "application/x-bzip" - or - ext = ".bz2" and mimeType = "application/x-bzip2" - or - ext = ".c" and mimeType = "text/x-c" - or - ext = ".c4g" and mimeType = "application/vnd.clonk.c4group" - or - ext = ".cab" and mimeType = "application/vnd.ms-cab-compressed" - or - ext = ".cc" and mimeType = "text/x-c" - or - ext = ".ccxml" and mimeType = "application/ccxml+xml" - or - ext = ".cdbcmsg" and mimeType = "application/vnd.contact.cmsg" - or - ext = ".cdkey" and mimeType = "application/vnd.mediastation.cdkey" - or - ext = ".cdx" and mimeType = "chemical/x-cdx" - or - ext = ".cdxml" and mimeType = "application/vnd.chemdraw+xml" - or - ext = ".cdy" and mimeType = "application/vnd.cinderella" - or - ext = ".cer" and mimeType = "application/pkix-cert" - or - ext = ".cgm" and mimeType = "image/cgm" - or - ext = ".chat" and mimeType = "application/x-chat" - or - ext = ".chm" and mimeType = "application/vnd.ms-htmlhelp" - or - ext = ".chrt" and mimeType = "application/vnd.kde.kchart" - or - ext = ".cif" and mimeType = "chemical/x-cif" - or - ext = ".cii" and mimeType = "application/vnd.anser-web-certificate-issue-initiation" - or - ext = ".cil" and mimeType = "application/vnd.ms-artgalry" - or - ext = ".cla" and mimeType = "application/vnd.claymore" - or - ext = ".class" and mimeType = "application/octet-stream" - or - ext = ".clkk" and mimeType = "application/vnd.crick.clicker.keyboard" - or - ext = ".clkp" and mimeType = "application/vnd.crick.clicker.palette" - or - ext = ".clkt" and mimeType = "application/vnd.crick.clicker.template" - or - ext = ".clkw" and mimeType = "application/vnd.crick.clicker.wordbank" - or - ext = ".clkx" and mimeType = "application/vnd.crick.clicker" - or - ext = ".clp" and mimeType = "application/x-msclip" - or - ext = ".cmc" and mimeType = "application/vnd.cosmocaller" - or - ext = ".cmdf" and mimeType = "chemical/x-cmdf" - or - ext = ".cml" and mimeType = "chemical/x-cml" - or - ext = ".cmp" and mimeType = "application/vnd.yellowriver-custom-menu" - or - ext = ".cmx" and mimeType = "image/x-cmx" - or - ext = ".com" and mimeType = "application/x-msdownload" - or - ext = ".conf" and mimeType = "text/plain" - or - ext = ".cpio" and mimeType = "application/x-cpio" - or - ext = ".cpp" and mimeType = "text/x-c" - or - ext = ".cpt" and mimeType = "application/mac-compactpro" - or - ext = ".crd" and mimeType = "application/x-mscardfile" - or - ext = ".crl" and mimeType = "application/pkix-crl" - or - ext = ".crt" and mimeType = "application/x-x509-ca-cert" - or - ext = ".csh" and mimeType = "application/x-csh" - or - ext = ".csml" and mimeType = "chemical/x-csml" - or - ext = ".csp" and mimeType = "application/vnd.commonspace" - or - ext = ".css" and mimeType = "text/css" - or - ext = ".csv" and mimeType = "text/csv" - or - ext = ".curl" and mimeType = "application/vnd.curl" - or - ext = ".cww" and mimeType = "application/prs.cww" - or - ext = ".cxx" and mimeType = "text/x-c" - or - ext = ".daf" and mimeType = "application/vnd.mobius.daf" - or - ext = ".davmount" and mimeType = "application/davmount+xml" - or - ext = ".dcr" and mimeType = "application/x-director" - or - ext = ".dd2" and mimeType = "application/vnd.oma.dd2+xml" - or - ext = ".ddd" and mimeType = "application/vnd.fujixerox.ddd" - or - ext = ".deb" and mimeType = "application/x-debian-package" - or - ext = ".der" and mimeType = "application/x-x509-ca-cert" - or - ext = ".dfac" and mimeType = "application/vnd.dreamfactory" - or - ext = ".diff" and mimeType = "text/x-diff" - or - ext = ".dis" and mimeType = "application/vnd.mobius.dis" - or - ext = ".djv" and mimeType = "image/vnd.djvu" - or - ext = ".djvu" and mimeType = "image/vnd.djvu" - or - ext = ".dll" and mimeType = "application/x-msdownload" - or - ext = ".dmg" and mimeType = "application/octet-stream" - or - ext = ".dna" and mimeType = "application/vnd.dna" - or - ext = ".doc" and mimeType = "application/msword" - or - ext = ".docm" and mimeType = "application/vnd.ms-word.document.macroEnabled.12" - or - ext = ".docx" and - mimeType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document" - or - ext = ".dot" and mimeType = "application/msword" - or - ext = ".dotm" and mimeType = "application/vnd.ms-word.template.macroEnabled.12" - or - ext = ".dotx" and - mimeType = "application/vnd.openxmlformats-officedocument.wordprocessingml.template" - or - ext = ".dp" and mimeType = "application/vnd.osgi.dp" - or - ext = ".dpg" and mimeType = "application/vnd.dpgraph" - or - ext = ".dsc" and mimeType = "text/prs.lines.tag" - or - ext = ".dtd" and mimeType = "application/xml-dtd" - or - ext = ".dts" and mimeType = "audio/vnd.dts" - or - ext = ".dtshd" and mimeType = "audio/vnd.dts.hd" - or - ext = ".dv" and mimeType = "video/x-dv" - or - ext = ".dvi" and mimeType = "application/x-dvi" - or - ext = ".dwf" and mimeType = "model/vnd.dwf" - or - ext = ".dwg" and mimeType = "image/vnd.dwg" - or - ext = ".dxf" and mimeType = "image/vnd.dxf" - or - ext = ".dxp" and mimeType = "application/vnd.spotfire.dxp" - or - ext = ".ear" and mimeType = "application/java-archive" - or - ext = ".ecelp4800" and mimeType = "audio/vnd.nuera.ecelp4800" - or - ext = ".ecelp7470" and mimeType = "audio/vnd.nuera.ecelp7470" - or - ext = ".ecelp9600" and mimeType = "audio/vnd.nuera.ecelp9600" - or - ext = ".ecma" and mimeType = "application/ecmascript" - or - ext = ".edm" and mimeType = "application/vnd.novadigm.edm" - or - ext = ".edx" and mimeType = "application/vnd.novadigm.edx" - or - ext = ".efif" and mimeType = "application/vnd.picsel" - or - ext = ".ei6" and mimeType = "application/vnd.pg.osasli" - or - ext = ".eml" and mimeType = "message/rfc822" - or - ext = ".eol" and mimeType = "audio/vnd.digital-winds" - or - ext = ".eot" and mimeType = "application/vnd.ms-fontobject" - or - ext = ".eps" and mimeType = "application/postscript" - or - ext = ".es3" and mimeType = "application/vnd.eszigno3+xml" - or - ext = ".esf" and mimeType = "application/vnd.epson.esf" - or - ext = ".etx" and mimeType = "text/x-setext" - or - ext = ".exe" and mimeType = "application/x-msdownload" - or - ext = ".ext" and mimeType = "application/vnd.novadigm.ext" - or - ext = ".ez" and mimeType = "application/andrew-inset" - or - ext = ".ez2" and mimeType = "application/vnd.ezpix-album" - or - ext = ".ez3" and mimeType = "application/vnd.ezpix-package" - or - ext = ".f" and mimeType = "text/x-fortran" - or - ext = ".f77" and mimeType = "text/x-fortran" - or - ext = ".f90" and mimeType = "text/x-fortran" - or - ext = ".fbs" and mimeType = "image/vnd.fastbidsheet" - or - ext = ".fdf" and mimeType = "application/vnd.fdf" - or - ext = ".fe_launch" and mimeType = "application/vnd.denovo.fcselayout-link" - or - ext = ".fg5" and mimeType = "application/vnd.fujitsu.oasysgp" - or - ext = ".fli" and mimeType = "video/x-fli" - or - ext = ".flif" and mimeType = "image/flif" - or - ext = ".flo" and mimeType = "application/vnd.micrografx.flo" - or - ext = ".flv" and mimeType = "video/x-flv" - or - ext = ".flw" and mimeType = "application/vnd.kde.kivio" - or - ext = ".flx" and mimeType = "text/vnd.fmi.flexstor" - or - ext = ".fly" and mimeType = "text/vnd.fly" - or - ext = ".fm" and mimeType = "application/vnd.framemaker" - or - ext = ".fnc" and mimeType = "application/vnd.frogans.fnc" - or - ext = ".for" and mimeType = "text/x-fortran" - or - ext = ".fpx" and mimeType = "image/vnd.fpx" - or - ext = ".fsc" and mimeType = "application/vnd.fsc.weblaunch" - or - ext = ".fst" and mimeType = "image/vnd.fst" - or - ext = ".ftc" and mimeType = "application/vnd.fluxtime.clip" - or - ext = ".fti" and mimeType = "application/vnd.anser-web-funds-transfer-initiation" - or - ext = ".fvt" and mimeType = "video/vnd.fvt" - or - ext = ".fzs" and mimeType = "application/vnd.fuzzysheet" - or - ext = ".g3" and mimeType = "image/g3fax" - or - ext = ".gac" and mimeType = "application/vnd.groove-account" - or - ext = ".gdl" and mimeType = "model/vnd.gdl" - or - ext = ".gem" and mimeType = "application/octet-stream" - or - ext = ".gemspec" and mimeType = "text/x-script.ruby" - or - ext = ".ghf" and mimeType = "application/vnd.groove-help" - or - ext = ".gif" and mimeType = "image/gif" - or - ext = ".gim" and mimeType = "application/vnd.groove-identity-message" - or - ext = ".gmx" and mimeType = "application/vnd.gmx" - or - ext = ".gph" and mimeType = "application/vnd.flographit" - or - ext = ".gqf" and mimeType = "application/vnd.grafeq" - or - ext = ".gram" and mimeType = "application/srgs" - or - ext = ".grv" and mimeType = "application/vnd.groove-injector" - or - ext = ".grxml" and mimeType = "application/srgs+xml" - or - ext = ".gtar" and mimeType = "application/x-gtar" - or - ext = ".gtm" and mimeType = "application/vnd.groove-tool-message" - or - ext = ".gtw" and mimeType = "model/vnd.gtw" - or - ext = ".gv" and mimeType = "text/vnd.graphviz" - or - ext = ".gz" and mimeType = "application/x-gzip" - or - ext = ".h" and mimeType = "text/x-c" - or - ext = ".h261" and mimeType = "video/h261" - or - ext = ".h263" and mimeType = "video/h263" - or - ext = ".h264" and mimeType = "video/h264" - or - ext = ".hbci" and mimeType = "application/vnd.hbci" - or - ext = ".hdf" and mimeType = "application/x-hdf" - or - ext = ".heic" and mimeType = "image/heic" - or - ext = ".heics" and mimeType = "image/heic-sequence" - or - ext = ".heif" and mimeType = "image/heif" - or - ext = ".heifs" and mimeType = "image/heif-sequence" - or - ext = ".hh" and mimeType = "text/x-c" - or - ext = ".hlp" and mimeType = "application/winhlp" - or - ext = ".hpgl" and mimeType = "application/vnd.hp-hpgl" - or - ext = ".hpid" and mimeType = "application/vnd.hp-hpid" - or - ext = ".hps" and mimeType = "application/vnd.hp-hps" - or - ext = ".hqx" and mimeType = "application/mac-binhex40" - or - ext = ".htc" and mimeType = "text/x-component" - or - ext = ".htke" and mimeType = "application/vnd.kenameaapp" - or - ext = ".htm" and mimeType = "text/html" - or - ext = ".html" and mimeType = "text/html" - or - ext = ".hvd" and mimeType = "application/vnd.yamaha.hv-dic" - or - ext = ".hvp" and mimeType = "application/vnd.yamaha.hv-voice" - or - ext = ".hvs" and mimeType = "application/vnd.yamaha.hv-script" - or - ext = ".icc" and mimeType = "application/vnd.iccprofile" - or - ext = ".ice" and mimeType = "x-conference/x-cooltalk" - or - ext = ".ico" and mimeType = "image/vnd.microsoft.icon" - or - ext = ".ics" and mimeType = "text/calendar" - or - ext = ".ief" and mimeType = "image/ief" - or - ext = ".ifb" and mimeType = "text/calendar" - or - ext = ".ifm" and mimeType = "application/vnd.shana.informed.formdata" - or - ext = ".igl" and mimeType = "application/vnd.igloader" - or - ext = ".igs" and mimeType = "model/iges" - or - ext = ".igx" and mimeType = "application/vnd.micrografx.igx" - or - ext = ".iif" and mimeType = "application/vnd.shana.informed.interchange" - or - ext = ".imp" and mimeType = "application/vnd.accpac.simply.imp" - or - ext = ".ims" and mimeType = "application/vnd.ms-ims" - or - ext = ".ipk" and mimeType = "application/vnd.shana.informed.package" - or - ext = ".irm" and mimeType = "application/vnd.ibm.rights-management" - or - ext = ".irp" and mimeType = "application/vnd.irepository.package+xml" - or - ext = ".iso" and mimeType = "application/octet-stream" - or - ext = ".itp" and mimeType = "application/vnd.shana.informed.formtemplate" - or - ext = ".ivp" and mimeType = "application/vnd.immervision-ivp" - or - ext = ".ivu" and mimeType = "application/vnd.immervision-ivu" - or - ext = ".jad" and mimeType = "text/vnd.sun.j2me.app-descriptor" - or - ext = ".jam" and mimeType = "application/vnd.jam" - or - ext = ".jar" and mimeType = "application/java-archive" - or - ext = ".java" and mimeType = "text/x-java-source" - or - ext = ".jisp" and mimeType = "application/vnd.jisp" - or - ext = ".jlt" and mimeType = "application/vnd.hp-jlyt" - or - ext = ".jnlp" and mimeType = "application/x-java-jnlp-file" - or - ext = ".joda" and mimeType = "application/vnd.joost.joda-archive" - or - ext = ".jp2" and mimeType = "image/jp2" - or - ext = ".jpeg" and mimeType = "image/jpeg" - or - ext = ".jpg" and mimeType = "image/jpeg" - or - ext = ".jpgv" and mimeType = "video/jpeg" - or - ext = ".jpm" and mimeType = "video/jpm" - or - ext = ".js" and mimeType = "application/javascript" - or - ext = ".json" and mimeType = "application/json" - or - ext = ".karbon" and mimeType = "application/vnd.kde.karbon" - or - ext = ".kfo" and mimeType = "application/vnd.kde.kformula" - or - ext = ".kia" and mimeType = "application/vnd.kidspiration" - or - ext = ".kml" and mimeType = "application/vnd.google-earth.kml+xml" - or - ext = ".kmz" and mimeType = "application/vnd.google-earth.kmz" - or - ext = ".kne" and mimeType = "application/vnd.kinar" - or - ext = ".kon" and mimeType = "application/vnd.kde.kontour" - or - ext = ".kpr" and mimeType = "application/vnd.kde.kpresenter" - or - ext = ".ksp" and mimeType = "application/vnd.kde.kspread" - or - ext = ".ktz" and mimeType = "application/vnd.kahootz" - or - ext = ".kwd" and mimeType = "application/vnd.kde.kword" - or - ext = ".latex" and mimeType = "application/x-latex" - or - ext = ".lbd" and mimeType = "application/vnd.llamagraphics.life-balance.desktop" - or - ext = ".lbe" and mimeType = "application/vnd.llamagraphics.life-balance.exchange+xml" - or - ext = ".les" and mimeType = "application/vnd.hhe.lesson-player" - or - ext = ".link66" and mimeType = "application/vnd.route66.link66+xml" - or - ext = ".log" and mimeType = "text/plain" - or - ext = ".lostxml" and mimeType = "application/lost+xml" - or - ext = ".lrm" and mimeType = "application/vnd.ms-lrm" - or - ext = ".ltf" and mimeType = "application/vnd.frogans.ltf" - or - ext = ".lvp" and mimeType = "audio/vnd.lucent.voice" - or - ext = ".lwp" and mimeType = "application/vnd.lotus-wordpro" - or - ext = ".m3u" and mimeType = "audio/x-mpegurl" - or - ext = ".m3u8" and mimeType = "application/x-mpegurl" - or - ext = ".m4a" and mimeType = "audio/mp4a-latm" - or - ext = ".m4v" and mimeType = "video/mp4" - or - ext = ".ma" and mimeType = "application/mathematica" - or - ext = ".mag" and mimeType = "application/vnd.ecowin.chart" - or - ext = ".man" and mimeType = "text/troff" - or - ext = ".manifest" and mimeType = "text/cache-manifest" - or - ext = ".mathml" and mimeType = "application/mathml+xml" - or - ext = ".mbk" and mimeType = "application/vnd.mobius.mbk" - or - ext = ".mbox" and mimeType = "application/mbox" - or - ext = ".mc1" and mimeType = "application/vnd.medcalcdata" - or - ext = ".mcd" and mimeType = "application/vnd.mcd" - or - ext = ".mdb" and mimeType = "application/x-msaccess" - or - ext = ".mdi" and mimeType = "image/vnd.ms-modi" - or - ext = ".mdoc" and mimeType = "text/troff" - or - ext = ".me" and mimeType = "text/troff" - or - ext = ".mfm" and mimeType = "application/vnd.mfmp" - or - ext = ".mgz" and mimeType = "application/vnd.proteus.magazine" - or - ext = ".mid" and mimeType = "audio/midi" - or - ext = ".midi" and mimeType = "audio/midi" - or - ext = ".mif" and mimeType = "application/vnd.mif" - or - ext = ".mime" and mimeType = "message/rfc822" - or - ext = ".mj2" and mimeType = "video/mj2" - or - ext = ".mlp" and mimeType = "application/vnd.dolby.mlp" - or - ext = ".mmd" and mimeType = "application/vnd.chipnuts.karaoke-mmd" - or - ext = ".mmf" and mimeType = "application/vnd.smaf" - or - ext = ".mml" and mimeType = "application/mathml+xml" - or - ext = ".mmr" and mimeType = "image/vnd.fujixerox.edmics-mmr" - or - ext = ".mng" and mimeType = "video/x-mng" - or - ext = ".mny" and mimeType = "application/x-msmoney" - or - ext = ".mov" and mimeType = "video/quicktime" - or - ext = ".movie" and mimeType = "video/x-sgi-movie" - or - ext = ".mp3" and mimeType = "audio/mpeg" - or - ext = ".mp4" and mimeType = "video/mp4" - or - ext = ".mp4a" and mimeType = "audio/mp4" - or - ext = ".mp4s" and mimeType = "application/mp4" - or - ext = ".mp4v" and mimeType = "video/mp4" - or - ext = ".mpc" and mimeType = "application/vnd.mophun.certificate" - or - ext = ".mpd" and mimeType = "application/dash+xml" - or - ext = ".mpeg" and mimeType = "video/mpeg" - or - ext = ".mpg" and mimeType = "video/mpeg" - or - ext = ".mpga" and mimeType = "audio/mpeg" - or - ext = ".mpkg" and mimeType = "application/vnd.apple.installer+xml" - or - ext = ".mpm" and mimeType = "application/vnd.blueice.multipass" - or - ext = ".mpn" and mimeType = "application/vnd.mophun.application" - or - ext = ".mpp" and mimeType = "application/vnd.ms-project" - or - ext = ".mpy" and mimeType = "application/vnd.ibm.minipay" - or - ext = ".mqy" and mimeType = "application/vnd.mobius.mqy" - or - ext = ".mrc" and mimeType = "application/marc" - or - ext = ".ms" and mimeType = "text/troff" - or - ext = ".mscml" and mimeType = "application/mediaservercontrol+xml" - or - ext = ".mseq" and mimeType = "application/vnd.mseq" - or - ext = ".msf" and mimeType = "application/vnd.epson.msf" - or - ext = ".msh" and mimeType = "model/mesh" - or - ext = ".msi" and mimeType = "application/x-msdownload" - or - ext = ".msl" and mimeType = "application/vnd.mobius.msl" - or - ext = ".msty" and mimeType = "application/vnd.muvee.style" - or - ext = ".mts" and mimeType = "model/vnd.mts" - or - ext = ".mus" and mimeType = "application/vnd.musician" - or - ext = ".mvb" and mimeType = "application/x-msmediaview" - or - ext = ".mwf" and mimeType = "application/vnd.mfer" - or - ext = ".mxf" and mimeType = "application/mxf" - or - ext = ".mxl" and mimeType = "application/vnd.recordare.musicxml" - or - ext = ".mxml" and mimeType = "application/xv+xml" - or - ext = ".mxs" and mimeType = "application/vnd.triscape.mxs" - or - ext = ".mxu" and mimeType = "video/vnd.mpegurl" - or - ext = ".n" and mimeType = "application/vnd.nokia.n-gage.symbian.install" - or - ext = ".nc" and mimeType = "application/x-netcdf" - or - ext = ".ngdat" and mimeType = "application/vnd.nokia.n-gage.data" - or - ext = ".nlu" and mimeType = "application/vnd.neurolanguage.nlu" - or - ext = ".nml" and mimeType = "application/vnd.enliven" - or - ext = ".nnd" and mimeType = "application/vnd.noblenet-directory" - or - ext = ".nns" and mimeType = "application/vnd.noblenet-sealer" - or - ext = ".nnw" and mimeType = "application/vnd.noblenet-web" - or - ext = ".npx" and mimeType = "image/vnd.net-fpx" - or - ext = ".nsf" and mimeType = "application/vnd.lotus-notes" - or - ext = ".oa2" and mimeType = "application/vnd.fujitsu.oasys2" - or - ext = ".oa3" and mimeType = "application/vnd.fujitsu.oasys3" - or - ext = ".oas" and mimeType = "application/vnd.fujitsu.oasys" - or - ext = ".obd" and mimeType = "application/x-msbinder" - or - ext = ".oda" and mimeType = "application/oda" - or - ext = ".odc" and mimeType = "application/vnd.oasis.opendocument.chart" - or - ext = ".odf" and mimeType = "application/vnd.oasis.opendocument.formula" - or - ext = ".odg" and mimeType = "application/vnd.oasis.opendocument.graphics" - or - ext = ".odi" and mimeType = "application/vnd.oasis.opendocument.image" - or - ext = ".odp" and mimeType = "application/vnd.oasis.opendocument.presentation" - or - ext = ".ods" and mimeType = "application/vnd.oasis.opendocument.spreadsheet" - or - ext = ".odt" and mimeType = "application/vnd.oasis.opendocument.text" - or - ext = ".oga" and mimeType = "audio/ogg" - or - ext = ".ogg" and mimeType = "application/ogg" - or - ext = ".ogv" and mimeType = "video/ogg" - or - ext = ".ogx" and mimeType = "application/ogg" - or - ext = ".org" and mimeType = "application/vnd.lotus-organizer" - or - ext = ".otc" and mimeType = "application/vnd.oasis.opendocument.chart-template" - or - ext = ".otf" and mimeType = "application/vnd.oasis.opendocument.formula-template" - or - ext = ".otg" and mimeType = "application/vnd.oasis.opendocument.graphics-template" - or - ext = ".oth" and mimeType = "application/vnd.oasis.opendocument.text-web" - or - ext = ".oti" and mimeType = "application/vnd.oasis.opendocument.image-template" - or - ext = ".otm" and mimeType = "application/vnd.oasis.opendocument.text-master" - or - ext = ".ots" and mimeType = "application/vnd.oasis.opendocument.spreadsheet-template" - or - ext = ".ott" and mimeType = "application/vnd.oasis.opendocument.text-template" - or - ext = ".oxt" and mimeType = "application/vnd.openofficeorg.extension" - or - ext = ".p" and mimeType = "text/x-pascal" - or - ext = ".p10" and mimeType = "application/pkcs10" - or - ext = ".p12" and mimeType = "application/x-pkcs12" - or - ext = ".p7b" and mimeType = "application/x-pkcs7-certificates" - or - ext = ".p7m" and mimeType = "application/pkcs7-mime" - or - ext = ".p7r" and mimeType = "application/x-pkcs7-certreqresp" - or - ext = ".p7s" and mimeType = "application/pkcs7-signature" - or - ext = ".pas" and mimeType = "text/x-pascal" - or - ext = ".pbd" and mimeType = "application/vnd.powerbuilder6" - or - ext = ".pbm" and mimeType = "image/x-portable-bitmap" - or - ext = ".pcl" and mimeType = "application/vnd.hp-pcl" - or - ext = ".pclxl" and mimeType = "application/vnd.hp-pclxl" - or - ext = ".pcx" and mimeType = "image/x-pcx" - or - ext = ".pdb" and mimeType = "chemical/x-pdb" - or - ext = ".pdf" and mimeType = "application/pdf" - or - ext = ".pem" and mimeType = "application/x-x509-ca-cert" - or - ext = ".pfr" and mimeType = "application/font-tdpfr" - or - ext = ".pgm" and mimeType = "image/x-portable-graymap" - or - ext = ".pgn" and mimeType = "application/x-chess-pgn" - or - ext = ".pgp" and mimeType = "application/pgp-encrypted" - or - ext = ".pic" and mimeType = "image/x-pict" - or - ext = ".pict" and mimeType = "image/pict" - or - ext = ".pkg" and mimeType = "application/octet-stream" - or - ext = ".pki" and mimeType = "application/pkixcmp" - or - ext = ".pkipath" and mimeType = "application/pkix-pkipath" - or - ext = ".pl" and mimeType = "text/x-script.perl" - or - ext = ".plb" and mimeType = "application/vnd.3gpp.pic-bw-large" - or - ext = ".plc" and mimeType = "application/vnd.mobius.plc" - or - ext = ".plf" and mimeType = "application/vnd.pocketlearn" - or - ext = ".pls" and mimeType = "application/pls+xml" - or - ext = ".pm" and mimeType = "text/x-script.perl-module" - or - ext = ".pml" and mimeType = "application/vnd.ctc-posml" - or - ext = ".png" and mimeType = "image/png" - or - ext = ".pnm" and mimeType = "image/x-portable-anymap" - or - ext = ".pntg" and mimeType = "image/x-macpaint" - or - ext = ".portpkg" and mimeType = "application/vnd.macports.portpkg" - or - ext = ".pot" and mimeType = "application/vnd.ms-powerpoint" - or - ext = ".potm" and mimeType = "application/vnd.ms-powerpoint.template.macroEnabled.12" - or - ext = ".potx" and - mimeType = "application/vnd.openxmlformats-officedocument.presentationml.template" - or - ext = ".ppa" and mimeType = "application/vnd.ms-powerpoint" - or - ext = ".ppam" and mimeType = "application/vnd.ms-powerpoint.addin.macroEnabled.12" - or - ext = ".ppd" and mimeType = "application/vnd.cups-ppd" - or - ext = ".ppm" and mimeType = "image/x-portable-pixmap" - or - ext = ".pps" and mimeType = "application/vnd.ms-powerpoint" - or - ext = ".ppsm" and mimeType = "application/vnd.ms-powerpoint.slideshow.macroEnabled.12" - or - ext = ".ppsx" and - mimeType = "application/vnd.openxmlformats-officedocument.presentationml.slideshow" - or - ext = ".ppt" and mimeType = "application/vnd.ms-powerpoint" - or - ext = ".pptm" and mimeType = "application/vnd.ms-powerpoint.presentation.macroEnabled.12" - or - ext = ".pptx" and - mimeType = "application/vnd.openxmlformats-officedocument.presentationml.presentation" - or - ext = ".prc" and mimeType = "application/vnd.palm" - or - ext = ".pre" and mimeType = "application/vnd.lotus-freelance" - or - ext = ".prf" and mimeType = "application/pics-rules" - or - ext = ".ps" and mimeType = "application/postscript" - or - ext = ".psb" and mimeType = "application/vnd.3gpp.pic-bw-small" - or - ext = ".psd" and mimeType = "image/vnd.adobe.photoshop" - or - ext = ".ptid" and mimeType = "application/vnd.pvi.ptid1" - or - ext = ".pub" and mimeType = "application/x-mspublisher" - or - ext = ".pvb" and mimeType = "application/vnd.3gpp.pic-bw-var" - or - ext = ".pwn" and mimeType = "application/vnd.3m.post-it-notes" - or - ext = ".py" and mimeType = "text/x-script.python" - or - ext = ".pya" and mimeType = "audio/vnd.ms-playready.media.pya" - or - ext = ".pyv" and mimeType = "video/vnd.ms-playready.media.pyv" - or - ext = ".qam" and mimeType = "application/vnd.epson.quickanime" - or - ext = ".qbo" and mimeType = "application/vnd.intu.qbo" - or - ext = ".qfx" and mimeType = "application/vnd.intu.qfx" - or - ext = ".qps" and mimeType = "application/vnd.publishare-delta-tree" - or - ext = ".qt" and mimeType = "video/quicktime" - or - ext = ".qtif" and mimeType = "image/x-quicktime" - or - ext = ".qxd" and mimeType = "application/vnd.quark.quarkxpress" - or - ext = ".ra" and mimeType = "audio/x-pn-realaudio" - or - ext = ".rake" and mimeType = "text/x-script.ruby" - or - ext = ".ram" and mimeType = "audio/x-pn-realaudio" - or - ext = ".rar" and mimeType = "application/x-rar-compressed" - or - ext = ".ras" and mimeType = "image/x-cmu-raster" - or - ext = ".rb" and mimeType = "text/x-script.ruby" - or - ext = ".rcprofile" and mimeType = "application/vnd.ipunplugged.rcprofile" - or - ext = ".rdf" and mimeType = "application/rdf+xml" - or - ext = ".rdz" and mimeType = "application/vnd.data-vision.rdz" - or - ext = ".rep" and mimeType = "application/vnd.businessobjects" - or - ext = ".rgb" and mimeType = "image/x-rgb" - or - ext = ".rif" and mimeType = "application/reginfo+xml" - or - ext = ".rl" and mimeType = "application/resource-lists+xml" - or - ext = ".rlc" and mimeType = "image/vnd.fujixerox.edmics-rlc" - or - ext = ".rld" and mimeType = "application/resource-lists-diff+xml" - or - ext = ".rm" and mimeType = "application/vnd.rn-realmedia" - or - ext = ".rmp" and mimeType = "audio/x-pn-realaudio-plugin" - or - ext = ".rms" and mimeType = "application/vnd.jcp.javame.midlet-rms" - or - ext = ".rnc" and mimeType = "application/relax-ng-compact-syntax" - or - ext = ".roff" and mimeType = "text/troff" - or - ext = ".rpm" and mimeType = "application/x-redhat-package-manager" - or - ext = ".rpss" and mimeType = "application/vnd.nokia.radio-presets" - or - ext = ".rpst" and mimeType = "application/vnd.nokia.radio-preset" - or - ext = ".rq" and mimeType = "application/sparql-query" - or - ext = ".rs" and mimeType = "application/rls-services+xml" - or - ext = ".rsd" and mimeType = "application/rsd+xml" - or - ext = ".rss" and mimeType = "application/rss+xml" - or - ext = ".rtf" and mimeType = "application/rtf" - or - ext = ".rtx" and mimeType = "text/richtext" - or - ext = ".ru" and mimeType = "text/x-script.ruby" - or - ext = ".s" and mimeType = "text/x-asm" - or - ext = ".saf" and mimeType = "application/vnd.yamaha.smaf-audio" - or - ext = ".sbml" and mimeType = "application/sbml+xml" - or - ext = ".sc" and mimeType = "application/vnd.ibm.secure-container" - or - ext = ".scd" and mimeType = "application/x-msschedule" - or - ext = ".scm" and mimeType = "application/vnd.lotus-screencam" - or - ext = ".scq" and mimeType = "application/scvp-cv-request" - or - ext = ".scs" and mimeType = "application/scvp-cv-response" - or - ext = ".sdkm" and mimeType = "application/vnd.solent.sdkm+xml" - or - ext = ".sdp" and mimeType = "application/sdp" - or - ext = ".see" and mimeType = "application/vnd.seemail" - or - ext = ".sema" and mimeType = "application/vnd.sema" - or - ext = ".semd" and mimeType = "application/vnd.semd" - or - ext = ".semf" and mimeType = "application/vnd.semf" - or - ext = ".setpay" and mimeType = "application/set-payment-initiation" - or - ext = ".setreg" and mimeType = "application/set-registration-initiation" - or - ext = ".sfd" and mimeType = "application/vnd.hydrostatix.sof-data" - or - ext = ".sfs" and mimeType = "application/vnd.spotfire.sfs" - or - ext = ".sgm" and mimeType = "text/sgml" - or - ext = ".sgml" and mimeType = "text/sgml" - or - ext = ".sh" and mimeType = "application/x-sh" - or - ext = ".shar" and mimeType = "application/x-shar" - or - ext = ".shf" and mimeType = "application/shf+xml" - or - ext = ".sig" and mimeType = "application/pgp-signature" - or - ext = ".sit" and mimeType = "application/x-stuffit" - or - ext = ".sitx" and mimeType = "application/x-stuffitx" - or - ext = ".skp" and mimeType = "application/vnd.koan" - or - ext = ".slt" and mimeType = "application/vnd.epson.salt" - or - ext = ".smi" and mimeType = "application/smil+xml" - or - ext = ".snd" and mimeType = "audio/basic" - or - ext = ".so" and mimeType = "application/octet-stream" - or - ext = ".spf" and mimeType = "application/vnd.yamaha.smaf-phrase" - or - ext = ".spl" and mimeType = "application/x-futuresplash" - or - ext = ".spot" and mimeType = "text/vnd.in3d.spot" - or - ext = ".spp" and mimeType = "application/scvp-vp-response" - or - ext = ".spq" and mimeType = "application/scvp-vp-request" - or - ext = ".src" and mimeType = "application/x-wais-source" - or - ext = ".srt" and mimeType = "text/srt" - or - ext = ".srx" and mimeType = "application/sparql-results+xml" - or - ext = ".sse" and mimeType = "application/vnd.kodak-descriptor" - or - ext = ".ssf" and mimeType = "application/vnd.epson.ssf" - or - ext = ".ssml" and mimeType = "application/ssml+xml" - or - ext = ".stf" and mimeType = "application/vnd.wt.stf" - or - ext = ".stk" and mimeType = "application/hyperstudio" - or - ext = ".str" and mimeType = "application/vnd.pg.format" - or - ext = ".sus" and mimeType = "application/vnd.sus-calendar" - or - ext = ".sv4cpio" and mimeType = "application/x-sv4cpio" - or - ext = ".sv4crc" and mimeType = "application/x-sv4crc" - or - ext = ".svd" and mimeType = "application/vnd.svd" - or - ext = ".svg" and mimeType = "image/svg+xml" - or - ext = ".svgz" and mimeType = "image/svg+xml" - or - ext = ".swf" and mimeType = "application/x-shockwave-flash" - or - ext = ".swi" and mimeType = "application/vnd.arastra.swi" - or - ext = ".t" and mimeType = "text/troff" - or - ext = ".tao" and mimeType = "application/vnd.tao.intent-module-archive" - or - ext = ".tar" and mimeType = "application/x-tar" - or - ext = ".tbz" and mimeType = "application/x-bzip-compressed-tar" - or - ext = ".tcap" and mimeType = "application/vnd.3gpp2.tcap" - or - ext = ".tcl" and mimeType = "application/x-tcl" - or - ext = ".tex" and mimeType = "application/x-tex" - or - ext = ".texi" and mimeType = "application/x-texinfo" - or - ext = ".texinfo" and mimeType = "application/x-texinfo" - or - ext = ".text" and mimeType = "text/plain" - or - ext = ".tif" and mimeType = "image/tiff" - or - ext = ".tiff" and mimeType = "image/tiff" - or - ext = ".tmo" and mimeType = "application/vnd.tmobile-livetv" - or - ext = ".torrent" and mimeType = "application/x-bittorrent" - or - ext = ".tpl" and mimeType = "application/vnd.groove-tool-template" - or - ext = ".tpt" and mimeType = "application/vnd.trid.tpt" - or - ext = ".tr" and mimeType = "text/troff" - or - ext = ".tra" and mimeType = "application/vnd.trueapp" - or - ext = ".trm" and mimeType = "application/x-msterminal" - or - ext = ".ts" and mimeType = "video/mp2t" - or - ext = ".tsv" and mimeType = "text/tab-separated-values" - or - ext = ".ttf" and mimeType = "application/octet-stream" - or - ext = ".twd" and mimeType = "application/vnd.simtech-mindmapper" - or - ext = ".txd" and mimeType = "application/vnd.genomatix.tuxedo" - or - ext = ".txf" and mimeType = "application/vnd.mobius.txf" - or - ext = ".txt" and mimeType = "text/plain" - or - ext = ".ufd" and mimeType = "application/vnd.ufdl" - or - ext = ".umj" and mimeType = "application/vnd.umajin" - or - ext = ".unityweb" and mimeType = "application/vnd.unity" - or - ext = ".uoml" and mimeType = "application/vnd.uoml+xml" - or - ext = ".uri" and mimeType = "text/uri-list" - or - ext = ".ustar" and mimeType = "application/x-ustar" - or - ext = ".utz" and mimeType = "application/vnd.uiq.theme" - or - ext = ".uu" and mimeType = "text/x-uuencode" - or - ext = ".vcd" and mimeType = "application/x-cdlink" - or - ext = ".vcf" and mimeType = "text/x-vcard" - or - ext = ".vcg" and mimeType = "application/vnd.groove-vcard" - or - ext = ".vcs" and mimeType = "text/x-vcalendar" - or - ext = ".vcx" and mimeType = "application/vnd.vcx" - or - ext = ".vis" and mimeType = "application/vnd.visionary" - or - ext = ".viv" and mimeType = "video/vnd.vivo" - or - ext = ".vrml" and mimeType = "model/vrml" - or - ext = ".vsd" and mimeType = "application/vnd.visio" - or - ext = ".vsf" and mimeType = "application/vnd.vsf" - or - ext = ".vtt" and mimeType = "text/vtt" - or - ext = ".vtu" and mimeType = "model/vnd.vtu" - or - ext = ".vxml" and mimeType = "application/voicexml+xml" - or - ext = ".war" and mimeType = "application/java-archive" - or - ext = ".wasm" and mimeType = "application/wasm" - or - ext = ".wav" and mimeType = "audio/x-wav" - or - ext = ".wax" and mimeType = "audio/x-ms-wax" - or - ext = ".wbmp" and mimeType = "image/vnd.wap.wbmp" - or - ext = ".wbs" and mimeType = "application/vnd.criticaltools.wbs+xml" - or - ext = ".wbxml" and mimeType = "application/vnd.wap.wbxml" - or - ext = ".webm" and mimeType = "video/webm" - or - ext = ".webp" and mimeType = "image/webp" - or - ext = ".wm" and mimeType = "video/x-ms-wm" - or - ext = ".wma" and mimeType = "audio/x-ms-wma" - or - ext = ".wmd" and mimeType = "application/x-ms-wmd" - or - ext = ".wmf" and mimeType = "application/x-msmetafile" - or - ext = ".wml" and mimeType = "text/vnd.wap.wml" - or - ext = ".wmlc" and mimeType = "application/vnd.wap.wmlc" - or - ext = ".wmls" and mimeType = "text/vnd.wap.wmlscript" - or - ext = ".wmlsc" and mimeType = "application/vnd.wap.wmlscriptc" - or - ext = ".wmv" and mimeType = "video/x-ms-wmv" - or - ext = ".wmx" and mimeType = "video/x-ms-wmx" - or - ext = ".wmz" and mimeType = "application/x-ms-wmz" - or - ext = ".woff" and mimeType = "application/font-woff" - or - ext = ".woff2" and mimeType = "application/font-woff2" - or - ext = ".wpd" and mimeType = "application/vnd.wordperfect" - or - ext = ".wpl" and mimeType = "application/vnd.ms-wpl" - or - ext = ".wps" and mimeType = "application/vnd.ms-works" - or - ext = ".wqd" and mimeType = "application/vnd.wqd" - or - ext = ".wri" and mimeType = "application/x-mswrite" - or - ext = ".wrl" and mimeType = "model/vrml" - or - ext = ".wsdl" and mimeType = "application/wsdl+xml" - or - ext = ".wspolicy" and mimeType = "application/wspolicy+xml" - or - ext = ".wtb" and mimeType = "application/vnd.webturbo" - or - ext = ".wvx" and mimeType = "video/x-ms-wvx" - or - ext = ".x3d" and mimeType = "application/vnd.hzn-3d-crossword" - or - ext = ".xar" and mimeType = "application/vnd.xara" - or - ext = ".xbd" and mimeType = "application/vnd.fujixerox.docuworks.binder" - or - ext = ".xbm" and mimeType = "image/x-xbitmap" - or - ext = ".xdm" and mimeType = "application/vnd.syncml.dm+xml" - or - ext = ".xdp" and mimeType = "application/vnd.adobe.xdp+xml" - or - ext = ".xdw" and mimeType = "application/vnd.fujixerox.docuworks" - or - ext = ".xenc" and mimeType = "application/xenc+xml" - or - ext = ".xer" and mimeType = "application/patch-ops-error+xml" - or - ext = ".xfdf" and mimeType = "application/vnd.adobe.xfdf" - or - ext = ".xfdl" and mimeType = "application/vnd.xfdl" - or - ext = ".xhtml" and mimeType = "application/xhtml+xml" - or - ext = ".xif" and mimeType = "image/vnd.xiff" - or - ext = ".xla" and mimeType = "application/vnd.ms-excel" - or - ext = ".xlam" and mimeType = "application/vnd.ms-excel.addin.macroEnabled.12" - or - ext = ".xls" and mimeType = "application/vnd.ms-excel" - or - ext = ".xlsb" and mimeType = "application/vnd.ms-excel.sheet.binary.macroEnabled.12" - or - ext = ".xlsx" and mimeType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" - or - ext = ".xlsm" and mimeType = "application/vnd.ms-excel.sheet.macroEnabled.12" - or - ext = ".xlt" and mimeType = "application/vnd.ms-excel" - or - ext = ".xltx" and - mimeType = "application/vnd.openxmlformats-officedocument.spreadsheetml.template" - or - ext = ".xml" and mimeType = "application/xml" - or - ext = ".xo" and mimeType = "application/vnd.olpc-sugar" - or - ext = ".xop" and mimeType = "application/xop+xml" - or - ext = ".xpm" and mimeType = "image/x-xpixmap" - or - ext = ".xpr" and mimeType = "application/vnd.is-xpr" - or - ext = ".xps" and mimeType = "application/vnd.ms-xpsdocument" - or - ext = ".xpw" and mimeType = "application/vnd.intercon.formnet" - or - ext = ".xsl" and mimeType = "application/xml" - or - ext = ".xslt" and mimeType = "application/xslt+xml" - or - ext = ".xsm" and mimeType = "application/vnd.syncml+xml" - or - ext = ".xspf" and mimeType = "application/xspf+xml" - or - ext = ".xul" and mimeType = "application/vnd.mozilla.xul+xml" - or - ext = ".xwd" and mimeType = "image/x-xwindowdump" - or - ext = ".xyz" and mimeType = "chemical/x-xyz" - or - ext = ".yaml" and mimeType = "text/yaml" - or - ext = ".yml" and mimeType = "text/yaml" - or - ext = ".zaz" and mimeType = "application/vnd.zzazz.deck+xml" - or - ext = ".zip" and mimeType = "application/zip" - or - ext = ".zmm" and mimeType = "application/vnd.handheld-entertainment+xml" -} - -/** - * Provides modeling for the `Mime` component of the `Rack` library. - */ -module Mime { - /** A call to `Rack::Mime.mime_type`. This method maps file extensions to MIME types. */ - class MimetypeCall extends DataFlow::CallNode { - MimetypeCall() { - this = API::getTopLevelMember("Rack").getMember("Mime").getAMethodCall("mime_type") - } - - private string getExtension() { - result = this.getArgument(0).getConstantValue().getStringlikeValue() - } - - /** Gets the canonical MIME type string returned by this call. */ - string getMimetype() { mimetypeMatches(this.getExtension(), result) } - } -} diff --git a/ruby/ql/test/library-tests/frameworks/rack/Rack.expected b/ruby/ql/test/library-tests/frameworks/rack/Rack.expected index a2671c95cb7a..c55afeb78010 100644 --- a/ruby/ql/test/library-tests/frameworks/rack/Rack.expected +++ b/ruby/ql/test/library-tests/frameworks/rack/Rack.expected @@ -6,8 +6,6 @@ rackApps | rack.rb:59:1:75:3 | Baz | rack.rb:60:12:60:14 | env | rackResponseContentTypes | rack.rb:8:5:8:38 | call to [] | rack.rb:7:34:7:45 | "text/plain" | -| rack.rb:20:5:20:27 | call to [] | rack.rb:19:28:19:54 | call to mime_type | -mimetypeCalls -| rack.rb:19:28:19:54 | call to mime_type | application/x-gzip | +| rack.rb:20:5:20:27 | call to [] | rack.rb:19:28:19:38 | "text/html" | redirectResponses | rack.rb:43:5:43:45 | call to [] | rack.rb:42:30:42:40 | "/foo.html" | diff --git a/ruby/ql/test/library-tests/frameworks/rack/Rack.ql b/ruby/ql/test/library-tests/frameworks/rack/Rack.ql index e1f1c506994d..9b5d0629a9f0 100644 --- a/ruby/ql/test/library-tests/frameworks/rack/Rack.ql +++ b/ruby/ql/test/library-tests/frameworks/rack/Rack.ql @@ -12,10 +12,6 @@ query predicate rackResponseContentTypes( contentType = resp.getMimetypeOrContentTypeArg() } -query predicate mimetypeCalls(Rack::Mime::MimetypeCall c, string mimetype) { - mimetype = c.getMimetype() -} - query predicate redirectResponses(Rack::Response::RedirectResponse resp, DataFlow::Node location) { location = resp.getRedirectLocation() } diff --git a/ruby/ql/test/library-tests/frameworks/rack/rack.rb b/ruby/ql/test/library-tests/frameworks/rack/rack.rb index c2e2598e5ec8..9f743496ad26 100644 --- a/ruby/ql/test/library-tests/frameworks/rack/rack.rb +++ b/ruby/ql/test/library-tests/frameworks/rack/rack.rb @@ -16,7 +16,7 @@ def initialize(app) def call(the_env) status, headers, body = @app.call(the_env) - headers.content_type = Rack::Mime.mime_type(".gz") + headers.content_type = "text/html" [status, headers, body] end end From 8ef8a0d2f63bd9b4e66fa95a1500b5272bf0e4d6 Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Tue, 20 Jun 2023 14:59:13 +0100 Subject: [PATCH 23/23] qlformat --- ruby/ql/lib/codeql/ruby/frameworks/Rack.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll b/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll index 4d9342d88054..6963f37a81c7 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/Rack.qll @@ -7,8 +7,8 @@ */ module Rack { import rack.internal.App -import rack.internal.Response::Public as Response + import rack.internal.Response::Public as Response -/** DEPRECATED: Alias for App::AppCandidate */ -deprecated class AppCandidate = App::AppCandidate; + /** DEPRECATED: Alias for App::AppCandidate */ + deprecated class AppCandidate = App::AppCandidate; }