From 6c8cc79b4ddc3b90fb02a25ab96842eb0447d4ad Mon Sep 17 00:00:00 2001 From: amammad <77095239+amammad@users.noreply.github.com> Date: Sun, 8 Oct 2023 21:24:54 +0200 Subject: [PATCH 01/10] v1 --- python/ql/lib/semmle/python/Frameworks.qll | 2 + .../python/frameworks/FileSystemAccess.qll | 95 +++++++++++++++++++ .../ql/lib/semmle/python/frameworks/Sanic.qll | 42 ++++++++ .../semmle/python/frameworks/Starlette.qll | 27 ++++++ .../lib/semmle/python/frameworks/Stdlib.qll | 20 ++++ .../FileSystemAccess/ConceptsTest.expected | 2 + .../FileSystemAccess/ConceptsTest.ql | 2 + .../FileSystemAccess/Query.expected | 0 .../frameworks/FileSystemAccess/Query.ql | 20 ++++ .../frameworks/FileSystemAccess/aiofile.py | 4 + .../frameworks/FileSystemAccess/aiofiles.py | 3 + .../frameworks/FileSystemAccess/anyio.py | 8 ++ .../frameworks/FileSystemAccess/sanic.py | 4 + .../frameworks/FileSystemAccess/starlette.py | 5 + .../frameworks/stdlib/ConceptsTest.expected | 2 +- .../frameworks/stdlib/FileSystemAccess.py | 2 + 16 files changed, 237 insertions(+), 1 deletion(-) create mode 100644 python/ql/lib/semmle/python/frameworks/FileSystemAccess.qll create mode 100644 python/ql/lib/semmle/python/frameworks/Sanic.qll create mode 100644 python/ql/test/library-tests/frameworks/FileSystemAccess/ConceptsTest.expected create mode 100644 python/ql/test/library-tests/frameworks/FileSystemAccess/ConceptsTest.ql create mode 100644 python/ql/test/library-tests/frameworks/FileSystemAccess/Query.expected create mode 100644 python/ql/test/library-tests/frameworks/FileSystemAccess/Query.ql create mode 100644 python/ql/test/library-tests/frameworks/FileSystemAccess/aiofile.py create mode 100644 python/ql/test/library-tests/frameworks/FileSystemAccess/aiofiles.py create mode 100644 python/ql/test/library-tests/frameworks/FileSystemAccess/anyio.py create mode 100644 python/ql/test/library-tests/frameworks/FileSystemAccess/sanic.py create mode 100644 python/ql/test/library-tests/frameworks/FileSystemAccess/starlette.py diff --git a/python/ql/lib/semmle/python/Frameworks.qll b/python/ql/lib/semmle/python/Frameworks.qll index ff0650fcda0..8b32dcccfb6 100644 --- a/python/ql/lib/semmle/python/Frameworks.qll +++ b/python/ql/lib/semmle/python/Frameworks.qll @@ -21,6 +21,7 @@ private import semmle.python.frameworks.Dill private import semmle.python.frameworks.Django private import semmle.python.frameworks.Fabric private import semmle.python.frameworks.FastApi +private import semmle.python.frameworks.FileSystemAccess private import semmle.python.frameworks.Flask private import semmle.python.frameworks.FlaskAdmin private import semmle.python.frameworks.FlaskSqlAlchemy @@ -51,6 +52,7 @@ private import semmle.python.frameworks.Requests private import semmle.python.frameworks.RestFramework private import semmle.python.frameworks.Rsa private import semmle.python.frameworks.RuamelYaml +private import semmle.python.frameworks.Sanic private import semmle.python.frameworks.ServerLess private import semmle.python.frameworks.Simplejson private import semmle.python.frameworks.SqlAlchemy diff --git a/python/ql/lib/semmle/python/frameworks/FileSystemAccess.qll b/python/ql/lib/semmle/python/frameworks/FileSystemAccess.qll new file mode 100644 index 00000000000..25060eccf58 --- /dev/null +++ b/python/ql/lib/semmle/python/frameworks/FileSystemAccess.qll @@ -0,0 +1,95 @@ +/** + * Provides classes modeling security-relevant aspects of the I/O write or read operations + */ + +private import python +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.dataflow.new.RemoteFlowSources +private import semmle.python.dataflow.new.TaintTracking +private import semmle.python.Concepts +private import semmle.python.ApiGraphs + +/** + * Provides models for the `aiofile` PyPI package. + * See https://github.com/agronholm/anyio. + */ +private module Aiofile { + /** + * A call to the `async_open` function or `AIOFile` constructor from `aiofile` as a sink for Filesystem access. + */ + class FileResponseCall extends FileSystemAccess::Range, API::CallNode { + string methodName; + + FileResponseCall() { + this = API::moduleImport("aiofile").getMember("async_open").getACall() and + methodName = "async_open" + or + this = API::moduleImport("aiofile").getMember("AIOFile").getACall() and + methodName = "AIOFile" + } + + override DataFlow::Node getAPathArgument() { + result = this.getParameter(0, "file_specifier").asSink() and + methodName = "async_open" + or + result = this.getParameter(0, "filename").asSink() and + methodName = "AIOFile" + } + } +} + +/** + * Provides models for the `aiofiles` PyPI package. + * See https://github.com/Tinche/aiofiles. + */ +private module Aiofiles { + /** + * A call to the `open` function from `aiofiles` as a sink for Filesystem access. + */ + class FileResponseCall extends FileSystemAccess::Range, API::CallNode { + FileResponseCall() { this = API::moduleImport("aiofiles").getMember("open").getACall() } + + override DataFlow::Node getAPathArgument() { result = this.getParameter(0, "file").asSink() } + } +} + +/** + * Provides models for the `anyio` PyPI package. + * See https://github.com/agronholm/anyio. + */ +private module Anyio { + /** + * A call to the `from_path` function from `FileReadStream` or `FileWriteStream` constructors of `anyio.streams.file` as a sink for Filesystem access. + */ + class FileStreamCall extends FileSystemAccess::Range, API::CallNode { + FileStreamCall() { + this = + API::moduleImport("anyio") + .getMember("streams") + .getMember("file") + .getMember(["FileReadStream", "FileWriteStream"]) + .getMember("from_path") + .getACall() + } + + override DataFlow::Node getAPathArgument() { result = this.getParameter(0, "path").asSink() } + } + + /** + * A call to the `Path` constructor from `anyio` as a sink for Filesystem access. + */ + class PathCall extends FileSystemAccess::Range, API::CallNode { + PathCall() { this = API::moduleImport("anyio").getMember("Path").getACall() } + + override DataFlow::Node getAPathArgument() { result = this.getParameter(0).asSink() } + } + + /** + * A call to the `open_file` function from `anyio` as a sink for Filesystem access. + */ + class OpenFileCall extends FileSystemAccess::Range, API::CallNode { + OpenFileCall() { this = API::moduleImport("anyio").getMember("open_file").getACall() } + + override DataFlow::Node getAPathArgument() { result = this.getParameter(0, "file").asSink() } + } +} diff --git a/python/ql/lib/semmle/python/frameworks/Sanic.qll b/python/ql/lib/semmle/python/frameworks/Sanic.qll new file mode 100644 index 00000000000..e973109f98a --- /dev/null +++ b/python/ql/lib/semmle/python/frameworks/Sanic.qll @@ -0,0 +1,42 @@ +/** + * Provides classes modeling security-relevant aspects of the `sanic` PyPI package. + * See https://sanic.dev/. + */ + +private import python +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.dataflow.new.RemoteFlowSources +private import semmle.python.dataflow.new.TaintTracking +private import semmle.python.Concepts +private import semmle.python.ApiGraphs + +/** + * Provides models for the `sanic` PyPI package. + * See https://sanic.dev/. + */ +private module Sanic { + /** + * Provides models for Sanic applications (an instance of `sanic.Sanic`). + */ + module App { + /** Gets a reference to a Sanic application (an instance of `sanic.Sanic`). */ + API::Node instance() { result = API::moduleImport("sanic").getMember("Sanic").getReturn() } + } + + /** + * A call to the `file` or `file_stream` functions of `sanic.response` as a sink for Filesystem access. + */ + class FileResponseCall extends FileSystemAccess::Range, API::CallNode { + FileResponseCall() { + this = + API::moduleImport("sanic") + .getMember("response") + .getMember(["file", "file_stream"]) + .getACall() + } + + override DataFlow::Node getAPathArgument() { + result = this.getParameter(0, "location").asSink() + } + } +} diff --git a/python/ql/lib/semmle/python/frameworks/Starlette.qll b/python/ql/lib/semmle/python/frameworks/Starlette.qll index cee5100d436..2141aed80ca 100644 --- a/python/ql/lib/semmle/python/frameworks/Starlette.qll +++ b/python/ql/lib/semmle/python/frameworks/Starlette.qll @@ -163,4 +163,31 @@ module Starlette { /** DEPRECATED: Alias for Url */ deprecated module URL = Url; + + /** + * A call to the `starlette.responses.FileResponse` constructor as a sink for Filesystem access. + */ + class FileResponseCall extends FileSystemAccess::Range, API::CallNode { + FileResponseCall() { + this = + API::moduleImport("starlette").getMember("responses").getMember("FileResponse").getACall() + } + + override DataFlow::Node getAPathArgument() { result = this.getParameter(0, "path").asSink() } + } + + /** + * A call to the `baize.asgi.FileResponse` constructor as a sink for Filesystem access. + * + * it is not contained to Starlette source code but it is mentioned as an alternative to Starlette FileResponse + */ + class BaizeFileResponseCall extends FileSystemAccess::Range, API::CallNode { + BaizeFileResponseCall() { + this = API::moduleImport("baize").getMember("asgi").getMember("FileResponse").getACall() + } + + override DataFlow::Node getAPathArgument() { + result = this.getParameter(0, "filepath").asSink() + } + } } diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index ec79a6dfddf..193ca36d156 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -1479,6 +1479,26 @@ private module StdlibPrivate { } } + /** + * A call to the `io.FileIO` constructor. + * See https://docs.python.org/3/library/io.html#io.FileIO + */ + private class FileIOCall extends FileSystemAccess::Range, API::CallNode { + FileIOCall() { this = API::moduleImport("io").getMember("FileIO").getACall() } + + override DataFlow::Node getAPathArgument() { result = this.getParameter(0, "file").asSink() } + } + + /** + * A call to the `io.open_code` function. + * See https://docs.python.org/3/library/io.html#io.FileIO + */ + private class OpenCodeCall extends FileSystemAccess::Range, API::CallNode { + OpenCodeCall() { this = API::moduleImport("io").getMember("open_code").getACall() } + + override DataFlow::Node getAPathArgument() { result = this.getParameter(0, "path").asSink() } + } + /** Gets a reference to an open file. */ private DataFlow::TypeTrackingNode openFile(DataFlow::TypeTracker t, FileSystemAccess openCall) { t.start() and diff --git a/python/ql/test/library-tests/frameworks/FileSystemAccess/ConceptsTest.expected b/python/ql/test/library-tests/frameworks/FileSystemAccess/ConceptsTest.expected new file mode 100644 index 00000000000..8ec8033d086 --- /dev/null +++ b/python/ql/test/library-tests/frameworks/FileSystemAccess/ConceptsTest.expected @@ -0,0 +1,2 @@ +testFailures +failures diff --git a/python/ql/test/library-tests/frameworks/FileSystemAccess/ConceptsTest.ql b/python/ql/test/library-tests/frameworks/FileSystemAccess/ConceptsTest.ql new file mode 100644 index 00000000000..b557a0bccb6 --- /dev/null +++ b/python/ql/test/library-tests/frameworks/FileSystemAccess/ConceptsTest.ql @@ -0,0 +1,2 @@ +import python +import experimental.meta.ConceptsTest diff --git a/python/ql/test/library-tests/frameworks/FileSystemAccess/Query.expected b/python/ql/test/library-tests/frameworks/FileSystemAccess/Query.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/ql/test/library-tests/frameworks/FileSystemAccess/Query.ql b/python/ql/test/library-tests/frameworks/FileSystemAccess/Query.ql new file mode 100644 index 00000000000..5f89e028f04 --- /dev/null +++ b/python/ql/test/library-tests/frameworks/FileSystemAccess/Query.ql @@ -0,0 +1,20 @@ +import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.Concepts +import TestUtilities.InlineExpectationsTest +private import semmle.python.dataflow.new.internal.PrintNode + +module FileSystemAccessTest implements TestSig { + string getARelevantTag() { result = "getAPathArgument" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + exists(location.getFile().getRelativePath()) and + exists(FileSystemAccess a, DataFlow::Node path | + path = a.getAPathArgument() and + location = a.getLocation() and + element = path.toString() and + value = prettyNodeForInlineTest(path) and + tag = "getAPathArgument" + ) + } +} diff --git a/python/ql/test/library-tests/frameworks/FileSystemAccess/aiofile.py b/python/ql/test/library-tests/frameworks/FileSystemAccess/aiofile.py new file mode 100644 index 00000000000..4546e17eb1a --- /dev/null +++ b/python/ql/test/library-tests/frameworks/FileSystemAccess/aiofile.py @@ -0,0 +1,4 @@ +from aiofile import async_open, AIOFile + +AIOFile("file", 'r') # $ getAPathArgument="file" +async_open("file", "r") # $ getAPathArgument="file" diff --git a/python/ql/test/library-tests/frameworks/FileSystemAccess/aiofiles.py b/python/ql/test/library-tests/frameworks/FileSystemAccess/aiofiles.py new file mode 100644 index 00000000000..d99ccefdf87 --- /dev/null +++ b/python/ql/test/library-tests/frameworks/FileSystemAccess/aiofiles.py @@ -0,0 +1,3 @@ +import aiofiles + +aiofiles.open("file", mode='r') # $ getAPathArgument="file" diff --git a/python/ql/test/library-tests/frameworks/FileSystemAccess/anyio.py b/python/ql/test/library-tests/frameworks/FileSystemAccess/anyio.py new file mode 100644 index 00000000000..abc66c42b61 --- /dev/null +++ b/python/ql/test/library-tests/frameworks/FileSystemAccess/anyio.py @@ -0,0 +1,8 @@ +import anyio +from anyio.streams.file import FileReadStream, FileWriteStream +from anyio import Path + +anyio.open_file("file", 'r') # $ getAPathArgument="file" +FileReadStream.from_path("file") # $ getAPathArgument="file" +FileWriteStream.from_path("file") # $ getAPathArgument="file" +Path("file") # $ getAPathArgument="file" diff --git a/python/ql/test/library-tests/frameworks/FileSystemAccess/sanic.py b/python/ql/test/library-tests/frameworks/FileSystemAccess/sanic.py new file mode 100644 index 00000000000..2f12e476235 --- /dev/null +++ b/python/ql/test/library-tests/frameworks/FileSystemAccess/sanic.py @@ -0,0 +1,4 @@ +from sanic import response + +response.file("file") # $ getAPathArgument="file" +response.file_stream("file") # $ getAPathArgument="file" diff --git a/python/ql/test/library-tests/frameworks/FileSystemAccess/starlette.py b/python/ql/test/library-tests/frameworks/FileSystemAccess/starlette.py new file mode 100644 index 00000000000..5982a937cba --- /dev/null +++ b/python/ql/test/library-tests/frameworks/FileSystemAccess/starlette.py @@ -0,0 +1,5 @@ +from starlette.responses import FileResponse +from baize.asgi import FileResponse as baizeFileResponse + +baizeFileResponse("file") # $ getAPathArgument="file" +FileResponse("file") # $ getAPathArgument="file" diff --git a/python/ql/test/library-tests/frameworks/stdlib/ConceptsTest.expected b/python/ql/test/library-tests/frameworks/stdlib/ConceptsTest.expected index 48de9172b36..8ec8033d086 100644 --- a/python/ql/test/library-tests/frameworks/stdlib/ConceptsTest.expected +++ b/python/ql/test/library-tests/frameworks/stdlib/ConceptsTest.expected @@ -1,2 +1,2 @@ -failures testFailures +failures diff --git a/python/ql/test/library-tests/frameworks/stdlib/FileSystemAccess.py b/python/ql/test/library-tests/frameworks/stdlib/FileSystemAccess.py index 21d66fa548a..197ccd8eb91 100644 --- a/python/ql/test/library-tests/frameworks/stdlib/FileSystemAccess.py +++ b/python/ql/test/library-tests/frameworks/stdlib/FileSystemAccess.py @@ -20,6 +20,8 @@ builtins.open(file="file") # $ getAPathArgument="file" io.open("file") # $ getAPathArgument="file" io.open(file="file") # $ getAPathArgument="file" +io.open_code("file") # $ getAPathArgument="file" +io.FileIO("file") # $ getAPathArgument="file" f = open("path") # $ getAPathArgument="path" f.write("foo") # $ getAPathArgument="path" fileWriteData="foo" From ad2631202de385b94172a6e69e9aa23a0af8d294 Mon Sep 17 00:00:00 2001 From: amammad <77095239+amammad@users.noreply.github.com> Date: Sun, 8 Oct 2023 21:29:55 +0200 Subject: [PATCH 02/10] fix comments --- python/ql/lib/semmle/python/frameworks/FileSystemAccess.qll | 2 +- python/ql/lib/semmle/python/frameworks/Starlette.qll | 2 +- python/ql/lib/semmle/python/frameworks/Stdlib.qll | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/python/ql/lib/semmle/python/frameworks/FileSystemAccess.qll b/python/ql/lib/semmle/python/frameworks/FileSystemAccess.qll index 25060eccf58..9c936e4075d 100644 --- a/python/ql/lib/semmle/python/frameworks/FileSystemAccess.qll +++ b/python/ql/lib/semmle/python/frameworks/FileSystemAccess.qll @@ -1,5 +1,5 @@ /** - * Provides classes modeling security-relevant aspects of the I/O write or read operations + * Provides classes modeling security-relevant aspects of the I/O file write or file read operations */ private import python diff --git a/python/ql/lib/semmle/python/frameworks/Starlette.qll b/python/ql/lib/semmle/python/frameworks/Starlette.qll index 2141aed80ca..ec41376cf67 100644 --- a/python/ql/lib/semmle/python/frameworks/Starlette.qll +++ b/python/ql/lib/semmle/python/frameworks/Starlette.qll @@ -179,7 +179,7 @@ module Starlette { /** * A call to the `baize.asgi.FileResponse` constructor as a sink for Filesystem access. * - * it is not contained to Starlette source code but it is mentioned as an alternative to Starlette FileResponse + * it is not contained to Starlette source code but it is mentioned in documents as an alternative to Starlette FileResponse */ class BaizeFileResponseCall extends FileSystemAccess::Range, API::CallNode { BaizeFileResponseCall() { diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 193ca36d156..c8ba48a12d2 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -1491,7 +1491,7 @@ private module StdlibPrivate { /** * A call to the `io.open_code` function. - * See https://docs.python.org/3/library/io.html#io.FileIO + * See https://docs.python.org/3.11/library/io.html#io.open_code */ private class OpenCodeCall extends FileSystemAccess::Range, API::CallNode { OpenCodeCall() { this = API::moduleImport("io").getMember("open_code").getACall() } From 1fe565a46fc535351934a8d55660b343d25e03cf Mon Sep 17 00:00:00 2001 From: amammad <77095239+amammad@users.noreply.github.com> Date: Sat, 21 Oct 2023 19:42:50 +0200 Subject: [PATCH 03/10] cherrypy framework file system access Sinks are added --- .../lib/semmle/python/frameworks/Cherrypy.qll | 48 +++++++++++++++++++ .../frameworks/FileSystemAccess/cherrypy.py | 8 ++++ 2 files changed, 56 insertions(+) create mode 100644 python/ql/lib/semmle/python/frameworks/Cherrypy.qll create mode 100644 python/ql/test/library-tests/frameworks/FileSystemAccess/cherrypy.py diff --git a/python/ql/lib/semmle/python/frameworks/Cherrypy.qll b/python/ql/lib/semmle/python/frameworks/Cherrypy.qll new file mode 100644 index 00000000000..c589d150f56 --- /dev/null +++ b/python/ql/lib/semmle/python/frameworks/Cherrypy.qll @@ -0,0 +1,48 @@ +/** + * Provides classes modeling security-relevant aspects of the `cherrypy` PyPI package. + */ + +private import python +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.dataflow.new.RemoteFlowSources +private import semmle.python.dataflow.new.TaintTracking +private import semmle.python.Concepts +private import semmle.python.ApiGraphs + +/** + * Provides models for the `cherrypy` PyPI package. + * See https://cherrypy.dev/. + */ +private module Cherrypy { + /** + * Holds for an instance of `cherrypy.lib.static` + */ + API::Node libStatic() { + result = API::moduleImport("cherrypy").getMember("lib").getMember("static") + } + + /** + * A call to the `serve_file` or `serve_download`or `staticfile` functions of `cherrypy.lib.static` as a sink for Filesystem access. + */ + class FileResponseCall extends FileSystemAccess::Range, API::CallNode { + string funcName; + + FileResponseCall() { + this = libStatic().getMember("staticfile").getACall() and + funcName = "staticfile" + or + this = libStatic().getMember("serve_file").getACall() and + funcName = "serve_file" + or + this = libStatic().getMember("serve_download").getACall() and + funcName = "serve_download" + } + + override DataFlow::Node getAPathArgument() { + result = this.getParameter(0, "path").asSink() and funcName = ["serve_download", "serve_file"] + or + result = this.getParameter(0, "filename").asSink() and + funcName = "staticfile" + } + } +} diff --git a/python/ql/test/library-tests/frameworks/FileSystemAccess/cherrypy.py b/python/ql/test/library-tests/frameworks/FileSystemAccess/cherrypy.py new file mode 100644 index 00000000000..04400c1ed8f --- /dev/null +++ b/python/ql/test/library-tests/frameworks/FileSystemAccess/cherrypy.py @@ -0,0 +1,8 @@ +import cherrypy +from cherrypy.lib.static import serve_file, serve_download, staticfile + +serve_file("file") # $ getAPathArgument="file" +serve_download("file") # $ getAPathArgument="file" +staticfile("file") # $ getAPathArgument="file" +# root won't make this safe +staticfile("file", root="/path/to/safe/dir") # $ getAPathArgument="file" From a0e2e1ef2105faba1f728c7cd0fda382c70545a4 Mon Sep 17 00:00:00 2001 From: amammad <77095239+amammad@users.noreply.github.com> Date: Sat, 21 Oct 2023 19:49:27 +0200 Subject: [PATCH 04/10] add to Frameworks.qll --- python/ql/lib/semmle/python/Frameworks.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/python/ql/lib/semmle/python/Frameworks.qll b/python/ql/lib/semmle/python/Frameworks.qll index 8b32dcccfb6..cfb34d0db78 100644 --- a/python/ql/lib/semmle/python/Frameworks.qll +++ b/python/ql/lib/semmle/python/Frameworks.qll @@ -12,6 +12,7 @@ private import semmle.python.frameworks.Aiopg private import semmle.python.frameworks.Asyncpg private import semmle.python.frameworks.BSon private import semmle.python.frameworks.CassandraDriver +private import semmle.python.frameworks.Cherrypy private import semmle.python.frameworks.ClickhouseDriver private import semmle.python.frameworks.Cryptodome private import semmle.python.frameworks.Cryptography From 3d8a7e0ee319471fb9a0b78f40425e49fcfefed6 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 6 Nov 2023 11:29:52 +0100 Subject: [PATCH 05/10] Python: Add change-note --- .../src/change-notes/2023-11-06-more-filesystem-modeling.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 python/ql/src/change-notes/2023-11-06-more-filesystem-modeling.md diff --git a/python/ql/src/change-notes/2023-11-06-more-filesystem-modeling.md b/python/ql/src/change-notes/2023-11-06-more-filesystem-modeling.md new file mode 100644 index 00000000000..f801e5c22b5 --- /dev/null +++ b/python/ql/src/change-notes/2023-11-06-more-filesystem-modeling.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added modeling of more `FileSystemAccess` in packages `cherrypy`, `aiofile`, `aiofiles`, `anyio`, `sanic`, `starlette`, `baize`, and `io`. This will mainly affect the _Uncontrolled data used in path expression_ (`py/path-injection`) query. From 637c52d10a8c9715114aa99e2daa277d9373f12b Mon Sep 17 00:00:00 2001 From: amammad <77095239+amammad@users.noreply.github.com> Date: Mon, 6 Nov 2023 19:03:55 +0100 Subject: [PATCH 06/10] separate each new FileSystemAccess packages. --- .../lib/semmle/python/frameworks/Aiofile.qll | 42 +++++++++++++++ .../lib/semmle/python/frameworks/Aiofiles.qll | 28 ++++++++++ .../{FileSystemAccess.qll => Anyio.qll} | 51 ++----------------- .../semmle/python/frameworks/Starlette.qll | 15 ------ .../ql/lib/semmle/python/frameworks/baize.qll | 35 +++++++++++++ 5 files changed, 110 insertions(+), 61 deletions(-) create mode 100644 python/ql/lib/semmle/python/frameworks/Aiofile.qll create mode 100644 python/ql/lib/semmle/python/frameworks/Aiofiles.qll rename python/ql/lib/semmle/python/frameworks/{FileSystemAccess.qll => Anyio.qll} (52%) create mode 100644 python/ql/lib/semmle/python/frameworks/baize.qll diff --git a/python/ql/lib/semmle/python/frameworks/Aiofile.qll b/python/ql/lib/semmle/python/frameworks/Aiofile.qll new file mode 100644 index 00000000000..62a561ebc0d --- /dev/null +++ b/python/ql/lib/semmle/python/frameworks/Aiofile.qll @@ -0,0 +1,42 @@ +/** + * Provides classes modeling security-relevant aspects of the `aiofile` PyPI package. + * + * See https://pypi.org/project/aiofile. + */ + +private import python +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.dataflow.new.RemoteFlowSources +private import semmle.python.dataflow.new.TaintTracking +private import semmle.python.Concepts +private import semmle.python.ApiGraphs + +/** + * Provides models for the `aiofile` PyPI package. + * + * See https://pypi.org/project/aiofile. + */ +private module Aiofile { + /** + * A call to the `async_open` function or `AIOFile` constructor from `aiofile` as a sink for Filesystem access. + */ + class FileResponseCall extends FileSystemAccess::Range, API::CallNode { + string methodName; + + FileResponseCall() { + this = API::moduleImport("aiofile").getMember("async_open").getACall() and + methodName = "async_open" + or + this = API::moduleImport("aiofile").getMember("AIOFile").getACall() and + methodName = "AIOFile" + } + + override DataFlow::Node getAPathArgument() { + result = this.getParameter(0, "file_specifier").asSink() and + methodName = "async_open" + or + result = this.getParameter(0, "filename").asSink() and + methodName = "AIOFile" + } + } +} diff --git a/python/ql/lib/semmle/python/frameworks/Aiofiles.qll b/python/ql/lib/semmle/python/frameworks/Aiofiles.qll new file mode 100644 index 00000000000..c65b9993e89 --- /dev/null +++ b/python/ql/lib/semmle/python/frameworks/Aiofiles.qll @@ -0,0 +1,28 @@ +/** + * Provides classes modeling security-relevant aspects of the `aiofiles` PyPI package. + * + * See https://pypi.org/project/aiofiles. + */ + +private import python +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.dataflow.new.RemoteFlowSources +private import semmle.python.dataflow.new.TaintTracking +private import semmle.python.Concepts +private import semmle.python.ApiGraphs + +/** + * Provides models for the `aiofiles` PyPI package. + * + * See https://pypi.org/project/aiofiles. + */ +private module Aiofiles { + /** + * A call to the `open` function from `aiofiles` as a sink for Filesystem access. + */ + class FileResponseCall extends FileSystemAccess::Range, API::CallNode { + FileResponseCall() { this = API::moduleImport("aiofiles").getMember("open").getACall() } + + override DataFlow::Node getAPathArgument() { result = this.getParameter(0, "file").asSink() } + } +} diff --git a/python/ql/lib/semmle/python/frameworks/FileSystemAccess.qll b/python/ql/lib/semmle/python/frameworks/Anyio.qll similarity index 52% rename from python/ql/lib/semmle/python/frameworks/FileSystemAccess.qll rename to python/ql/lib/semmle/python/frameworks/Anyio.qll index 9c936e4075d..d1e21764e9a 100644 --- a/python/ql/lib/semmle/python/frameworks/FileSystemAccess.qll +++ b/python/ql/lib/semmle/python/frameworks/Anyio.qll @@ -1,5 +1,7 @@ /** - * Provides classes modeling security-relevant aspects of the I/O file write or file read operations + * Provides classes modeling security-relevant aspects of the `anyio` PyPI package. + * + * See https://pypi.org/project/anyio. */ private import python @@ -9,53 +11,10 @@ private import semmle.python.dataflow.new.TaintTracking private import semmle.python.Concepts private import semmle.python.ApiGraphs -/** - * Provides models for the `aiofile` PyPI package. - * See https://github.com/agronholm/anyio. - */ -private module Aiofile { - /** - * A call to the `async_open` function or `AIOFile` constructor from `aiofile` as a sink for Filesystem access. - */ - class FileResponseCall extends FileSystemAccess::Range, API::CallNode { - string methodName; - - FileResponseCall() { - this = API::moduleImport("aiofile").getMember("async_open").getACall() and - methodName = "async_open" - or - this = API::moduleImport("aiofile").getMember("AIOFile").getACall() and - methodName = "AIOFile" - } - - override DataFlow::Node getAPathArgument() { - result = this.getParameter(0, "file_specifier").asSink() and - methodName = "async_open" - or - result = this.getParameter(0, "filename").asSink() and - methodName = "AIOFile" - } - } -} - -/** - * Provides models for the `aiofiles` PyPI package. - * See https://github.com/Tinche/aiofiles. - */ -private module Aiofiles { - /** - * A call to the `open` function from `aiofiles` as a sink for Filesystem access. - */ - class FileResponseCall extends FileSystemAccess::Range, API::CallNode { - FileResponseCall() { this = API::moduleImport("aiofiles").getMember("open").getACall() } - - override DataFlow::Node getAPathArgument() { result = this.getParameter(0, "file").asSink() } - } -} - /** * Provides models for the `anyio` PyPI package. - * See https://github.com/agronholm/anyio. + * + * See https://pypi.org/project/anyio. */ private module Anyio { /** diff --git a/python/ql/lib/semmle/python/frameworks/Starlette.qll b/python/ql/lib/semmle/python/frameworks/Starlette.qll index ec41376cf67..bd41401733d 100644 --- a/python/ql/lib/semmle/python/frameworks/Starlette.qll +++ b/python/ql/lib/semmle/python/frameworks/Starlette.qll @@ -175,19 +175,4 @@ module Starlette { override DataFlow::Node getAPathArgument() { result = this.getParameter(0, "path").asSink() } } - - /** - * A call to the `baize.asgi.FileResponse` constructor as a sink for Filesystem access. - * - * it is not contained to Starlette source code but it is mentioned in documents as an alternative to Starlette FileResponse - */ - class BaizeFileResponseCall extends FileSystemAccess::Range, API::CallNode { - BaizeFileResponseCall() { - this = API::moduleImport("baize").getMember("asgi").getMember("FileResponse").getACall() - } - - override DataFlow::Node getAPathArgument() { - result = this.getParameter(0, "filepath").asSink() - } - } } diff --git a/python/ql/lib/semmle/python/frameworks/baize.qll b/python/ql/lib/semmle/python/frameworks/baize.qll new file mode 100644 index 00000000000..907dbb6b86b --- /dev/null +++ b/python/ql/lib/semmle/python/frameworks/baize.qll @@ -0,0 +1,35 @@ +/** + * Provides classes modeling security-relevant aspects of the `baize` PyPI package. + * + * See https://pypi.org/project/baize. + */ + +private import python +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.dataflow.new.TaintTracking +private import semmle.python.Concepts +private import semmle.python.ApiGraphs +private import semmle.python.frameworks.internal.InstanceTaintStepsHelper +private import semmle.python.frameworks.Stdlib + +/** + * Provides models for `baize` PyPI package. + * + * See https://pypi.org/project/baize. + */ +module Starlette { + /** + * A call to the `baize.asgi.FileResponse` constructor as a sink for Filesystem access. + * + * it is not contained to Starlette source code but it is mentioned in documents as an alternative to Starlette FileResponse + */ + class BaizeFileResponseCall extends FileSystemAccess::Range, API::CallNode { + BaizeFileResponseCall() { + this = API::moduleImport("baize").getMember("asgi").getMember("FileResponse").getACall() + } + + override DataFlow::Node getAPathArgument() { + result = this.getParameter(0, "filepath").asSink() + } + } +} From 315bdc2b48712455f8f524804e6eeb837cf8558d Mon Sep 17 00:00:00 2001 From: amammad <77095239+amammad@users.noreply.github.com> Date: Mon, 6 Nov 2023 19:13:57 +0100 Subject: [PATCH 07/10] add tests for new frameworks --- .../FileSystemAccess/ConceptsTest.expected | 2 -- .../FileSystemAccess/Query.expected | 0 .../frameworks/FileSystemAccess/Query.ql | 20 ------------------- .../frameworks/aiofile/ConceptsTest.expected | 1 + .../ConceptsTest.ql | 0 .../FileSystemAccess.py} | 0 .../frameworks/aiofiles/ConceptsTest.expected | 1 + .../frameworks/aiofiles/ConceptsTest.ql | 2 ++ .../FileSystemAccess.py} | 0 .../frameworks/anyio/ConceptsTest.expected | 1 + .../frameworks/anyio/ConceptsTest.ql | 2 ++ .../anyio.py => anyio/FileSystemAccess.py} | 0 .../frameworks/baize/ConceptsTest.expected | 1 + .../frameworks/baize/ConceptsTest.ql | 2 ++ .../FileSystemAccess.py} | 3 +-- .../frameworks/cherrypy/ConceptsTest.expected | 1 + .../frameworks/cherrypy/ConceptsTest.ql | 2 ++ .../FileSystemAccess.py} | 0 .../frameworks/sanic/ConceptsTest.expected | 1 + .../frameworks/sanic/ConceptsTest.ql | 2 ++ .../sanic.py => sanic/FileSystemAccess.py} | 0 .../starlette/ConceptsTest.expected | 1 + .../frameworks/starlette/ConceptsTest.ql | 2 ++ .../frameworks/starlette/FileSystemAccess.py | 3 +++ 24 files changed, 23 insertions(+), 24 deletions(-) delete mode 100644 python/ql/test/library-tests/frameworks/FileSystemAccess/ConceptsTest.expected delete mode 100644 python/ql/test/library-tests/frameworks/FileSystemAccess/Query.expected delete mode 100644 python/ql/test/library-tests/frameworks/FileSystemAccess/Query.ql create mode 100644 python/ql/test/library-tests/frameworks/aiofile/ConceptsTest.expected rename python/ql/test/library-tests/frameworks/{FileSystemAccess => aiofile}/ConceptsTest.ql (100%) rename python/ql/test/library-tests/frameworks/{FileSystemAccess/aiofile.py => aiofile/FileSystemAccess.py} (100%) create mode 100644 python/ql/test/library-tests/frameworks/aiofiles/ConceptsTest.expected create mode 100644 python/ql/test/library-tests/frameworks/aiofiles/ConceptsTest.ql rename python/ql/test/library-tests/frameworks/{FileSystemAccess/aiofiles.py => aiofiles/FileSystemAccess.py} (100%) create mode 100644 python/ql/test/library-tests/frameworks/anyio/ConceptsTest.expected create mode 100644 python/ql/test/library-tests/frameworks/anyio/ConceptsTest.ql rename python/ql/test/library-tests/frameworks/{FileSystemAccess/anyio.py => anyio/FileSystemAccess.py} (100%) create mode 100644 python/ql/test/library-tests/frameworks/baize/ConceptsTest.expected create mode 100644 python/ql/test/library-tests/frameworks/baize/ConceptsTest.ql rename python/ql/test/library-tests/frameworks/{FileSystemAccess/starlette.py => baize/FileSystemAccess.py} (54%) create mode 100644 python/ql/test/library-tests/frameworks/cherrypy/ConceptsTest.expected create mode 100644 python/ql/test/library-tests/frameworks/cherrypy/ConceptsTest.ql rename python/ql/test/library-tests/frameworks/{FileSystemAccess/cherrypy.py => cherrypy/FileSystemAccess.py} (100%) create mode 100644 python/ql/test/library-tests/frameworks/sanic/ConceptsTest.expected create mode 100644 python/ql/test/library-tests/frameworks/sanic/ConceptsTest.ql rename python/ql/test/library-tests/frameworks/{FileSystemAccess/sanic.py => sanic/FileSystemAccess.py} (100%) create mode 100644 python/ql/test/library-tests/frameworks/starlette/ConceptsTest.expected create mode 100644 python/ql/test/library-tests/frameworks/starlette/ConceptsTest.ql create mode 100644 python/ql/test/library-tests/frameworks/starlette/FileSystemAccess.py diff --git a/python/ql/test/library-tests/frameworks/FileSystemAccess/ConceptsTest.expected b/python/ql/test/library-tests/frameworks/FileSystemAccess/ConceptsTest.expected deleted file mode 100644 index 8ec8033d086..00000000000 --- a/python/ql/test/library-tests/frameworks/FileSystemAccess/ConceptsTest.expected +++ /dev/null @@ -1,2 +0,0 @@ -testFailures -failures diff --git a/python/ql/test/library-tests/frameworks/FileSystemAccess/Query.expected b/python/ql/test/library-tests/frameworks/FileSystemAccess/Query.expected deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/python/ql/test/library-tests/frameworks/FileSystemAccess/Query.ql b/python/ql/test/library-tests/frameworks/FileSystemAccess/Query.ql deleted file mode 100644 index 5f89e028f04..00000000000 --- a/python/ql/test/library-tests/frameworks/FileSystemAccess/Query.ql +++ /dev/null @@ -1,20 +0,0 @@ -import python -import semmle.python.dataflow.new.DataFlow -import semmle.python.Concepts -import TestUtilities.InlineExpectationsTest -private import semmle.python.dataflow.new.internal.PrintNode - -module FileSystemAccessTest implements TestSig { - string getARelevantTag() { result = "getAPathArgument" } - - predicate hasActualResult(Location location, string element, string tag, string value) { - exists(location.getFile().getRelativePath()) and - exists(FileSystemAccess a, DataFlow::Node path | - path = a.getAPathArgument() and - location = a.getLocation() and - element = path.toString() and - value = prettyNodeForInlineTest(path) and - tag = "getAPathArgument" - ) - } -} diff --git a/python/ql/test/library-tests/frameworks/aiofile/ConceptsTest.expected b/python/ql/test/library-tests/frameworks/aiofile/ConceptsTest.expected new file mode 100644 index 00000000000..1822a89c5eb --- /dev/null +++ b/python/ql/test/library-tests/frameworks/aiofile/ConceptsTest.expected @@ -0,0 +1 @@ +ERROR: Could not resolve module semmle.python.frameworks.FileSystemAccess (/home/am/CodeQL-home/codeql-repo-amammad/python/ql/lib/semmle/python/Frameworks.qll:25,16-57) diff --git a/python/ql/test/library-tests/frameworks/FileSystemAccess/ConceptsTest.ql b/python/ql/test/library-tests/frameworks/aiofile/ConceptsTest.ql similarity index 100% rename from python/ql/test/library-tests/frameworks/FileSystemAccess/ConceptsTest.ql rename to python/ql/test/library-tests/frameworks/aiofile/ConceptsTest.ql diff --git a/python/ql/test/library-tests/frameworks/FileSystemAccess/aiofile.py b/python/ql/test/library-tests/frameworks/aiofile/FileSystemAccess.py similarity index 100% rename from python/ql/test/library-tests/frameworks/FileSystemAccess/aiofile.py rename to python/ql/test/library-tests/frameworks/aiofile/FileSystemAccess.py diff --git a/python/ql/test/library-tests/frameworks/aiofiles/ConceptsTest.expected b/python/ql/test/library-tests/frameworks/aiofiles/ConceptsTest.expected new file mode 100644 index 00000000000..1822a89c5eb --- /dev/null +++ b/python/ql/test/library-tests/frameworks/aiofiles/ConceptsTest.expected @@ -0,0 +1 @@ +ERROR: Could not resolve module semmle.python.frameworks.FileSystemAccess (/home/am/CodeQL-home/codeql-repo-amammad/python/ql/lib/semmle/python/Frameworks.qll:25,16-57) diff --git a/python/ql/test/library-tests/frameworks/aiofiles/ConceptsTest.ql b/python/ql/test/library-tests/frameworks/aiofiles/ConceptsTest.ql new file mode 100644 index 00000000000..b557a0bccb6 --- /dev/null +++ b/python/ql/test/library-tests/frameworks/aiofiles/ConceptsTest.ql @@ -0,0 +1,2 @@ +import python +import experimental.meta.ConceptsTest diff --git a/python/ql/test/library-tests/frameworks/FileSystemAccess/aiofiles.py b/python/ql/test/library-tests/frameworks/aiofiles/FileSystemAccess.py similarity index 100% rename from python/ql/test/library-tests/frameworks/FileSystemAccess/aiofiles.py rename to python/ql/test/library-tests/frameworks/aiofiles/FileSystemAccess.py diff --git a/python/ql/test/library-tests/frameworks/anyio/ConceptsTest.expected b/python/ql/test/library-tests/frameworks/anyio/ConceptsTest.expected new file mode 100644 index 00000000000..1822a89c5eb --- /dev/null +++ b/python/ql/test/library-tests/frameworks/anyio/ConceptsTest.expected @@ -0,0 +1 @@ +ERROR: Could not resolve module semmle.python.frameworks.FileSystemAccess (/home/am/CodeQL-home/codeql-repo-amammad/python/ql/lib/semmle/python/Frameworks.qll:25,16-57) diff --git a/python/ql/test/library-tests/frameworks/anyio/ConceptsTest.ql b/python/ql/test/library-tests/frameworks/anyio/ConceptsTest.ql new file mode 100644 index 00000000000..b557a0bccb6 --- /dev/null +++ b/python/ql/test/library-tests/frameworks/anyio/ConceptsTest.ql @@ -0,0 +1,2 @@ +import python +import experimental.meta.ConceptsTest diff --git a/python/ql/test/library-tests/frameworks/FileSystemAccess/anyio.py b/python/ql/test/library-tests/frameworks/anyio/FileSystemAccess.py similarity index 100% rename from python/ql/test/library-tests/frameworks/FileSystemAccess/anyio.py rename to python/ql/test/library-tests/frameworks/anyio/FileSystemAccess.py diff --git a/python/ql/test/library-tests/frameworks/baize/ConceptsTest.expected b/python/ql/test/library-tests/frameworks/baize/ConceptsTest.expected new file mode 100644 index 00000000000..1822a89c5eb --- /dev/null +++ b/python/ql/test/library-tests/frameworks/baize/ConceptsTest.expected @@ -0,0 +1 @@ +ERROR: Could not resolve module semmle.python.frameworks.FileSystemAccess (/home/am/CodeQL-home/codeql-repo-amammad/python/ql/lib/semmle/python/Frameworks.qll:25,16-57) diff --git a/python/ql/test/library-tests/frameworks/baize/ConceptsTest.ql b/python/ql/test/library-tests/frameworks/baize/ConceptsTest.ql new file mode 100644 index 00000000000..b557a0bccb6 --- /dev/null +++ b/python/ql/test/library-tests/frameworks/baize/ConceptsTest.ql @@ -0,0 +1,2 @@ +import python +import experimental.meta.ConceptsTest diff --git a/python/ql/test/library-tests/frameworks/FileSystemAccess/starlette.py b/python/ql/test/library-tests/frameworks/baize/FileSystemAccess.py similarity index 54% rename from python/ql/test/library-tests/frameworks/FileSystemAccess/starlette.py rename to python/ql/test/library-tests/frameworks/baize/FileSystemAccess.py index 5982a937cba..d2808292acf 100644 --- a/python/ql/test/library-tests/frameworks/FileSystemAccess/starlette.py +++ b/python/ql/test/library-tests/frameworks/baize/FileSystemAccess.py @@ -1,5 +1,4 @@ -from starlette.responses import FileResponse from baize.asgi import FileResponse as baizeFileResponse baizeFileResponse("file") # $ getAPathArgument="file" -FileResponse("file") # $ getAPathArgument="file" +FileSystemAccess \ No newline at end of file diff --git a/python/ql/test/library-tests/frameworks/cherrypy/ConceptsTest.expected b/python/ql/test/library-tests/frameworks/cherrypy/ConceptsTest.expected new file mode 100644 index 00000000000..1822a89c5eb --- /dev/null +++ b/python/ql/test/library-tests/frameworks/cherrypy/ConceptsTest.expected @@ -0,0 +1 @@ +ERROR: Could not resolve module semmle.python.frameworks.FileSystemAccess (/home/am/CodeQL-home/codeql-repo-amammad/python/ql/lib/semmle/python/Frameworks.qll:25,16-57) diff --git a/python/ql/test/library-tests/frameworks/cherrypy/ConceptsTest.ql b/python/ql/test/library-tests/frameworks/cherrypy/ConceptsTest.ql new file mode 100644 index 00000000000..b557a0bccb6 --- /dev/null +++ b/python/ql/test/library-tests/frameworks/cherrypy/ConceptsTest.ql @@ -0,0 +1,2 @@ +import python +import experimental.meta.ConceptsTest diff --git a/python/ql/test/library-tests/frameworks/FileSystemAccess/cherrypy.py b/python/ql/test/library-tests/frameworks/cherrypy/FileSystemAccess.py similarity index 100% rename from python/ql/test/library-tests/frameworks/FileSystemAccess/cherrypy.py rename to python/ql/test/library-tests/frameworks/cherrypy/FileSystemAccess.py diff --git a/python/ql/test/library-tests/frameworks/sanic/ConceptsTest.expected b/python/ql/test/library-tests/frameworks/sanic/ConceptsTest.expected new file mode 100644 index 00000000000..1822a89c5eb --- /dev/null +++ b/python/ql/test/library-tests/frameworks/sanic/ConceptsTest.expected @@ -0,0 +1 @@ +ERROR: Could not resolve module semmle.python.frameworks.FileSystemAccess (/home/am/CodeQL-home/codeql-repo-amammad/python/ql/lib/semmle/python/Frameworks.qll:25,16-57) diff --git a/python/ql/test/library-tests/frameworks/sanic/ConceptsTest.ql b/python/ql/test/library-tests/frameworks/sanic/ConceptsTest.ql new file mode 100644 index 00000000000..b557a0bccb6 --- /dev/null +++ b/python/ql/test/library-tests/frameworks/sanic/ConceptsTest.ql @@ -0,0 +1,2 @@ +import python +import experimental.meta.ConceptsTest diff --git a/python/ql/test/library-tests/frameworks/FileSystemAccess/sanic.py b/python/ql/test/library-tests/frameworks/sanic/FileSystemAccess.py similarity index 100% rename from python/ql/test/library-tests/frameworks/FileSystemAccess/sanic.py rename to python/ql/test/library-tests/frameworks/sanic/FileSystemAccess.py diff --git a/python/ql/test/library-tests/frameworks/starlette/ConceptsTest.expected b/python/ql/test/library-tests/frameworks/starlette/ConceptsTest.expected new file mode 100644 index 00000000000..1822a89c5eb --- /dev/null +++ b/python/ql/test/library-tests/frameworks/starlette/ConceptsTest.expected @@ -0,0 +1 @@ +ERROR: Could not resolve module semmle.python.frameworks.FileSystemAccess (/home/am/CodeQL-home/codeql-repo-amammad/python/ql/lib/semmle/python/Frameworks.qll:25,16-57) diff --git a/python/ql/test/library-tests/frameworks/starlette/ConceptsTest.ql b/python/ql/test/library-tests/frameworks/starlette/ConceptsTest.ql new file mode 100644 index 00000000000..b557a0bccb6 --- /dev/null +++ b/python/ql/test/library-tests/frameworks/starlette/ConceptsTest.ql @@ -0,0 +1,2 @@ +import python +import experimental.meta.ConceptsTest diff --git a/python/ql/test/library-tests/frameworks/starlette/FileSystemAccess.py b/python/ql/test/library-tests/frameworks/starlette/FileSystemAccess.py new file mode 100644 index 00000000000..d7dff980967 --- /dev/null +++ b/python/ql/test/library-tests/frameworks/starlette/FileSystemAccess.py @@ -0,0 +1,3 @@ +from starlette.responses import FileResponse + +FileResponse("file") # $ getAPathArgument="file" From ad756d59c8f0b10fe292963ada84832bc409caa9 Mon Sep 17 00:00:00 2001 From: amammad <77095239+amammad@users.noreply.github.com> Date: Mon, 6 Nov 2023 19:17:50 +0100 Subject: [PATCH 08/10] put new frameworks in Frameworks.qll and fix some mistakes of Baize --- python/ql/lib/semmle/python/Frameworks.qll | 5 ++++- .../ql/lib/semmle/python/frameworks/{baize.qll => Baize.qll} | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) rename python/ql/lib/semmle/python/frameworks/{baize.qll => Baize.qll} (98%) diff --git a/python/ql/lib/semmle/python/Frameworks.qll b/python/ql/lib/semmle/python/Frameworks.qll index e773735fbbc..801a51008ec 100644 --- a/python/ql/lib/semmle/python/Frameworks.qll +++ b/python/ql/lib/semmle/python/Frameworks.qll @@ -5,11 +5,15 @@ // If you add modeling of a new framework/library, remember to add it to the docs in // `docs/codeql/reusables/supported-frameworks.rst` private import semmle.python.frameworks.Aioch +private import semmle.python.frameworks.Aiofile +private import semmle.python.frameworks.Aiofiles private import semmle.python.frameworks.Aiohttp private import semmle.python.frameworks.Aiomysql private import semmle.python.frameworks.Aiopg private import semmle.python.frameworks.Aiosqlite +private import semmle.python.frameworks.Anyio private import semmle.python.frameworks.Asyncpg +private import semmle.python.frameworks.Baize private import semmle.python.frameworks.BSon private import semmle.python.frameworks.CassandraDriver private import semmle.python.frameworks.Cherrypy @@ -22,7 +26,6 @@ private import semmle.python.frameworks.Dill private import semmle.python.frameworks.Django private import semmle.python.frameworks.Fabric private import semmle.python.frameworks.FastApi -private import semmle.python.frameworks.FileSystemAccess private import semmle.python.frameworks.Flask private import semmle.python.frameworks.FlaskAdmin private import semmle.python.frameworks.FlaskSqlAlchemy diff --git a/python/ql/lib/semmle/python/frameworks/baize.qll b/python/ql/lib/semmle/python/frameworks/Baize.qll similarity index 98% rename from python/ql/lib/semmle/python/frameworks/baize.qll rename to python/ql/lib/semmle/python/frameworks/Baize.qll index 907dbb6b86b..0da77938229 100644 --- a/python/ql/lib/semmle/python/frameworks/baize.qll +++ b/python/ql/lib/semmle/python/frameworks/Baize.qll @@ -17,7 +17,7 @@ private import semmle.python.frameworks.Stdlib * * See https://pypi.org/project/baize. */ -module Starlette { +module Baize { /** * A call to the `baize.asgi.FileResponse` constructor as a sink for Filesystem access. * From e8eff78799536508e22f59f0ac60fbfe5d6980dc Mon Sep 17 00:00:00 2001 From: amammad <77095239+amammad@users.noreply.github.com> Date: Mon, 6 Nov 2023 19:19:36 +0100 Subject: [PATCH 09/10] fix tests because of error in Frameworks.qll --- .../library-tests/frameworks/aiofile/ConceptsTest.expected | 3 ++- .../library-tests/frameworks/aiofiles/ConceptsTest.expected | 3 ++- .../test/library-tests/frameworks/anyio/ConceptsTest.expected | 3 ++- .../test/library-tests/frameworks/baize/ConceptsTest.expected | 3 ++- .../library-tests/frameworks/cherrypy/ConceptsTest.expected | 3 ++- .../test/library-tests/frameworks/sanic/ConceptsTest.expected | 3 ++- .../library-tests/frameworks/starlette/ConceptsTest.expected | 3 ++- 7 files changed, 14 insertions(+), 7 deletions(-) diff --git a/python/ql/test/library-tests/frameworks/aiofile/ConceptsTest.expected b/python/ql/test/library-tests/frameworks/aiofile/ConceptsTest.expected index 1822a89c5eb..8ec8033d086 100644 --- a/python/ql/test/library-tests/frameworks/aiofile/ConceptsTest.expected +++ b/python/ql/test/library-tests/frameworks/aiofile/ConceptsTest.expected @@ -1 +1,2 @@ -ERROR: Could not resolve module semmle.python.frameworks.FileSystemAccess (/home/am/CodeQL-home/codeql-repo-amammad/python/ql/lib/semmle/python/Frameworks.qll:25,16-57) +testFailures +failures diff --git a/python/ql/test/library-tests/frameworks/aiofiles/ConceptsTest.expected b/python/ql/test/library-tests/frameworks/aiofiles/ConceptsTest.expected index 1822a89c5eb..8ec8033d086 100644 --- a/python/ql/test/library-tests/frameworks/aiofiles/ConceptsTest.expected +++ b/python/ql/test/library-tests/frameworks/aiofiles/ConceptsTest.expected @@ -1 +1,2 @@ -ERROR: Could not resolve module semmle.python.frameworks.FileSystemAccess (/home/am/CodeQL-home/codeql-repo-amammad/python/ql/lib/semmle/python/Frameworks.qll:25,16-57) +testFailures +failures diff --git a/python/ql/test/library-tests/frameworks/anyio/ConceptsTest.expected b/python/ql/test/library-tests/frameworks/anyio/ConceptsTest.expected index 1822a89c5eb..8ec8033d086 100644 --- a/python/ql/test/library-tests/frameworks/anyio/ConceptsTest.expected +++ b/python/ql/test/library-tests/frameworks/anyio/ConceptsTest.expected @@ -1 +1,2 @@ -ERROR: Could not resolve module semmle.python.frameworks.FileSystemAccess (/home/am/CodeQL-home/codeql-repo-amammad/python/ql/lib/semmle/python/Frameworks.qll:25,16-57) +testFailures +failures diff --git a/python/ql/test/library-tests/frameworks/baize/ConceptsTest.expected b/python/ql/test/library-tests/frameworks/baize/ConceptsTest.expected index 1822a89c5eb..8ec8033d086 100644 --- a/python/ql/test/library-tests/frameworks/baize/ConceptsTest.expected +++ b/python/ql/test/library-tests/frameworks/baize/ConceptsTest.expected @@ -1 +1,2 @@ -ERROR: Could not resolve module semmle.python.frameworks.FileSystemAccess (/home/am/CodeQL-home/codeql-repo-amammad/python/ql/lib/semmle/python/Frameworks.qll:25,16-57) +testFailures +failures diff --git a/python/ql/test/library-tests/frameworks/cherrypy/ConceptsTest.expected b/python/ql/test/library-tests/frameworks/cherrypy/ConceptsTest.expected index 1822a89c5eb..8ec8033d086 100644 --- a/python/ql/test/library-tests/frameworks/cherrypy/ConceptsTest.expected +++ b/python/ql/test/library-tests/frameworks/cherrypy/ConceptsTest.expected @@ -1 +1,2 @@ -ERROR: Could not resolve module semmle.python.frameworks.FileSystemAccess (/home/am/CodeQL-home/codeql-repo-amammad/python/ql/lib/semmle/python/Frameworks.qll:25,16-57) +testFailures +failures diff --git a/python/ql/test/library-tests/frameworks/sanic/ConceptsTest.expected b/python/ql/test/library-tests/frameworks/sanic/ConceptsTest.expected index 1822a89c5eb..8ec8033d086 100644 --- a/python/ql/test/library-tests/frameworks/sanic/ConceptsTest.expected +++ b/python/ql/test/library-tests/frameworks/sanic/ConceptsTest.expected @@ -1 +1,2 @@ -ERROR: Could not resolve module semmle.python.frameworks.FileSystemAccess (/home/am/CodeQL-home/codeql-repo-amammad/python/ql/lib/semmle/python/Frameworks.qll:25,16-57) +testFailures +failures diff --git a/python/ql/test/library-tests/frameworks/starlette/ConceptsTest.expected b/python/ql/test/library-tests/frameworks/starlette/ConceptsTest.expected index 1822a89c5eb..8ec8033d086 100644 --- a/python/ql/test/library-tests/frameworks/starlette/ConceptsTest.expected +++ b/python/ql/test/library-tests/frameworks/starlette/ConceptsTest.expected @@ -1 +1,2 @@ -ERROR: Could not resolve module semmle.python.frameworks.FileSystemAccess (/home/am/CodeQL-home/codeql-repo-amammad/python/ql/lib/semmle/python/Frameworks.qll:25,16-57) +testFailures +failures From e349891cff16406af7abcfce0e8d6e90667fe7c3 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 15 Nov 2023 14:35:52 +0100 Subject: [PATCH 10/10] Python: Apply suggestions from code review --- .../ql/test/library-tests/frameworks/baize/FileSystemAccess.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/python/ql/test/library-tests/frameworks/baize/FileSystemAccess.py b/python/ql/test/library-tests/frameworks/baize/FileSystemAccess.py index d2808292acf..7e1f7e0f0be 100644 --- a/python/ql/test/library-tests/frameworks/baize/FileSystemAccess.py +++ b/python/ql/test/library-tests/frameworks/baize/FileSystemAccess.py @@ -1,4 +1,3 @@ from baize.asgi import FileResponse as baizeFileResponse -baizeFileResponse("file") # $ getAPathArgument="file" -FileSystemAccess \ No newline at end of file +baizeFileResponse("file") # $ getAPathArgument="file" \ No newline at end of file