Compare commits

..

27 Commits

Author SHA1 Message Date
Andrew Eisenberg
66c1629974 Merge pull request #7285 from github/post-release-prep-2.7.3-ddd4ccbb
Post-release preparation 2.7.3
2021-12-10 09:59:45 -08:00
yoff
d8857c7ce8 Merge pull request #7246 from tausbn/python/import-star-flow
Python: Support flow through `import *`
2021-12-10 16:34:32 +01:00
Taus
b871342e83 Python: A small further performance improvement
Unrolling the transitive closure had slightly better performance here.

Also, we exclude names of builtins, since those will be handled by a
separate case of `isDefinedLocally`.
2021-12-09 10:29:55 +00:00
Taus
8517eff0f7 Python: Fix bad performance
A few changes, all bundled together:

- We were getting a lot of magic applied to the predicates in the
  `ImportStar` module, and this was causing needless re-evaluation.
  To address this, the easiest solution was to simply cache the entire
  module.
- In order to separate this from the dataflow analysis and make it
  dependent only on control flow, `potentialImportStarBase` was changed
  to return a `ControlFlowNode`.
- `isDefinedLocally` was defined on control flow nodes, which meant we
  were duplicating a lot of tuples due to control flow splitting, to no
  actual benefit.

Finally, there was a really bad join in `isDefinedLocally` that was
fixed by separating out a helper predicate. This is a case where we
could use a three-way join, since the join between the `Scope`, the
`name` string and the `Name` is big no matter what.

If we join `scope_defines_name` with `n.getId()`, we'll get `Name`s
belonging to irrelevant scopes.

If we join `scope_defines_name` with the enclosing scope of the `Name`
`n`, then we'll get this also for `Name`s that don't share their `getId`
with the local variable defined in the scope.

If we join `n.getId()` with `n.getScope()...` then we'll get all
enclosing scopes for each `Name`.

The last of these is what we currently have. It's not terrible, but not
great either. (Though thankfully it's rare to have lots of enclosing
scopes.)
2021-12-08 22:53:45 +00:00
Taus
7cd9369d91 Python: Autoformat 2021-12-07 09:29:24 +00:00
Taus
33a9f86f54 Python: Change integer in trois.py 2021-12-07 08:54:07 +00:00
Taus
dd33f4f4d2 Python: Apply suggestions from code review
Co-authored-by: yoff <lerchedahl@gmail.com>
2021-12-07 09:48:53 +01:00
Taus
7f44cebed7 Python: Add missing hidden flow
The easiest way to implement this was to change the definition of
`module_export` to account for chains of `import *`. We reuse the
machinery from `ImportStar.qll` for this, naturally.
2021-12-02 17:11:56 +00:00
Taus
4138296ec6 Python: Add test for "hidden" import * flow
TL;DR: We were missing out on flow in the following situation:

`mod1.py`:
```python
foo = SOURCE
```

`mod2.py`:
```python
from mod1 import *
```

`test.py`:
```python
from mod2 import foo
SINK(foo)
```

This is because there's no node at which a read of `foo` takes place
within `test.py`, and so the added reads make no difference.

Unfortunately, this means the previous test was a bit too simplistic,
since it only looks for module variable reads and writes. Because of
this, we change the test to be a more traditional "all flow" style
(though restricted to `CfgNode`s).
2021-12-02 17:05:54 +00:00
github-actions[bot]
87b968f337 Post-release preparation 2.7.3 2021-12-02 00:46:55 +00:00
Andrew Eisenberg
ddd4ccbb4b Merge pull request #7274 from github/aeisenberg/add-version-policy
Add a version policy
2021-11-30 14:51:30 -08:00
Andrew Eisenberg
ff030534ff Add a version policy
Handles the post release process.
2021-11-30 14:47:48 -08:00
Dave Bartolomeo
b42295801b Merge pull request #7271 from github/release-prep/2.7.3
Release preparation for version 2.7.3
2021-11-30 17:29:46 -05:00
github-actions[bot]
337ce65fe5 Release preparation for version 2.7.3 2021-11-30 20:39:35 +00:00
Dave Bartolomeo
9f6c0991cf Catch up with recent change notes 2021-11-29 16:41:18 -05:00
Dave Bartolomeo
5ed9029143 Move change notes to correct directories 2021-11-29 16:31:11 -05:00
Dave Bartolomeo
75fb47c76f Ruby change notes 2021-11-29 16:17:19 -05:00
Dave Bartolomeo
cd8a10d0a5 Python change notes 2021-11-29 16:17:05 -05:00
Dave Bartolomeo
96deddf053 JavaScript change notes 2021-11-29 16:16:30 -05:00
Dave Bartolomeo
452685bb66 Fix change note path 2021-11-29 16:11:34 -05:00
Dave Bartolomeo
310ef79fbd C++ change notes 2021-11-29 16:10:33 -05:00
Dave Bartolomeo
d0dac03bad Manually bump versions 2021-11-29 14:21:08 -05:00
Dave Bartolomeo
2dfcd1dd9c Add groups property
Also removed versions from test packs
2021-11-29 14:15:53 -05:00
Taus
09a11f4166 Python: Update ImpliesDataflow test
Turns out that now we can resolve the convoluted imports. Hurray!
2021-11-26 14:47:25 +00:00
Taus
6c3aabe1df Python: Support flow through import *
Adds result for `ModuleVariableNode::getARead` corresponding to reads
that go through (chains of) `import *`.

This required a bit of a change to _which_ module variables we define.
Previously, we only included variables that were accessed elsewhere in
the same file, but now we must ensure to also include variables that may
be accessed through `import *`.
2021-11-26 13:49:08 +00:00
Taus
c3e495efe9 Python: Refactor built-ins and import * logic
Moves this from the API graphs implementation into separate files.
2021-11-26 13:49:08 +00:00
Taus
03b6ee3833 Python: Add import * test
This test shows off a few things:

- transitive chains of `import *`
- multiple modules exporting the same name (to test for cross-talk)
2021-11-26 13:49:08 +00:00
97 changed files with 483 additions and 158 deletions

View File

@@ -10,7 +10,14 @@
"javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml",
"misc/legacy-support/*/qlpack.yml",
"misc/suite-helpers/qlpack.yml",
"ruby/ql/consistency-queries/qlpack.yml",
"ruby/extractor-pack/codeql-extractor.yml"
]
}
"ruby/extractor-pack/codeql-extractor.yml",
"ruby/ql/consistency-queries/qlpack.yml"
],
"versionPolicies": {
"default": {
"requireChangeNotes": true,
"committedPrereleaseSuffix": "dev",
"committedVersion": "nextPatchRelease"
}
}
}

7
cpp/ql/lib/CHANGELOG.md Normal file
View File

@@ -0,0 +1,7 @@
## 0.0.4
### New Features
* The QL library `semmle.code.cpp.commons.Exclusions` now contains a predicate
`isFromSystemMacroDefinition` for identifying code that originates from a
macro outside the project being analyzed.

View File

@@ -0,0 +1,7 @@
## 0.0.4
### New Features
* The QL library `semmle.code.cpp.commons.Exclusions` now contains a predicate
`isFromSystemMacroDefinition` for identifying code that originates from a
macro outside the project being analyzed.

View File

@@ -0,0 +1,2 @@
---
lastReleaseVersion: 0.0.4

View File

@@ -1,7 +1,8 @@
name: codeql/cpp-all
version: 0.0.2
version: 0.0.5-dev
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp
library: true
dependencies:
codeql/cpp-upgrades: 0.0.2
codeql/cpp-upgrades: 0.0.3

5
cpp/ql/src/CHANGELOG.md Normal file
View File

@@ -0,0 +1,5 @@
## 0.0.4
### New Queries
* A new query `cpp/non-https-url` has been added for C/C++. The query flags uses of `http` URLs that might be better replaced with `https`.

View File

@@ -0,0 +1,5 @@
## 0.0.4
### New Queries
* A new query `cpp/non-https-url` has been added for C/C++. The query flags uses of `http` URLs that might be better replaced with `https`.

View File

@@ -0,0 +1,2 @@
---
lastReleaseVersion: 0.0.4

View File

@@ -1,5 +1,6 @@
name: codeql/cpp-queries
version: 0.0.2
version: 0.0.5-dev
groups: cpp
dependencies:
codeql/cpp-all: "*"
codeql/suite-helpers: "*"

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-tests
version: 0.0.2
groups: [cpp, test]
dependencies:
codeql/cpp-all: "*"
codeql/cpp-queries: "*"

View File

@@ -1,6 +1,6 @@
# This directory has its own qlpack for reasons detailed in commit 2550788598010fa2117274607c9d58f64f997f34
name: codeql/cpp-tests-cwe-190-tainted
version: 0.0.2
groups: [cpp, test]
dependencies:
codeql/cpp-all: "*"
codeql/cpp-queries: "*"

View File

@@ -0,0 +1 @@
## 0.0.4

View File

@@ -0,0 +1 @@
## 0.0.4

View File

@@ -0,0 +1,2 @@
---
lastReleaseVersion: 0.0.4

View File

@@ -1,4 +1,5 @@
name: codeql/cpp-upgrades
groups: cpp
upgrades: .
version: 0.0.2
version: 0.0.5-dev
library: true

View File

@@ -0,0 +1 @@
## 0.0.4

View File

@@ -0,0 +1 @@
## 0.0.4

View File

@@ -0,0 +1,2 @@
---
lastReleaseVersion: 0.0.4

View File

@@ -1,7 +1,8 @@
name: codeql/csharp-all
version: 0.0.2
version: 0.0.5-dev
groups: csharp
dbscheme: semmlecode.csharp.dbscheme
extractor: csharp
library: true
dependencies:
codeql/csharp-upgrades: 0.0.2
codeql/csharp-upgrades: 0.0.3

View File

@@ -0,0 +1 @@
## 0.0.4

View File

@@ -0,0 +1 @@
## 0.0.4

View File

@@ -0,0 +1,2 @@
---
lastReleaseVersion: 0.0.4

View File

@@ -1,5 +1,6 @@
name: codeql/csharp-queries
version: 0.0.2
version: 0.0.5-dev
groups: csharp
suites: codeql-suites
extractor: csharp
defaultSuiteFile: codeql-suites/csharp-code-scanning.qls

View File

@@ -1,5 +1,5 @@
name: codeql-csharp-tests
version: 0.0.2
groups: [csharp, test]
dependencies:
codeql/csharp-all: "*"
codeql/csharp-queries: "*"

View File

@@ -0,0 +1 @@
## 0.0.4

View File

@@ -0,0 +1 @@
## 0.0.4

View File

@@ -0,0 +1,2 @@
---
lastReleaseVersion: 0.0.4

View File

@@ -1,4 +1,5 @@
name: codeql/csharp-upgrades
groups: csharp
version: 0.0.5-dev
upgrades: .
version: 0.0.2
library: true

7
java/ql/lib/CHANGELOG.md Normal file
View File

@@ -0,0 +1,7 @@
## 0.0.4
### Bug Fixes
* `CharacterLiteral`'s `getCodePointValue` predicate now returns the correct value for UTF-16 surrogates.
* The `RangeAnalysis` module and the `java/constant-comparison` queries no longer raise false alerts regarding comparisons with Unicode surrogate character literals.
* The predicate `Method.overrides(Method)` was accidentally transitive. This has been fixed. This fix also affects `Method.overridesOrInstantiates(Method)` and `Method.getASourceOverriddenMethod()`.

View File

@@ -0,0 +1,7 @@
## 0.0.4
### Bug Fixes
* `CharacterLiteral`'s `getCodePointValue` predicate now returns the correct value for UTF-16 surrogates.
* The `RangeAnalysis` module and the `java/constant-comparison` queries no longer raise false alerts regarding comparisons with Unicode surrogate character literals.
* The predicate `Method.overrides(Method)` was accidentally transitive. This has been fixed. This fix also affects `Method.overridesOrInstantiates(Method)` and `Method.getASourceOverriddenMethod()`.

View File

@@ -0,0 +1,2 @@
---
lastReleaseVersion: 0.0.4

View File

@@ -1,7 +1,8 @@
name: codeql/java-all
version: 0.0.2
version: 0.0.5-dev
groups: java
dbscheme: config/semmlecode.dbscheme
extractor: java
library: true
dependencies:
codeql/java-upgrades: 0.0.2
codeql/java-upgrades: 0.0.3

1
java/ql/src/CHANGELOG.md Normal file
View File

@@ -0,0 +1 @@
## 0.0.4

View File

@@ -0,0 +1 @@
## 0.0.4

View File

@@ -0,0 +1,2 @@
---
lastReleaseVersion: 0.0.4

View File

@@ -1,5 +1,6 @@
name: codeql/java-queries
version: 0.0.2
version: 0.0.5-dev
groups: java
suites: codeql-suites
extractor: java
defaultSuiteFile: codeql-suites/java-code-scanning.qls

View File

@@ -1,5 +1,5 @@
name: codeql/java-tests
version: 0.0.2
groups: [java, test]
dependencies:
codeql/java-all: "*"
codeql/java-queries: "*"

View File

@@ -0,0 +1 @@
## 0.0.4

View File

@@ -0,0 +1 @@
## 0.0.4

View File

@@ -0,0 +1,2 @@
---
lastReleaseVersion: 0.0.4

View File

@@ -1,4 +1,5 @@
name: codeql/java-upgrades
groups: java
upgrades: .
library: true
version: 0.0.2
version: 0.0.5-dev

View File

@@ -13,7 +13,6 @@ import EndpointScoring
*
* This is a single string containing a space-separated list of tokens.
*/
pragma[inline]
private string getTokenFeature(DataFlow::Node endpoint, string featureName) {
// Features for endpoints that are contained within a function.
exists(DatabaseFeatures::Entity entity | entity = getRepresentativeEntityForEndpoint(endpoint) |
@@ -276,7 +275,6 @@ private string getASupportedFeatureName() {
* This predicate holds if the generic token-based feature named `featureName` has the value
* `featureValue` for the endpoint `endpoint`.
*/
pragma[inline]
predicate tokenFeatures(DataFlow::Node endpoint, string featureName, string featureValue) {
ModelScoring::endpoints(endpoint) and
(

View File

@@ -0,0 +1 @@
## 0.0.5

View File

@@ -0,0 +1 @@
## 0.0.5

View File

@@ -0,0 +1,2 @@
---
lastReleaseVersion: 0.0.5

View File

@@ -1,7 +1,8 @@
name: codeql/javascript-all
version: 0.0.3
version: 0.0.5
groups: javascript
dbscheme: semmlecode.javascript.dbscheme
extractor: javascript
library: true
dependencies:
codeql/javascript-upgrades: 0.0.3
codeql/javascript-upgrades: 0.0.4

View File

@@ -0,0 +1,7 @@
## 0.0.5
### New Queries
* The `js/sensitive-get-query` query has been added. It highlights GET requests that read sensitive information from the query string.
* The `js/insufficient-key-size` query has been added. It highlights the creation of cryptographic keys with a short key size.
* The `js/session-fixation` query has been added. It highlights servers that reuse a session after a user has logged in.

View File

@@ -0,0 +1,7 @@
## 0.0.5
### New Queries
* The `js/sensitive-get-query` query has been added. It highlights GET requests that read sensitive information from the query string.
* The `js/insufficient-key-size` query has been added. It highlights the creation of cryptographic keys with a short key size.
* The `js/session-fixation` query has been added. It highlights servers that reuse a session after a user has logged in.

View File

@@ -0,0 +1,2 @@
---
lastReleaseVersion: 0.0.5

View File

@@ -1,5 +1,6 @@
name: codeql/javascript-queries
version: 0.0.3
version: 0.0.5
groups: javascript
suites: codeql-suites
extractor: javascript
defaultSuiteFile: codeql-suites/javascript-code-scanning.qls

View File

@@ -1,5 +1,5 @@
name: codeql/javascript-tests
version: 0.0.3
groups: [javascript, test]
dependencies:
codeql/javascript-all: "*"
codeql/javascript-queries: "*"

View File

@@ -0,0 +1 @@
## 0.0.5

View File

@@ -0,0 +1 @@
## 0.0.5

View File

@@ -0,0 +1,2 @@
---
lastReleaseVersion: 0.0.5

View File

@@ -1,4 +1,5 @@
name: codeql/javascript-upgrades
groups: javascript
upgrades: .
library: true
version: 0.0.3
version: 0.0.5

View File

@@ -1,2 +1,3 @@
name: codeql/suite-helpers
version: 0.0.2
version: 0.0.3
groups: shared

View File

@@ -0,0 +1,10 @@
## 0.0.4
### Major Analysis Improvements
* Added modeling of `os.stat`, `os.lstat`, `os.statvfs`, `os.fstat`, and `os.fstatvfs`, which are new sinks for the _Uncontrolled data used in path expression_ (`py/path-injection`) query.
* Added modeling of the `posixpath`, `ntpath`, and `genericpath` modules for path operations (although these are not supposed to be used), resulting in new sinks for the _Uncontrolled data used in path expression_ (`py/path-injection`) query.
* Added modeling of `wsgiref.simple_server` applications, leading to new remote flow sources.
* Added modeling of `aiopg` for sinks executing SQL.
* Added modeling of HTTP requests and responses when using `flask_admin` (`Flask-Admin` PyPI package), which leads to additional remote flow sources.
* Added modeling of the PyPI package `toml`, which provides encoding/decoding of TOML documents, leading to new taint-tracking steps.

View File

@@ -0,0 +1,10 @@
## 0.0.4
### Major Analysis Improvements
* Added modeling of `os.stat`, `os.lstat`, `os.statvfs`, `os.fstat`, and `os.fstatvfs`, which are new sinks for the _Uncontrolled data used in path expression_ (`py/path-injection`) query.
* Added modeling of the `posixpath`, `ntpath`, and `genericpath` modules for path operations (although these are not supposed to be used), resulting in new sinks for the _Uncontrolled data used in path expression_ (`py/path-injection`) query.
* Added modeling of `wsgiref.simple_server` applications, leading to new remote flow sources.
* Added modeling of `aiopg` for sinks executing SQL.
* Added modeling of HTTP requests and responses when using `flask_admin` (`Flask-Admin` PyPI package), which leads to additional remote flow sources.
* Added modeling of the PyPI package `toml`, which provides encoding/decoding of TOML documents, leading to new taint-tracking steps.

View File

@@ -0,0 +1,2 @@
---
lastReleaseVersion: 0.0.4

View File

@@ -1,7 +1,8 @@
name: codeql/python-all
version: 0.0.2
version: 0.0.5-dev
groups: python
dbscheme: semmlecode.python.dbscheme
extractor: python
library: true
dependencies:
codeql/python-upgrades: 0.0.2
codeql/python-upgrades: 0.0.3

View File

@@ -358,134 +358,26 @@ module API {
)
}
/** Gets the name of a known built-in. */
private string getBuiltInName() {
// These lists were created by inspecting the `builtins` and `__builtin__` modules in
// Python 3 and 2 respectively, using the `dir` built-in.
// Built-in functions and exceptions shared between Python 2 and 3
result in [
"abs", "all", "any", "bin", "bool", "bytearray", "callable", "chr", "classmethod",
"compile", "complex", "delattr", "dict", "dir", "divmod", "enumerate", "eval", "filter",
"float", "format", "frozenset", "getattr", "globals", "hasattr", "hash", "help", "hex",
"id", "input", "int", "isinstance", "issubclass", "iter", "len", "list", "locals", "map",
"max", "memoryview", "min", "next", "object", "oct", "open", "ord", "pow", "print",
"property", "range", "repr", "reversed", "round", "set", "setattr", "slice", "sorted",
"staticmethod", "str", "sum", "super", "tuple", "type", "vars", "zip", "__import__",
// Exceptions
"ArithmeticError", "AssertionError", "AttributeError", "BaseException", "BufferError",
"BytesWarning", "DeprecationWarning", "EOFError", "EnvironmentError", "Exception",
"FloatingPointError", "FutureWarning", "GeneratorExit", "IOError", "ImportError",
"ImportWarning", "IndentationError", "IndexError", "KeyError", "KeyboardInterrupt",
"LookupError", "MemoryError", "NameError", "NotImplemented", "NotImplementedError",
"OSError", "OverflowError", "PendingDeprecationWarning", "ReferenceError", "RuntimeError",
"RuntimeWarning", "StandardError", "StopIteration", "SyntaxError", "SyntaxWarning",
"SystemError", "SystemExit", "TabError", "TypeError", "UnboundLocalError",
"UnicodeDecodeError", "UnicodeEncodeError", "UnicodeError", "UnicodeTranslateError",
"UnicodeWarning", "UserWarning", "ValueError", "Warning", "ZeroDivisionError",
// Added for compatibility
"exec"
]
or
// Built-in constants shared between Python 2 and 3
result in ["False", "True", "None", "NotImplemented", "Ellipsis", "__debug__"]
or
// Python 3 only
result in [
"ascii", "breakpoint", "bytes", "exec", "aiter", "anext",
// Exceptions
"BlockingIOError", "BrokenPipeError", "ChildProcessError", "ConnectionAbortedError",
"ConnectionError", "ConnectionRefusedError", "ConnectionResetError", "FileExistsError",
"FileNotFoundError", "InterruptedError", "IsADirectoryError", "ModuleNotFoundError",
"NotADirectoryError", "PermissionError", "ProcessLookupError", "RecursionError",
"ResourceWarning", "StopAsyncIteration", "TimeoutError"
]
or
// Python 2 only
result in [
"basestring", "cmp", "execfile", "file", "long", "raw_input", "reduce", "reload",
"unichr", "unicode", "xrange"
]
}
/**
* Gets a data flow node that is likely to refer to a built-in with the name `name`.
*
* Currently this is an over-approximation, and may not account for things like overwriting a
* built-in with a different value.
*/
private DataFlow::Node likely_builtin(string name) {
exists(Module m |
result.asCfgNode() =
any(NameNode n |
possible_builtin_accessed_in_module(n, name, m) and
not possible_builtin_defined_in_module(name, m)
)
)
}
/**
* Holds if a global variable called `name` (which is also the name of a built-in) is assigned
* a value in the module `m`.
*/
private predicate possible_builtin_defined_in_module(string name, Module m) {
global_name_defined_in_module(name, m) and
name = getBuiltInName()
}
/**
* Holds if `n` is an access of a global variable called `name` (which is also the name of a
* built-in) inside the module `m`.
*/
private predicate possible_builtin_accessed_in_module(NameNode n, string name, Module m) {
n.isGlobal() and
n.isLoad() and
name = n.getId() and
name = getBuiltInName() and
m = n.getEnclosingModule()
}
/**
* Holds if `n` is an access of a variable called `name` (which is _not_ the name of a
* built-in, and which is _not_ a global defined in the enclosing module) inside the scope `s`.
*/
private predicate name_possibly_defined_in_import_star(NameNode n, string name, Scope s) {
n.isLoad() and
name = n.getId() and
// Not already defined in an enclosing scope.
not exists(LocalVariable v |
v.getId() = name and v.getScope() = n.getScope().getEnclosingScope*()
) and
not name = getBuiltInName() and
s = n.getScope().getEnclosingScope*() and
exists(potential_import_star_base(s)) and
not global_name_defined_in_module(name, n.getEnclosingModule())
}
/** Holds if a global variable called `name` is assigned a value in the module `m`. */
private predicate global_name_defined_in_module(string name, Module m) {
exists(NameNode n |
not exists(LocalVariable v | n.defines(v)) and
n.isStore() and
name = n.getId() and
m = n.getEnclosingModule()
)
}
private import semmle.python.dataflow.new.internal.Builtins
private import semmle.python.dataflow.new.internal.ImportStar
/**
* Gets the API graph node for all modules imported with `from ... import *` inside the scope `s`.
*
* For example, given
*
* `from foo.bar import *`
* ```python
* from foo.bar import *
* ```
*
* this would be the API graph node with the path
*
* `moduleImport("foo").getMember("bar")`
*/
private TApiNode potential_import_star_base(Scope s) {
exists(DataFlow::Node ref |
ref.asCfgNode() = any(ImportStarNode n | n.getScope() = s).getModule() and
use(result, ref)
exists(DataFlow::Node n |
n.asCfgNode() = ImportStar::potentialImportStarBase(s) and
use(result, n)
)
}
@@ -529,14 +421,14 @@ module API {
or
// Built-ins, treated as members of the module `builtins`
base = MkModuleImport("builtins") and
lbl = Label::member(any(string name | ref = likely_builtin(name)))
lbl = Label::member(any(string name | ref = Builtins::likelyBuiltin(name)))
or
// Unknown variables that may belong to a module imported with `import *`
exists(Scope s |
base = potential_import_star_base(s) and
lbl =
Label::member(any(string name |
name_possibly_defined_in_import_star(ref.asCfgNode(), name, s)
ImportStar::namePossiblyDefinedInImportStar(ref.asCfgNode(), name, s)
))
)
}

View File

@@ -0,0 +1,93 @@
/** Provides predicates for reasoning about built-ins in Python. */
private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.internal.ImportStar
module Builtins {
/** Gets the name of a known built-in. */
string getBuiltinName() {
// These lists were created by inspecting the `builtins` and `__builtin__` modules in
// Python 3 and 2 respectively, using the `dir` built-in.
// Built-in functions and exceptions shared between Python 2 and 3
result in [
"abs", "all", "any", "bin", "bool", "bytearray", "callable", "chr", "classmethod",
"compile", "complex", "delattr", "dict", "dir", "divmod", "enumerate", "eval", "filter",
"float", "format", "frozenset", "getattr", "globals", "hasattr", "hash", "help", "hex",
"id", "input", "int", "isinstance", "issubclass", "iter", "len", "list", "locals", "map",
"max", "memoryview", "min", "next", "object", "oct", "open", "ord", "pow", "print",
"property", "range", "repr", "reversed", "round", "set", "setattr", "slice", "sorted",
"staticmethod", "str", "sum", "super", "tuple", "type", "vars", "zip", "__import__",
// Exceptions
"ArithmeticError", "AssertionError", "AttributeError", "BaseException", "BufferError",
"BytesWarning", "DeprecationWarning", "EOFError", "EnvironmentError", "Exception",
"FloatingPointError", "FutureWarning", "GeneratorExit", "IOError", "ImportError",
"ImportWarning", "IndentationError", "IndexError", "KeyError", "KeyboardInterrupt",
"LookupError", "MemoryError", "NameError", "NotImplemented", "NotImplementedError",
"OSError", "OverflowError", "PendingDeprecationWarning", "ReferenceError", "RuntimeError",
"RuntimeWarning", "StandardError", "StopIteration", "SyntaxError", "SyntaxWarning",
"SystemError", "SystemExit", "TabError", "TypeError", "UnboundLocalError",
"UnicodeDecodeError", "UnicodeEncodeError", "UnicodeError", "UnicodeTranslateError",
"UnicodeWarning", "UserWarning", "ValueError", "Warning", "ZeroDivisionError",
// Added for compatibility
"exec"
]
or
// Built-in constants shared between Python 2 and 3
result in ["False", "True", "None", "NotImplemented", "Ellipsis", "__debug__"]
or
// Python 3 only
result in [
"ascii", "breakpoint", "bytes", "exec",
// Exceptions
"BlockingIOError", "BrokenPipeError", "ChildProcessError", "ConnectionAbortedError",
"ConnectionError", "ConnectionRefusedError", "ConnectionResetError", "FileExistsError",
"FileNotFoundError", "InterruptedError", "IsADirectoryError", "ModuleNotFoundError",
"NotADirectoryError", "PermissionError", "ProcessLookupError", "RecursionError",
"ResourceWarning", "StopAsyncIteration", "TimeoutError"
]
or
// Python 2 only
result in [
"basestring", "cmp", "execfile", "file", "long", "raw_input", "reduce", "reload", "unichr",
"unicode", "xrange"
]
}
/**
* Gets a data flow node that is likely to refer to a built-in with the name `name`.
*
* Currently this is an over-approximation, and may not account for things like overwriting a
* built-in with a different value.
*/
DataFlow::Node likelyBuiltin(string name) {
exists(Module m |
result.asCfgNode() =
any(NameNode n |
possible_builtin_accessed_in_module(n, name, m) and
not possible_builtin_defined_in_module(name, m)
)
)
}
/**
* Holds if a global variable called `name` (which is also the name of a built-in) is assigned
* a value in the module `m`.
*/
private predicate possible_builtin_defined_in_module(string name, Module m) {
ImportStar::globalNameDefinedInModule(name, m) and
name = getBuiltinName()
}
/**
* Holds if `n` is an access of a global variable called `name` (which is also the name of a
* built-in) inside the module `m`.
*/
private predicate possible_builtin_accessed_in_module(NameNode n, string name, Module m) {
n.isGlobal() and
n.isLoad() and
name = n.getId() and
name = getBuiltinName() and
m = n.getEnclosingModule()
}
}

View File

@@ -2,6 +2,7 @@ private import python
private import DataFlowPublic
import semmle.python.SpecialMethods
private import semmle.python.essa.SsaCompute
private import semmle.python.dataflow.new.internal.ImportStar
/** Gets the callable in which this node occurs. */
DataFlowCallable nodeGetEnclosingCallable(Node n) { result = n.getEnclosingCallable() }
@@ -948,7 +949,7 @@ predicate jumpStep(Node nodeFrom, Node nodeTo) {
private predicate module_export(Module m, string name, CfgNode defn) {
exists(EssaVariable v |
v.getName() = name and
v.getAUse() = m.getANormalExit()
v.getAUse() = ImportStar::getStarImported*(m).getANormalExit()
|
defn.getNode() = v.getDefinition().(AssignmentDefinition).getValue()
or

View File

@@ -8,6 +8,7 @@ import semmle.python.dataflow.new.TypeTracker
import Attributes
import LocalSources
private import semmle.python.essa.SsaCompute
private import semmle.python.dataflow.new.internal.ImportStar
/**
* IPA type for data flow nodes.
@@ -30,7 +31,15 @@ newtype TNode =
/** A synthetic node representing the value of an object after a state change. */
TSyntheticPostUpdateNode(NeedsSyntheticPostUpdateNode pre) or
/** A node representing a global (module-level) variable in a specific module. */
TModuleVariableNode(Module m, GlobalVariable v) { v.getScope() = m and v.escapes() } or
TModuleVariableNode(Module m, GlobalVariable v) {
v.getScope() = m and
(
v.escapes()
or
isAccessedThroughImportStar(m) and
ImportStar::globalNameDefinedInModule(v.getId(), m)
)
} or
/**
* A node representing the overflow positional arguments to a call.
* That is, `call` contains more positional arguments than there are
@@ -346,6 +355,8 @@ class ModuleVariableNode extends Node, TModuleVariableNode {
result.asCfgNode() = var.getALoad().getAFlowNode() and
// Ignore reads that happen when the module is imported. These are only executed once.
not result.getScope() = mod
or
this = import_star_read(result)
}
/** Gets an `EssaNode` that corresponds to an assignment of this global variable. */
@@ -358,6 +369,13 @@ class ModuleVariableNode extends Node, TModuleVariableNode {
override Location getLocation() { result = mod.getLocation() }
}
private predicate isAccessedThroughImportStar(Module m) { m = ImportStar::getStarImported(_) }
private ModuleVariableNode import_star_read(Node n) {
ImportStar::importStarResolvesTo(n.asCfgNode(), result.getModule()) and
n.asCfgNode().(NameNode).getId() = result.getVariable().getId()
}
/**
* The node holding the extra positional arguments to a call. This node is passed as a tuple
* to the starred parameter of the callable.

View File

@@ -0,0 +1,95 @@
/** Provides predicates for reasoning about uses of `import *` in Python. */
private import python
private import semmle.python.dataflow.new.internal.Builtins
cached
module ImportStar {
/**
* Holds if `n` is an access of a variable called `name` (which is _not_ the name of a
* built-in, and which is _not_ a global defined in the enclosing module) inside the scope `s`.
*/
cached
predicate namePossiblyDefinedInImportStar(NameNode n, string name, Scope s) {
n.isLoad() and
name = n.getId() and
s = n.getScope().getEnclosingScope*() and
exists(potentialImportStarBase(s)) and
// Not already defined in an enclosing scope.
not isDefinedLocally(n.getNode())
}
/** Holds if `n` refers to a variable that is defined in the module in which it occurs. */
cached
private predicate isDefinedLocally(Name n) {
// Defined in an enclosing scope
enclosing_scope_defines_name(n.getScope(), n.getId())
or
// Defined as a built-in
n.getId() = Builtins::getBuiltinName()
or
// Defined as a global in this module
globalNameDefinedInModule(n.getId(), n.getEnclosingModule())
or
// A non-built-in that still has file-specific meaning
n.getId() in ["__name__", "__package__"]
}
pragma[nomagic]
private predicate enclosing_scope_defines_name(Scope s, string name) {
exists(LocalVariable v |
v.getId() = name and v.getScope() = s and not name = Builtins::getBuiltinName()
)
or
enclosing_scope_defines_name(s.getEnclosingScope(), name)
}
/** Holds if a global variable called `name` is assigned a value in the module `m`. */
cached
predicate globalNameDefinedInModule(string name, Module m) {
exists(NameNode n |
not exists(LocalVariable v | n.defines(v)) and
n.isStore() and
name = n.getId() and
m = n.getEnclosingModule()
)
}
/**
* Holds if `n` may refer to a global variable of the same name in the module `m`, accessible
* from the scope of `n` by a chain of `import *` imports.
*/
cached
predicate importStarResolvesTo(NameNode n, Module m) {
m = getStarImported+(n.getEnclosingModule()) and
globalNameDefinedInModule(n.getId(), m) and
not isDefinedLocally(n.getNode())
}
/**
* Gets a module that is imported from `m` via `import *`.
*/
cached
Module getStarImported(Module m) {
exists(ImportStar i |
i.getScope() = m and result = i.getModule().pointsTo().(ModuleValue).getScope()
)
}
/**
* Gets the data-flow node for a module imported with `from ... import *` inside the scope `s`.
*
* For example, given
*
* ```python
* from foo.bar import *
* from quux import *
* ```
*
* this would return the data-flow nodes corresponding to `foo.bar` and `quux`.
*/
cached
ControlFlowNode potentialImportStarBase(Scope s) {
result = any(ImportStarNode n | n.getScope() = s).getModule()
}
}

View File

@@ -0,0 +1,5 @@
## 0.0.4
### Query Metadata Changes
* Fixed the query ids of two queries that are meant for manual exploration: `python/count-untrusted-data-external-api` and `python/untrusted-data-to-external-api` have been changed to `py/count-untrusted-data-external-api` and `py/untrusted-data-to-external-api`.

View File

@@ -0,0 +1,5 @@
## 0.0.4
### Query Metadata Changes
* Fixed the query ids of two queries that are meant for manual exploration: `python/count-untrusted-data-external-api` and `python/untrusted-data-to-external-api` have been changed to `py/count-untrusted-data-external-api` and `py/untrusted-data-to-external-api`.

View File

@@ -0,0 +1,2 @@
---
lastReleaseVersion: 0.0.4

View File

@@ -1,5 +1,6 @@
name: codeql/python-queries
version: 0.0.2
version: 0.0.5-dev
groups: python
dependencies:
codeql/python-all: "*"
codeql/suite-helpers: "*"

View File

@@ -1 +1 @@
known_attr = [1000]
known_attr = [1000] #$ writes=known_attr

View File

@@ -0,0 +1,2 @@
from trois import *
print(foo)

View File

@@ -0,0 +1,15 @@
| test3.py:1:17:1:19 | ControlFlowNode for ImportMember | test3.py:2:7:2:9 | ControlFlowNode for foo |
| three.py:1:1:1:3 | ControlFlowNode for foo | test1.py:2:7:2:9 | ControlFlowNode for foo |
| three.py:1:1:1:3 | ControlFlowNode for foo | test3.py:1:17:1:19 | ControlFlowNode for ImportMember |
| three.py:1:1:1:3 | ControlFlowNode for foo | test3.py:2:7:2:9 | ControlFlowNode for foo |
| three.py:1:1:1:3 | ControlFlowNode for foo | two.py:2:7:2:9 | ControlFlowNode for foo |
| three.py:1:7:1:7 | ControlFlowNode for IntegerLiteral | test1.py:2:7:2:9 | ControlFlowNode for foo |
| three.py:1:7:1:7 | ControlFlowNode for IntegerLiteral | test3.py:1:17:1:19 | ControlFlowNode for ImportMember |
| three.py:1:7:1:7 | ControlFlowNode for IntegerLiteral | test3.py:2:7:2:9 | ControlFlowNode for foo |
| three.py:1:7:1:7 | ControlFlowNode for IntegerLiteral | two.py:2:7:2:9 | ControlFlowNode for foo |
| trois.py:1:1:1:3 | ControlFlowNode for foo | deux.py:2:7:2:9 | ControlFlowNode for foo |
| trois.py:1:1:1:3 | ControlFlowNode for foo | test2.py:2:7:2:9 | ControlFlowNode for foo |
| trois.py:1:7:1:7 | ControlFlowNode for IntegerLiteral | deux.py:2:7:2:9 | ControlFlowNode for foo |
| trois.py:1:7:1:7 | ControlFlowNode for IntegerLiteral | test2.py:2:7:2:9 | ControlFlowNode for foo |
| two.py:2:7:2:9 | ControlFlowNode for foo | test3.py:1:17:1:19 | ControlFlowNode for ImportMember |
| two.py:2:7:2:9 | ControlFlowNode for foo | test3.py:2:7:2:9 | ControlFlowNode for foo |

View File

@@ -0,0 +1,19 @@
import semmle.python.dataflow.new.DataFlow
/**
* A configuration to find all flows.
* To be used on tiny programs.
*/
class AllFlowsConfig extends DataFlow::Configuration {
AllFlowsConfig() { this = "AllFlowsConfig" }
override predicate isSource(DataFlow::Node node) { any() }
override predicate isSink(DataFlow::Node node) { any() }
}
from DataFlow::CfgNode source, DataFlow::CfgNode sink
where
source != sink and
exists(AllFlowsConfig cfg | cfg.hasFlow(source, sink))
select source, sink

View File

@@ -0,0 +1 @@
from two import *

View File

@@ -0,0 +1,2 @@
from one import *
print(foo)

View File

@@ -0,0 +1,2 @@
from un import *
print(foo)

View File

@@ -0,0 +1,2 @@
from one import foo
print(foo)

View File

@@ -0,0 +1 @@
foo = 5

View File

@@ -0,0 +1 @@
foo = 6

View File

@@ -0,0 +1,2 @@
from three import *
print(foo)

View File

@@ -0,0 +1 @@
from deux import *

View File

@@ -15,4 +15,3 @@
| code/r_regressions.py:46:1:46:14 | ControlFlowNode for FunctionExpr | code/r_regressions.py:52:9:52:12 | ControlFlowNode for fail |
| code/t_type.py:3:1:3:16 | ControlFlowNode for ClassExpr | code/t_type.py:6:1:6:9 | ControlFlowNode for type() |
| code/t_type.py:3:1:3:16 | ControlFlowNode for ClassExpr | code/t_type.py:13:5:13:13 | ControlFlowNode for type() |
| code/test_package/module2.py:5:5:5:6 | ControlFlowNode for Dict | code/j_convoluted_imports.py:25:1:25:1 | ControlFlowNode for r |

View File

@@ -1,5 +1,5 @@
name: codeql/python-tests
version: 0.0.2
groups: [python, test]
dependencies:
codeql/python-all: "*"
codeql/python-queries: "*"

View File

@@ -0,0 +1 @@
## 0.0.4

View File

@@ -0,0 +1 @@
## 0.0.4

View File

@@ -0,0 +1,2 @@
---
lastReleaseVersion: 0.0.4

View File

@@ -1,4 +1,5 @@
name: codeql/python-upgrades
groups: python
upgrades: .
library: true
version: 0.0.2
version: 0.0.5-dev

1
ruby/ql/lib/CHANGELOG.md Normal file
View File

@@ -0,0 +1 @@
## 0.0.4

View File

@@ -0,0 +1 @@
## 0.0.4

View File

@@ -0,0 +1,2 @@
---
lastReleaseVersion: 0.0.4

View File

@@ -1,5 +1,6 @@
name: codeql/ruby-all
version: 0.0.2
version: 0.0.5-dev
groups: ruby
extractor: ruby
dbscheme: ruby.dbscheme
upgrades: upgrades

10
ruby/ql/src/CHANGELOG.md Normal file
View File

@@ -0,0 +1,10 @@
## 0.0.4
### New Queries
* A new query (`rb/request-forgery`) has been added. The query finds HTTP requests made with user-controlled URLs.
* A new query (`rb/csrf-protection-disabled`) has been added. The query finds cases where cross-site forgery protection is explictly disabled.
### Query Metadata Changes
* The precision of "Hard-coded credentials" (`rb/hardcoded-credentials`) has been decreased from "high" to "medium". This query will no longer be run and displayed by default on Code Scanning and LGTM.

View File

@@ -0,0 +1,10 @@
## 0.0.4
### New Queries
* A new query (`rb/request-forgery`) has been added. The query finds HTTP requests made with user-controlled URLs.
* A new query (`rb/csrf-protection-disabled`) has been added. The query finds cases where cross-site forgery protection is explictly disabled.
### Query Metadata Changes
* The precision of "Hard-coded credentials" (`rb/hardcoded-credentials`) has been decreased from "high" to "medium". This query will no longer be run and displayed by default on Code Scanning and LGTM.

View File

@@ -0,0 +1,2 @@
---
lastReleaseVersion: 0.0.4

View File

@@ -1,5 +1,6 @@
name: codeql/ruby-queries
version: 0.0.2
version: 0.0.5-dev
groups: ruby
suites: codeql-suites
defaultSuiteFile: codeql-suites/ruby-code-scanning.qls
dependencies:

View File

@@ -1,5 +1,5 @@
name: codeql/ruby-tests
version: 0.0.2
groups: [ruby, test]
dependencies:
codeql/ruby-queries: ^0.0.2
codeql/ruby-examples: ^0.0.2