mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge branch 'main' into systemwebhttprequest-test-stubs
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
## 0.4.18
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.4.17
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
3
actions/ql/lib/change-notes/released/0.4.18.md
Normal file
3
actions/ql/lib/change-notes/released/0.4.18.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.4.18
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.4.17
|
||||
lastReleaseVersion: 0.4.18
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/actions-all
|
||||
version: 0.4.18-dev
|
||||
version: 0.4.19-dev
|
||||
library: true
|
||||
warnOnImplicitThis: true
|
||||
dependencies:
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 0.6.10
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.6.9
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
3
actions/ql/src/change-notes/released/0.6.10.md
Normal file
3
actions/ql/src/change-notes/released/0.6.10.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.6.10
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.6.9
|
||||
lastReleaseVersion: 0.6.10
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/actions-queries
|
||||
version: 0.6.10-dev
|
||||
version: 0.6.11-dev
|
||||
library: false
|
||||
warnOnImplicitThis: true
|
||||
groups: [actions, queries]
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 5.6.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 5.6.0
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
3
cpp/ql/lib/change-notes/released/5.6.1.md
Normal file
3
cpp/ql/lib/change-notes/released/5.6.1.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 5.6.1
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 5.6.0
|
||||
lastReleaseVersion: 5.6.1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 5.6.1-dev
|
||||
version: 5.6.2-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 1.5.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.5.0
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
3
cpp/ql/src/change-notes/released/1.5.1.md
Normal file
3
cpp/ql/src/change-notes/released/1.5.1.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 1.5.1
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.5.0
|
||||
lastReleaseVersion: 1.5.1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 1.5.1-dev
|
||||
version: 1.5.2-dev
|
||||
groups:
|
||||
- cpp
|
||||
- queries
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
| permissive.cpp:6:5:6:7 | str |
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
| permissive.cpp:6:3:6:3 | call to f | permissive.cpp:2:13:2:13 | f |
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
// semmle-extractor-options: --edg --permissive
|
||||
static void f(char* foo) {}
|
||||
|
||||
static void g(void) {
|
||||
const char* str = "foo";
|
||||
f(str);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 1.7.49
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.7.48
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
## 1.7.49
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.7.48
|
||||
lastReleaseVersion: 1.7.49
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-solorigate-all
|
||||
version: 1.7.49-dev
|
||||
version: 1.7.50-dev
|
||||
groups:
|
||||
- csharp
|
||||
- solorigate
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 1.7.49
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.7.48
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
## 1.7.49
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.7.48
|
||||
lastReleaseVersion: 1.7.49
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-solorigate-queries
|
||||
version: 1.7.49-dev
|
||||
version: 1.7.50-dev
|
||||
groups:
|
||||
- csharp
|
||||
- solorigate
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 5.2.5
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 5.2.4
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
3
csharp/ql/lib/change-notes/released/5.2.5.md
Normal file
3
csharp/ql/lib/change-notes/released/5.2.5.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 5.2.5
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 5.2.4
|
||||
lastReleaseVersion: 5.2.5
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-all
|
||||
version: 5.2.5-dev
|
||||
version: 5.2.6-dev
|
||||
groups: csharp
|
||||
dbscheme: semmlecode.csharp.dbscheme
|
||||
extractor: csharp
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
## 1.4.1
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The modeling of null guards based on complex pattern expressions has been improved, which in turn improves the query `cs/dereferenced-value-may-be-null` by removing false positives.
|
||||
* The query `cs/xmldoc/missing-summary` has been removed from the `code-quality` suite, to align with other languages.
|
||||
|
||||
## 1.4.0
|
||||
|
||||
### Deprecated Queries
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Remove the query `cs/xmldoc/missing-summary` from the `code-quality` suite (align with other languages).
|
||||
@@ -1,4 +1,6 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
## 1.4.1
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The modeling of null guards based on complex pattern expressions has been improved, which in turn improves the query `cs/dereferenced-value-may-be-null` by removing false positives.
|
||||
* The query `cs/xmldoc/missing-summary` has been removed from the `code-quality` suite, to align with other languages.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.4.0
|
||||
lastReleaseVersion: 1.4.1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-queries
|
||||
version: 1.4.1-dev
|
||||
version: 1.4.2-dev
|
||||
groups:
|
||||
- csharp
|
||||
- queries
|
||||
|
||||
131
docs/codeql/codeql-language-guides/basic-query-for-rust-code.rst
Normal file
131
docs/codeql/codeql-language-guides/basic-query-for-rust-code.rst
Normal file
@@ -0,0 +1,131 @@
|
||||
.. _basic-query-for-rust-code:
|
||||
|
||||
Basic query for Rust code
|
||||
==========================
|
||||
|
||||
Learn to write and run a simple CodeQL query using Visual Studio Code with the CodeQL extension.
|
||||
|
||||
.. include:: ../reusables/vs-code-basic-instructions/setup-to-run-queries.rst
|
||||
|
||||
About the query
|
||||
---------------
|
||||
|
||||
The query we're going to run performs a basic search of the code for ``if`` expressions that are redundant, in the sense that they have an empty ``then`` branch. For example, code such as:
|
||||
|
||||
.. code-block:: rust
|
||||
|
||||
if error {
|
||||
// we should handle the error
|
||||
}
|
||||
|
||||
.. include:: ../reusables/vs-code-basic-instructions/find-database.rst
|
||||
|
||||
Running a quick query
|
||||
---------------------
|
||||
|
||||
.. include:: ../reusables/vs-code-basic-instructions/run-quick-query-1.rst
|
||||
|
||||
#. In the quick query tab, delete the content and paste in the following query.
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
import rust
|
||||
|
||||
from IfExpr ifExpr
|
||||
where ifExpr.getThen().(BlockExpr).getStmtList().getNumberOfStmtOrExpr() = 0
|
||||
select ifExpr, "This 'if' expression is redundant."
|
||||
|
||||
.. include:: ../reusables/vs-code-basic-instructions/run-quick-query-2.rst
|
||||
|
||||
.. image:: ../images/codeql-for-visual-studio-code/basic-rust-query-results-1.png
|
||||
:align: center
|
||||
|
||||
If any matching code is found, click a link in the ``ifExpr`` column to open the file and highlight the matching ``if`` expression.
|
||||
|
||||
.. image:: ../images/codeql-for-visual-studio-code/basic-rust-query-results-2.png
|
||||
:align: center
|
||||
|
||||
.. include:: ../reusables/vs-code-basic-instructions/note-store-quick-query.rst
|
||||
|
||||
About the query structure
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
After the initial ``import`` statement, this simple query comprises three parts that serve similar purposes to the FROM, WHERE, and SELECT parts of an SQL query.
|
||||
|
||||
+----------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+
|
||||
| Query part | Purpose | Details |
|
||||
+==================================================================================+===================================================================================================================+======================================================================================================+
|
||||
| ``import rust`` | Imports the standard CodeQL AST libraries for Rust. | Every query begins with one or more ``import`` statements. |
|
||||
+----------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+
|
||||
| ``from IfExpr ifExpr`` | Defines the variables for the query. | We use: an ``IfExpr`` variable for ``if`` expressions. |
|
||||
| | Declarations are of the form: | |
|
||||
| | ``<type> <variable name>`` | |
|
||||
+----------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+
|
||||
| ``where ifExpr.getThen().(BlockExpr).getStmtList().getNumberOfStmtOrExpr() = 0`` | Defines a condition on the variables. | ``ifExpr.getThen()``: gets the ``then`` branch of the ``if`` expression. |
|
||||
| | | ``.(BlockExpr)``: requires that the ``then`` branch is a block expression (``{ }``). |
|
||||
| | | ``.getStmtList()``: gets the list of things in the block. |
|
||||
| | | ``.getNumberOfStmtOrExpr() = 0``: requires that there are no statements or expressions in the block. |
|
||||
+----------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+
|
||||
| ``select ifExpr, "This 'if' expression is redundant."`` | Defines what to report for each match. | Reports the resulting ``if`` expression with a string that explains the problem. |
|
||||
| | | |
|
||||
| | ``select`` statements for queries that are used to find instances of poor coding practice are always in the form: | |
|
||||
| | ``select <program element>, "<alert message>"`` | |
|
||||
+----------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+
|
||||
|
||||
Extend the query
|
||||
----------------
|
||||
|
||||
Query writing is an inherently iterative process. You write a simple query and then, when you run it, you discover examples that you had not previously considered, or opportunities for improvement.
|
||||
|
||||
Remove false positive results
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Browsing the results of our basic query shows that it could be improved. Among the results you are likely to find examples of ``if`` expressions with an ``else`` branch, where an empty ``then`` branch does serve a purpose. For example:
|
||||
|
||||
.. code-block:: rust
|
||||
|
||||
if (option == "-verbose") {
|
||||
// nothing to do - handled earlier
|
||||
} else {
|
||||
handleError("unrecognized option")
|
||||
}
|
||||
|
||||
In this case, identifying the ``if`` expression with the empty ``then`` branch as redundant is a false positive. One solution to this is to modify the query to select ``if`` expressions where both the ``then`` and ``else`` branches are missing.
|
||||
|
||||
To exclude ``if`` expressions that have an ``else`` branch:
|
||||
|
||||
#. Add the following to the where clause:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
and not exists(ifExpr.getElse())
|
||||
|
||||
The ``where`` clause is now:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
where
|
||||
ifExpr.getThen().(BlockExpr).getStmtList().getNumberOfStmtOrExpr() = 0 and
|
||||
not exists(ifExpr.getElse())
|
||||
|
||||
#. Re-run the query.
|
||||
|
||||
There are now fewer results because ``if`` expressions with an ``else`` branch are no longer included.
|
||||
|
||||
Further reading
|
||||
---------------
|
||||
|
||||
.. include:: ../reusables/rust-further-reading.rst
|
||||
.. include:: ../reusables/codeql-ref-tools-further-reading.rst
|
||||
|
||||
.. Article-specific substitutions for the reusables used in docs/codeql/reusables/vs-code-basic-instructions
|
||||
|
||||
.. |language-text| replace:: Rust
|
||||
|
||||
.. |language-code| replace:: ``rust``
|
||||
|
||||
.. |example-url| replace:: https://github.com/rust-lang/rustlings
|
||||
|
||||
.. |image-quick-query| image:: ../images/codeql-for-visual-studio-code/quick-query-tab-rust.png
|
||||
|
||||
.. |result-col-1| replace:: The first column corresponds to the expression ``ifExpr`` and is linked to the location in the source code of the project where ``ifExpr`` occurs.
|
||||
@@ -9,8 +9,12 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
basic-query-for-rust-code
|
||||
codeql-library-for-rust
|
||||
analyzing-data-flow-in-rust
|
||||
|
||||
- :doc:`Basic query for Rust code <basic-query-for-rust-code>`: Learn to write and run a simple CodeQL query.
|
||||
|
||||
- :doc:`CodeQL library for Rust <codeql-library-for-rust>`: When analyzing Rust code, you can make use of the large collection of classes in the CodeQL library for Rust.
|
||||
|
||||
- :doc:`Analyzing data flow in Rust <analyzing-data-flow-in-rust>`: You can use CodeQL to track the flow of data through a Rust program to places where the data is used.
|
||||
|
||||
@@ -88,7 +88,7 @@ JavaScript/TypeScript
|
||||
* Data flow is now tracked through the :code:`Promise.try` and :code:`Array.prototype.with` functions.
|
||||
* Query :code:`js/index-out-of-bounds` no longer produces a false-positive when a strictly-less-than check overrides a previous less-than-or-equal test.
|
||||
* The query :code:`js/remote-property-injection` now detects property injection vulnerabilities through object enumeration patterns such as :code:`Object.keys()`.
|
||||
* The query "Permissive CORS configuration" (:code:`js/cors-permissive-configuration`) has been promoted from experimental and is now part of the default security suite.
|
||||
* The query "Permissive CORS configuration" (:code:`js/cors-permissive-configuration`) has been promoted from experimental and is now part of the default security suite. Thank you to @maikypedia who `submitted the original experimental query <https://github.com/github/codeql/pull/14342>`__!
|
||||
|
||||
Python
|
||||
""""""
|
||||
@@ -126,7 +126,7 @@ Golang
|
||||
""""""
|
||||
|
||||
* The second argument of the :code:`CreateTemp` function, from the :code:`os` package, is no longer a path-injection sink due to proper sanitization by Go.
|
||||
* The query "Uncontrolled data used in path expression" (:code:`go/path-injection`) now detects sanitizing a path by adding :code:`os.PathSeparator` or :code:`\ ` to the beginning.
|
||||
* The query "Uncontrolled data used in path expression" (:code:`go/path-injection`) now detects sanitizing a path by adding :code:`os.PathSeparator` or ``\`` to the beginning.
|
||||
|
||||
Java/Kotlin
|
||||
"""""""""""
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 9.1 KiB |
@@ -20,7 +20,7 @@
|
||||
- ``python``
|
||||
* - Ruby
|
||||
- ``ruby``
|
||||
- Rust
|
||||
* - Rust
|
||||
- ``rust``
|
||||
* - Swift
|
||||
- ``swift``
|
||||
|
||||
@@ -324,12 +324,15 @@ All support is experimental.
|
||||
Name, Category
|
||||
`actix-web <https://crates.io/crates/actix-web>`__, Web framework
|
||||
alloc, Standard library
|
||||
`async-std <https://crates.io/crates/async-std>`__, Asynchronous programming library
|
||||
`biscotti <https://crates.io/crates/biscotti>`__, Cookie management
|
||||
`clap <http://crates.io/crates/clap>`__, Utility library
|
||||
`cookie <https://crates.io/crates/cookie>`__, Cookie management
|
||||
core, Standard library
|
||||
`digest <https://crates.io/crates/digest>`__, Cryptography library
|
||||
`futures-executor <https://crates.io/crates/futures-executor>`__, Utility library
|
||||
`futures <https://crates.io/crates/futures>`__, Asynchronous programming library
|
||||
`futures-rustls <https://crates.io/crates/futures-rustls>`__, Network communicator
|
||||
`hyper <https://crates.io/crates/hyper>`__, HTTP library
|
||||
`hyper-util <https://crates.io/crates/hyper-util>`__, HTTP library
|
||||
`libc <https://crates.io/crates/libc>`__, Utility library
|
||||
`log <https://crates.io/crates/log>`__, Logging library
|
||||
`md5 <https://crates.io/crates/md5>`__, Utility library
|
||||
@@ -345,12 +348,14 @@ All support is experimental.
|
||||
`rusqlite <https://crates.io/crates/rusqlite>`__, Database
|
||||
std, Standard library
|
||||
`rust-crypto <https://crates.io/crates/rust-crypto>`__, Cryptography library
|
||||
`rustls <https://crates.io/crates/rustls>`__, Network communicator
|
||||
`serde <https://crates.io/crates/serde>`__, Serialization
|
||||
`smallvec <https://crates.io/crates/smallvec>`__, Utility library
|
||||
`sqlx <https://crates.io/crates/sqlx>`__, Database
|
||||
`tokio <https://crates.io/crates/tokio>`__, Asynchronous IO
|
||||
`tokio-postgres <https://crates.io/crates/tokio-postgres>`__, Database
|
||||
`url <https://crates.io/crates/url>`__, Utility library
|
||||
`warp <https://crates.io/crates/warp>`__, Web framework
|
||||
|
||||
Swift built-in support
|
||||
================================
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 1.0.32
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.0.31
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
## 1.0.32
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.0.31
|
||||
lastReleaseVersion: 1.0.32
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql-go-consistency-queries
|
||||
version: 1.0.32-dev
|
||||
version: 1.0.33-dev
|
||||
groups:
|
||||
- go
|
||||
- queries
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 4.3.5
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 4.3.4
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
4
go/ql/lib/change-notes/2025-09-30-fewer-safe-urls.md
Normal file
4
go/ql/lib/change-notes/2025-09-30-fewer-safe-urls.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* `go/unvalidated-url-redirection` and `go/request-forgery` have a shared notion of a safe URL, which is known to not be malicious. Some URLs which were incorrectly considered safe are now correctly considered unsafe. This may lead to more alerts for those two queries.
|
||||
3
go/ql/lib/change-notes/released/4.3.5.md
Normal file
3
go/ql/lib/change-notes/released/4.3.5.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 4.3.5
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 4.3.4
|
||||
lastReleaseVersion: 4.3.5
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/go-all
|
||||
version: 4.3.5-dev
|
||||
version: 4.3.6-dev
|
||||
groups: go
|
||||
dbscheme: go.dbscheme
|
||||
extractor: go
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import go
|
||||
import UrlConcatenation
|
||||
import SafeUrlFlowCustomizations
|
||||
private import SafeUrlFlowCustomizations
|
||||
import semmle.go.dataflow.barrierguardutil.RedirectCheckBarrierGuard
|
||||
import semmle.go.dataflow.barrierguardutil.RegexpCheck
|
||||
import semmle.go.dataflow.barrierguardutil.UrlCheck
|
||||
@@ -121,21 +121,6 @@ module OpenUrlRedirect {
|
||||
/** A sink for an open redirect, considered as a sink for safe URL flow. */
|
||||
private class SafeUrlSink extends SafeUrlFlow::Sink instanceof OpenUrlRedirect::Sink { }
|
||||
|
||||
/**
|
||||
* A read of a field considered unsafe to redirect to, considered as a sanitizer for a safe
|
||||
* URL.
|
||||
*/
|
||||
private class UnsafeFieldReadSanitizer extends SafeUrlFlow::SanitizerEdge {
|
||||
UnsafeFieldReadSanitizer() {
|
||||
exists(DataFlow::FieldReadNode frn, string name |
|
||||
name = ["User", "RawQuery", "Fragment"] and
|
||||
frn.getField().hasQualifiedName("net/url", "URL")
|
||||
|
|
||||
this = frn.getBase()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reinstate the usual field propagation rules for fields, which the OpenURLRedirect
|
||||
* query usually excludes, for fields of `Params` other than `Params.Fixed`.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import go
|
||||
import UrlConcatenation
|
||||
import SafeUrlFlowCustomizations
|
||||
private import SafeUrlFlowCustomizations
|
||||
import semmle.go.dataflow.barrierguardutil.RedirectCheckBarrierGuard
|
||||
import semmle.go.dataflow.barrierguardutil.RegexpCheck
|
||||
import semmle.go.dataflow.barrierguardutil.UrlCheck
|
||||
@@ -118,18 +118,3 @@ module RequestForgery {
|
||||
|
||||
/** A sink for request forgery, considered as a sink for safe URL flow. */
|
||||
private class SafeUrlSink extends SafeUrlFlow::Sink instanceof RequestForgery::Sink { }
|
||||
|
||||
/**
|
||||
* A read of a field considered unsafe for request forgery, considered as a sanitizer for a safe
|
||||
* URL.
|
||||
*/
|
||||
private class UnsafeFieldReadSanitizer extends SafeUrlFlow::SanitizerEdge {
|
||||
UnsafeFieldReadSanitizer() {
|
||||
exists(DataFlow::FieldReadNode frn, string name |
|
||||
(name = "RawQuery" or name = "Fragment" or name = "User") and
|
||||
frn.getField().hasQualifiedName("net/url", "URL")
|
||||
|
|
||||
this = frn.getBase()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,8 +30,10 @@ module SafeUrlFlow {
|
||||
|
||||
predicate isBarrierOut(DataFlow::Node node) {
|
||||
// block propagation of this safe value when its host is overwritten
|
||||
exists(Write w, Field f | f.hasQualifiedName("net/url", "URL", "Host") |
|
||||
w.writesField(node.getASuccessor(), f, _)
|
||||
exists(Write w, DataFlow::Node b, Field f |
|
||||
f.hasQualifiedName("net/url", "URL", "Host") and
|
||||
b = node.getASuccessor() and
|
||||
w.writesField(b, f, _)
|
||||
)
|
||||
or
|
||||
node instanceof SanitizerEdge
|
||||
|
||||
@@ -40,4 +40,19 @@ module SafeUrlFlow {
|
||||
private class StringSlicingEdge extends SanitizerEdge {
|
||||
StringSlicingEdge() { this = any(DataFlow::SliceNode sn) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A read of a field considered unsafe to redirect to, considered as a sanitizer for a safe
|
||||
* URL.
|
||||
*/
|
||||
private class UnsafeFieldReadSanitizer extends SanitizerEdge {
|
||||
UnsafeFieldReadSanitizer() {
|
||||
exists(DataFlow::FieldReadNode frn, string name |
|
||||
name = ["Fragment", "RawQuery", "User"] and
|
||||
frn.getField().hasQualifiedName("net/url", "URL", name)
|
||||
|
|
||||
this = frn.getBase()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 1.4.6
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.4.5
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -13,12 +13,16 @@
|
||||
|
||||
import go
|
||||
|
||||
private Expr getConstantInitialiser(Expr e) {
|
||||
exists(DeclaredConstant c | e = c.getAReference() | result = c.getInit())
|
||||
}
|
||||
|
||||
/** Holds if `e` is not 0 and is either an octal or hexadecimal literal, or the number one. */
|
||||
predicate maybeXorBitPattern(Expr e) {
|
||||
// 0 makes no sense as an xor bit pattern
|
||||
not e.getNumericValue() = 0 and
|
||||
// include octal and hex literals
|
||||
e.(IntLit).getText().matches("0%")
|
||||
[e, getConstantInitialiser(e)].(IntLit).getText().matches("0%")
|
||||
or
|
||||
e.getNumericValue() = 1
|
||||
}
|
||||
|
||||
3
go/ql/src/change-notes/released/1.4.6.md
Normal file
3
go/ql/src/change-notes/released/1.4.6.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 1.4.6
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.4.5
|
||||
lastReleaseVersion: 1.4.6
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/go-queries
|
||||
version: 1.4.6-dev
|
||||
version: 1.4.7-dev
|
||||
groups:
|
||||
- go
|
||||
- queries
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
#select
|
||||
| SafeUrlFlow.go:11:24:11:50 | ...+... | SafeUrlFlow.go:10:14:10:21 | selection of Host | SafeUrlFlow.go:11:24:11:50 | ...+... | A safe URL flows here from $@. | SafeUrlFlow.go:10:14:10:21 | selection of Host | here |
|
||||
| SafeUrlFlow.go:14:29:14:44 | call to String | SafeUrlFlow.go:13:13:13:19 | selection of URL | SafeUrlFlow.go:14:29:14:44 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:13:13:13:19 | selection of URL | here |
|
||||
| SafeUrlFlow.go:18:11:18:28 | call to String | SafeUrlFlow.go:10:14:10:21 | selection of Host | SafeUrlFlow.go:18:11:18:28 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:10:14:10:21 | selection of Host | here |
|
||||
| SafeUrlFlow.go:45:24:45:61 | ...+... | SafeUrlFlow.go:37:13:37:19 | selection of URL | SafeUrlFlow.go:45:24:45:61 | ...+... | A safe URL flows here from $@. | SafeUrlFlow.go:37:13:37:19 | selection of URL | here |
|
||||
| SafeUrlFlow.go:46:29:46:55 | ...+... | SafeUrlFlow.go:37:13:37:19 | selection of URL | SafeUrlFlow.go:46:29:46:55 | ...+... | A safe URL flows here from $@. | SafeUrlFlow.go:37:13:37:19 | selection of URL | here |
|
||||
| SafeUrlFlow.go:47:11:47:42 | ...+... | SafeUrlFlow.go:37:13:37:19 | selection of URL | SafeUrlFlow.go:47:11:47:42 | ...+... | A safe URL flows here from $@. | SafeUrlFlow.go:37:13:37:19 | selection of URL | here |
|
||||
| SafeUrlFlow.go:57:11:57:26 | call to String | SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:57:11:57:26 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:54:13:54:19 | selection of URL | here |
|
||||
| SafeUrlFlow.go:58:12:58:27 | call to String | SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:58:12:58:27 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:54:13:54:19 | selection of URL | here |
|
||||
| SafeUrlFlow.go:59:16:59:31 | call to String | SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:59:16:59:31 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:54:13:54:19 | selection of URL | here |
|
||||
| SafeUrlFlow.go:60:12:60:27 | call to String | SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:60:12:60:27 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:54:13:54:19 | selection of URL | here |
|
||||
| SafeUrlFlow.go:64:13:64:28 | call to String | SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:64:13:64:28 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:54:13:54:19 | selection of URL | here |
|
||||
| SafeUrlFlow.go:65:14:65:29 | call to String | SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:65:14:65:29 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:54:13:54:19 | selection of URL | here |
|
||||
| SafeUrlFlow.go:66:18:66:33 | call to String | SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:66:18:66:33 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:54:13:54:19 | selection of URL | here |
|
||||
| SafeUrlFlow.go:67:14:67:29 | call to String | SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:67:14:67:29 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:54:13:54:19 | selection of URL | here |
|
||||
| SafeUrlFlow.go:70:39:70:54 | call to String | SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:70:39:70:54 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:54:13:54:19 | selection of URL | here |
|
||||
| SafeUrlFlow.go:74:70:74:85 | call to String | SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:74:70:74:85 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:54:13:54:19 | selection of URL | here |
|
||||
| SafeUrlFlow.go:78:40:78:55 | call to String | SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:78:40:78:55 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:54:13:54:19 | selection of URL | here |
|
||||
| SafeUrlFlow.go:89:24:89:41 | call to String | SafeUrlFlow.go:84:14:84:21 | selection of Host | SafeUrlFlow.go:89:24:89:41 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:84:14:84:21 | selection of Host | here |
|
||||
| SafeUrlFlow.go:109:11:109:23 | reconstructed | SafeUrlFlow.go:100:13:100:19 | selection of URL | SafeUrlFlow.go:109:11:109:23 | reconstructed | A safe URL flows here from $@. | SafeUrlFlow.go:100:13:100:19 | selection of URL | here |
|
||||
| SafeUrlFlow.go:112:24:112:50 | ...+... | SafeUrlFlow.go:100:13:100:19 | selection of URL | SafeUrlFlow.go:112:24:112:50 | ...+... | A safe URL flows here from $@. | SafeUrlFlow.go:100:13:100:19 | selection of URL | here |
|
||||
| SafeUrlFlow.go:113:29:113:58 | ...+... | SafeUrlFlow.go:100:13:100:19 | selection of URL | SafeUrlFlow.go:113:29:113:58 | ...+... | A safe URL flows here from $@. | SafeUrlFlow.go:100:13:100:19 | selection of URL | here |
|
||||
| SafeUrlFlow.go:114:12:114:42 | ...+... | SafeUrlFlow.go:100:13:100:19 | selection of URL | SafeUrlFlow.go:114:12:114:42 | ...+... | A safe URL flows here from $@. | SafeUrlFlow.go:100:13:100:19 | selection of URL | here |
|
||||
| SafeUrlFlow.go:115:12:115:25 | safeOpaquePart | SafeUrlFlow.go:100:13:100:19 | selection of URL | SafeUrlFlow.go:115:12:115:25 | safeOpaquePart | A safe URL flows here from $@. | SafeUrlFlow.go:100:13:100:19 | selection of URL | here |
|
||||
edges
|
||||
| SafeUrlFlow.go:10:14:10:21 | selection of Host | SafeUrlFlow.go:11:24:11:50 | ...+... | provenance | Sink:MaD:1 |
|
||||
| SafeUrlFlow.go:10:14:10:21 | selection of Host | SafeUrlFlow.go:17:19:17:26 | safeHost | provenance | |
|
||||
| SafeUrlFlow.go:13:13:13:19 | selection of URL | SafeUrlFlow.go:14:29:14:35 | safeURL | provenance | Src:MaD:2 |
|
||||
| SafeUrlFlow.go:14:29:14:35 | safeURL | SafeUrlFlow.go:14:29:14:44 | call to String | provenance | MaD:3 |
|
||||
| SafeUrlFlow.go:17:19:17:26 | safeHost | SafeUrlFlow.go:18:11:18:19 | targetURL | provenance | Config |
|
||||
| SafeUrlFlow.go:18:11:18:19 | targetURL | SafeUrlFlow.go:18:11:18:28 | call to String | provenance | MaD:3 |
|
||||
| SafeUrlFlow.go:37:13:37:19 | selection of URL | SafeUrlFlow.go:45:24:45:61 | ...+... | provenance | Src:MaD:2 Sink:MaD:1 |
|
||||
| SafeUrlFlow.go:37:13:37:19 | selection of URL | SafeUrlFlow.go:46:29:46:55 | ...+... | provenance | Src:MaD:2 |
|
||||
| SafeUrlFlow.go:37:13:37:19 | selection of URL | SafeUrlFlow.go:47:11:47:42 | ...+... | provenance | Src:MaD:2 |
|
||||
| SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:57:11:57:17 | safeURL | provenance | Src:MaD:2 |
|
||||
| SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:58:12:58:18 | safeURL | provenance | Src:MaD:2 |
|
||||
| SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:59:16:59:22 | safeURL | provenance | Src:MaD:2 |
|
||||
| SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:60:12:60:18 | safeURL | provenance | Src:MaD:2 |
|
||||
| SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:64:13:64:19 | safeURL | provenance | Src:MaD:2 |
|
||||
| SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:65:14:65:20 | safeURL | provenance | Src:MaD:2 |
|
||||
| SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:66:18:66:24 | safeURL | provenance | Src:MaD:2 |
|
||||
| SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:67:14:67:20 | safeURL | provenance | Src:MaD:2 |
|
||||
| SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:70:39:70:45 | safeURL | provenance | Src:MaD:2 |
|
||||
| SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:74:70:74:76 | safeURL | provenance | Src:MaD:2 |
|
||||
| SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:78:40:78:46 | safeURL | provenance | Src:MaD:2 |
|
||||
| SafeUrlFlow.go:57:11:57:17 | safeURL | SafeUrlFlow.go:57:11:57:26 | call to String | provenance | MaD:3 |
|
||||
| SafeUrlFlow.go:58:12:58:18 | safeURL | SafeUrlFlow.go:58:12:58:27 | call to String | provenance | MaD:3 |
|
||||
| SafeUrlFlow.go:59:16:59:22 | safeURL | SafeUrlFlow.go:59:16:59:31 | call to String | provenance | MaD:3 |
|
||||
| SafeUrlFlow.go:60:12:60:18 | safeURL | SafeUrlFlow.go:60:12:60:27 | call to String | provenance | MaD:3 |
|
||||
| SafeUrlFlow.go:64:13:64:19 | safeURL | SafeUrlFlow.go:64:13:64:28 | call to String | provenance | MaD:3 |
|
||||
| SafeUrlFlow.go:65:14:65:20 | safeURL | SafeUrlFlow.go:65:14:65:29 | call to String | provenance | MaD:3 |
|
||||
| SafeUrlFlow.go:66:18:66:24 | safeURL | SafeUrlFlow.go:66:18:66:33 | call to String | provenance | MaD:3 |
|
||||
| SafeUrlFlow.go:67:14:67:20 | safeURL | SafeUrlFlow.go:67:14:67:29 | call to String | provenance | MaD:3 |
|
||||
| SafeUrlFlow.go:70:39:70:45 | safeURL | SafeUrlFlow.go:70:39:70:54 | call to String | provenance | MaD:3 |
|
||||
| SafeUrlFlow.go:74:70:74:76 | safeURL | SafeUrlFlow.go:74:70:74:85 | call to String | provenance | MaD:3 |
|
||||
| SafeUrlFlow.go:78:40:78:46 | safeURL | SafeUrlFlow.go:78:40:78:55 | call to String | provenance | MaD:3 |
|
||||
| SafeUrlFlow.go:84:14:84:21 | selection of Host | SafeUrlFlow.go:87:19:87:26 | safeHost | provenance | |
|
||||
| SafeUrlFlow.go:87:19:87:26 | safeHost | SafeUrlFlow.go:89:24:89:32 | targetURL | provenance | Config |
|
||||
| SafeUrlFlow.go:89:24:89:32 | targetURL | SafeUrlFlow.go:89:24:89:41 | call to String | provenance | MaD:3 Sink:MaD:1 |
|
||||
| SafeUrlFlow.go:100:13:100:19 | selection of URL | SafeUrlFlow.go:109:11:109:23 | reconstructed | provenance | Src:MaD:2 |
|
||||
| SafeUrlFlow.go:100:13:100:19 | selection of URL | SafeUrlFlow.go:112:24:112:50 | ...+... | provenance | Src:MaD:2 Sink:MaD:1 |
|
||||
| SafeUrlFlow.go:100:13:100:19 | selection of URL | SafeUrlFlow.go:113:29:113:58 | ...+... | provenance | Src:MaD:2 |
|
||||
| SafeUrlFlow.go:100:13:100:19 | selection of URL | SafeUrlFlow.go:114:12:114:42 | ...+... | provenance | Src:MaD:2 |
|
||||
| SafeUrlFlow.go:100:13:100:19 | selection of URL | SafeUrlFlow.go:115:12:115:25 | safeOpaquePart | provenance | Src:MaD:2 |
|
||||
models
|
||||
| 1 | Sink: net/http; ; false; Redirect; ; ; Argument[2]; url-redirection[0]; manual |
|
||||
| 2 | Source: net/http; Request; true; URL; ; ; ; remote; manual |
|
||||
| 3 | Summary: fmt; Stringer; true; String; ; ; Argument[receiver]; ReturnValue; taint; manual |
|
||||
nodes
|
||||
| SafeUrlFlow.go:10:14:10:21 | selection of Host | semmle.label | selection of Host |
|
||||
| SafeUrlFlow.go:11:24:11:50 | ...+... | semmle.label | ...+... |
|
||||
| SafeUrlFlow.go:13:13:13:19 | selection of URL | semmle.label | selection of URL |
|
||||
| SafeUrlFlow.go:14:29:14:35 | safeURL | semmle.label | safeURL |
|
||||
| SafeUrlFlow.go:14:29:14:44 | call to String | semmle.label | call to String |
|
||||
| SafeUrlFlow.go:17:19:17:26 | safeHost | semmle.label | safeHost |
|
||||
| SafeUrlFlow.go:18:11:18:19 | targetURL | semmle.label | targetURL |
|
||||
| SafeUrlFlow.go:18:11:18:28 | call to String | semmle.label | call to String |
|
||||
| SafeUrlFlow.go:37:13:37:19 | selection of URL | semmle.label | selection of URL |
|
||||
| SafeUrlFlow.go:45:24:45:61 | ...+... | semmle.label | ...+... |
|
||||
| SafeUrlFlow.go:46:29:46:55 | ...+... | semmle.label | ...+... |
|
||||
| SafeUrlFlow.go:47:11:47:42 | ...+... | semmle.label | ...+... |
|
||||
| SafeUrlFlow.go:54:13:54:19 | selection of URL | semmle.label | selection of URL |
|
||||
| SafeUrlFlow.go:57:11:57:17 | safeURL | semmle.label | safeURL |
|
||||
| SafeUrlFlow.go:57:11:57:26 | call to String | semmle.label | call to String |
|
||||
| SafeUrlFlow.go:58:12:58:18 | safeURL | semmle.label | safeURL |
|
||||
| SafeUrlFlow.go:58:12:58:27 | call to String | semmle.label | call to String |
|
||||
| SafeUrlFlow.go:59:16:59:22 | safeURL | semmle.label | safeURL |
|
||||
| SafeUrlFlow.go:59:16:59:31 | call to String | semmle.label | call to String |
|
||||
| SafeUrlFlow.go:60:12:60:18 | safeURL | semmle.label | safeURL |
|
||||
| SafeUrlFlow.go:60:12:60:27 | call to String | semmle.label | call to String |
|
||||
| SafeUrlFlow.go:64:13:64:19 | safeURL | semmle.label | safeURL |
|
||||
| SafeUrlFlow.go:64:13:64:28 | call to String | semmle.label | call to String |
|
||||
| SafeUrlFlow.go:65:14:65:20 | safeURL | semmle.label | safeURL |
|
||||
| SafeUrlFlow.go:65:14:65:29 | call to String | semmle.label | call to String |
|
||||
| SafeUrlFlow.go:66:18:66:24 | safeURL | semmle.label | safeURL |
|
||||
| SafeUrlFlow.go:66:18:66:33 | call to String | semmle.label | call to String |
|
||||
| SafeUrlFlow.go:67:14:67:20 | safeURL | semmle.label | safeURL |
|
||||
| SafeUrlFlow.go:67:14:67:29 | call to String | semmle.label | call to String |
|
||||
| SafeUrlFlow.go:70:39:70:45 | safeURL | semmle.label | safeURL |
|
||||
| SafeUrlFlow.go:70:39:70:54 | call to String | semmle.label | call to String |
|
||||
| SafeUrlFlow.go:74:70:74:76 | safeURL | semmle.label | safeURL |
|
||||
| SafeUrlFlow.go:74:70:74:85 | call to String | semmle.label | call to String |
|
||||
| SafeUrlFlow.go:78:40:78:46 | safeURL | semmle.label | safeURL |
|
||||
| SafeUrlFlow.go:78:40:78:55 | call to String | semmle.label | call to String |
|
||||
| SafeUrlFlow.go:84:14:84:21 | selection of Host | semmle.label | selection of Host |
|
||||
| SafeUrlFlow.go:87:19:87:26 | safeHost | semmle.label | safeHost |
|
||||
| SafeUrlFlow.go:89:24:89:32 | targetURL | semmle.label | targetURL |
|
||||
| SafeUrlFlow.go:89:24:89:41 | call to String | semmle.label | call to String |
|
||||
| SafeUrlFlow.go:100:13:100:19 | selection of URL | semmle.label | selection of URL |
|
||||
| SafeUrlFlow.go:109:11:109:23 | reconstructed | semmle.label | reconstructed |
|
||||
| SafeUrlFlow.go:112:24:112:50 | ...+... | semmle.label | ...+... |
|
||||
| SafeUrlFlow.go:113:29:113:58 | ...+... | semmle.label | ...+... |
|
||||
| SafeUrlFlow.go:114:12:114:42 | ...+... | semmle.label | ...+... |
|
||||
| SafeUrlFlow.go:115:12:115:25 | safeOpaquePart | semmle.label | safeOpaquePart |
|
||||
subpaths
|
||||
@@ -0,0 +1,126 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
func testStdlibSources(w http.ResponseWriter, req *http.Request) {
|
||||
safeHost := req.Host // $ Source
|
||||
http.Redirect(w, req, "https://"+safeHost+"/path", http.StatusFound) // $ Alert
|
||||
|
||||
safeURL := req.URL // $ Source
|
||||
w.Header().Set("Location", safeURL.String()) // $ Alert
|
||||
|
||||
targetURL := url.URL{}
|
||||
targetURL.Host = safeHost // URL is safe if Host is safe
|
||||
http.Get(targetURL.String()) // $ Alert
|
||||
}
|
||||
|
||||
func testBarrierEdge1(w http.ResponseWriter, req *http.Request) {
|
||||
safeURL := req.URL
|
||||
|
||||
query := safeURL.Query() // query is not guaranteed to be safe
|
||||
http.Redirect(w, req, query.Get("redirect"), http.StatusFound) // not guaranteed to be safe
|
||||
}
|
||||
|
||||
func testBarrierEdge2(w http.ResponseWriter, req *http.Request) {
|
||||
safeURL := req.URL
|
||||
|
||||
urlString := safeURL.String()
|
||||
sliced := urlString[0:10] // a substring of a safe URL is not guaranteed to be safe
|
||||
w.Header().Set("Location", sliced) // not guaranteed to be safe
|
||||
}
|
||||
|
||||
func testFieldReads(w http.ResponseWriter, req *http.Request) {
|
||||
safeURL := req.URL // $ Source
|
||||
|
||||
safeScheme := safeURL.Scheme // the scheme of a safe URL is safe
|
||||
safeHost := safeURL.Host // the host of a safe URL is safe
|
||||
safePath := safeURL.Path // the path of a safe URL is safe
|
||||
fragment := safeURL.Fragment // the fragment of a safe URL is not guaranteed to be safe
|
||||
user := safeURL.User // the user of a safe URL is not guaranteed to be safe
|
||||
|
||||
http.Redirect(w, req, "https://"+safeScheme+"://example.com", http.StatusFound) // $ Alert
|
||||
w.Header().Set("Location", "https://"+safeHost+"/path") // $ Alert
|
||||
http.Get("https://example.com" + safePath) // $ Alert
|
||||
|
||||
http.Get(fragment) // not guaranteed to be safe
|
||||
http.Get(user.String()) // not guaranteed to be safe
|
||||
}
|
||||
|
||||
func testRequestForgerySinks(req *http.Request) {
|
||||
safeURL := req.URL // $ Source
|
||||
|
||||
// Standard library HTTP functions (request-forgery sinks)
|
||||
http.Get(safeURL.String()) // $ Alert
|
||||
http.Post(safeURL.String(), "application/json", nil) // $ Alert
|
||||
http.PostForm(safeURL.String(), nil) // $ Alert
|
||||
http.Head(safeURL.String()) // $ Alert
|
||||
|
||||
// HTTP Client methods (request-forgery sinks)
|
||||
client := &http.Client{}
|
||||
client.Get(safeURL.String()) // $ Alert
|
||||
client.Post(safeURL.String(), "application/json", nil) // $ Alert
|
||||
client.PostForm(safeURL.String(), nil) // $ Alert
|
||||
client.Head(safeURL.String()) // $ Alert
|
||||
|
||||
// NewRequest + Client.Do (request-forgery sinks)
|
||||
request, _ := http.NewRequest("GET", safeURL.String(), nil) // $ Alert
|
||||
client.Do(request)
|
||||
|
||||
// NewRequestWithContext + Client.Do (request-forgery sinks)
|
||||
reqWithCtx, _ := http.NewRequestWithContext(context.TODO(), "POST", safeURL.String(), nil) // $ Alert
|
||||
client.Do(reqWithCtx)
|
||||
|
||||
// RoundTrip method (request-forgery sink)
|
||||
request2, _ := http.NewRequest("GET", safeURL.String(), nil) // $ Alert
|
||||
transport := &http.Transport{}
|
||||
transport.RoundTrip(request2)
|
||||
}
|
||||
|
||||
func testHostFieldAssignmentFlow(w http.ResponseWriter, req *http.Request) {
|
||||
safeHost := req.Host // $ Source
|
||||
|
||||
targetURL, _ := url.Parse("http://example.com/data")
|
||||
targetURL.Host = safeHost // URL is safe if Host is safe
|
||||
|
||||
http.Redirect(w, req, targetURL.String(), http.StatusFound) // $ Alert
|
||||
}
|
||||
|
||||
func testHostFieldOverwritten(w http.ResponseWriter, req *http.Request) {
|
||||
safeURL := req.URL
|
||||
|
||||
safeURL.Host = "something.else.com" // safeURL is not guaranteed to be safe now that Host is overwritten
|
||||
http.Get(safeURL.String()) // not guaranteed to be safe
|
||||
}
|
||||
|
||||
func testFieldAccess(w http.ResponseWriter, req *http.Request) {
|
||||
safeURL := req.URL // $ Source
|
||||
|
||||
safeHost := safeURL.Host // the host of a safe URL is safe
|
||||
safePath := safeURL.Path // the path of a safe URL is safe
|
||||
safeScheme := safeURL.Scheme // the scheme of a safe URL is safe
|
||||
safeOpaquePart := safeURL.Opaque // the opaque part of a safe URL is safe
|
||||
|
||||
// Reconstruct URL - still guaranteed to be safe
|
||||
reconstructed := safeScheme + "://" + safeHost + safePath
|
||||
http.Get(reconstructed) // $ Alert
|
||||
|
||||
// Test individual fields
|
||||
http.Redirect(w, req, "https://"+safeHost+"/path", http.StatusFound) // $ Alert
|
||||
w.Header().Set("Location", "https://example.com"+safePath) // $ Alert
|
||||
http.Post(safeScheme+"://example.com/api", "application/json", nil) // $ Alert
|
||||
http.Post(safeOpaquePart, "application/json", nil) // $ Alert
|
||||
|
||||
user := safeURL.User // the user of a safe URL is not guaranteed to be safe
|
||||
query := safeURL.RawQuery // the query of a safe URL is not guaranteed to be safe
|
||||
fragment := safeURL.Fragment // the fragment of a safe URL is not guaranteed to be safe
|
||||
|
||||
if user != nil {
|
||||
http.Redirect(w, req, user.String(), http.StatusFound) // not guaranteed to be safe
|
||||
}
|
||||
w.Header().Set("Location", "https://example.com/?"+query) // not guaranteed to be safe
|
||||
http.Get("https://example.com/#" + fragment) // not guaranteed to be safe
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* @id go/test-safe-url-flow
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
*/
|
||||
|
||||
import go
|
||||
import semmle.go.security.RequestForgeryCustomizations
|
||||
import semmle.go.security.OpenUrlRedirectCustomizations
|
||||
import semmle.go.security.SafeUrlFlow
|
||||
import SafeUrlFlow::Flow::PathGraph
|
||||
|
||||
from SafeUrlFlow::Flow::PathNode source, SafeUrlFlow::Flow::PathNode sink
|
||||
where SafeUrlFlow::Flow::flowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "A safe URL flows here from $@.", source.getNode(), "here"
|
||||
@@ -0,0 +1,4 @@
|
||||
query: SafeUrlFlow.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
@@ -22,6 +22,13 @@ func main() {
|
||||
|
||||
mask := (((1 << 10) - 1) ^ 7) // OK
|
||||
|
||||
const (
|
||||
c1 = 0x1234
|
||||
c2 = 0x5678
|
||||
)
|
||||
|
||||
fmt.Println(c1 ^ c2) // OK
|
||||
|
||||
// This is not ok, but isn't detected because the multiplication binds tighter
|
||||
// than the xor operator and so the query doesn't see a constant on the left
|
||||
// hand side of ^.
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
query: Likely Bugs/Arithmetic/ConstantExpAppearsNonConstant.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
@@ -0,0 +1,7 @@
|
||||
class Test {
|
||||
public static void updateFlashlights(Minecraft mc){
|
||||
if(mc.world != null){
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
def test(codeql, java):
|
||||
codeql.database.create(build_mode="none")
|
||||
@@ -1,3 +1,7 @@
|
||||
## 7.7.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 7.7.0
|
||||
|
||||
### New Features
|
||||
|
||||
3
java/ql/lib/change-notes/released/7.7.1.md
Normal file
3
java/ql/lib/change-notes/released/7.7.1.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 7.7.1
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 7.7.0
|
||||
lastReleaseVersion: 7.7.1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/java-all
|
||||
version: 7.7.1-dev
|
||||
version: 7.7.2-dev
|
||||
groups: java
|
||||
dbscheme: config/semmlecode.dbscheme
|
||||
extractor: java
|
||||
|
||||
@@ -88,7 +88,45 @@ private string baseConfigLocatable(@configLocatable el) {
|
||||
not isOverlay() and result = getRawFileForConfig(el)
|
||||
}
|
||||
|
||||
overlay[local]
|
||||
private predicate overlayConfigExtracted(string file) {
|
||||
isOverlay() and
|
||||
exists(@configLocatable el | file = getRawFileForConfig(el))
|
||||
}
|
||||
|
||||
overlay[discard_entity]
|
||||
private predicate discardBaseConfigLocatable(@configLocatable el) {
|
||||
overlayChangedFiles(baseConfigLocatable(el))
|
||||
or
|
||||
// The config extractor is currently not incremental and may extract more
|
||||
// property files than those included in overlayChangedFiles.
|
||||
overlayConfigExtracted(baseConfigLocatable(el))
|
||||
}
|
||||
|
||||
/**
|
||||
* An `@xmllocatable` that should be discarded in the base variant if its file is
|
||||
* extracted in the overlay variant.
|
||||
*/
|
||||
overlay[local]
|
||||
abstract class DiscardableXmlLocatable extends @xmllocatable {
|
||||
/** Gets the raw file for an xmllocatable in base. */
|
||||
string getRawFileInBase() { not isOverlay() and result = getRawFile(this) }
|
||||
|
||||
/** Gets a textual representation of this discardable xmllocatable. */
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
overlay[local]
|
||||
private predicate overlayXmlExtracted(string file) {
|
||||
isOverlay() and
|
||||
exists(@xmllocatable el | not files(el, _) and not xmlNs(el, _, _, _) and file = getRawFile(el))
|
||||
}
|
||||
|
||||
overlay[discard_entity]
|
||||
private predicate discardXmlLocatable(@xmllocatable el) {
|
||||
overlayChangedFiles(el.(DiscardableXmlLocatable).getRawFileInBase())
|
||||
or
|
||||
// The XML extractor is currently not incremental and may extract more
|
||||
// XML files than those included in overlayChangedFiles.
|
||||
overlayXmlExtracted(el.(DiscardableXmlLocatable).getRawFileInBase())
|
||||
}
|
||||
|
||||
@@ -71,12 +71,12 @@ private module Input implements InputSig<File, Location> {
|
||||
|
||||
import Make<File, Location, Input>
|
||||
|
||||
private class DiscardableXmlAttribute extends DiscardableLocatable, @xmlattribute { }
|
||||
private class DiscardableXmlAttribute extends DiscardableXmlLocatable, @xmlattribute { }
|
||||
|
||||
private class DiscardableXmlElement extends DiscardableLocatable, @xmlelement { }
|
||||
private class DiscardableXmlElement extends DiscardableXmlLocatable, @xmlelement { }
|
||||
|
||||
private class DiscardableXmlComment extends DiscardableLocatable, @xmlcomment { }
|
||||
private class DiscardableXmlComment extends DiscardableXmlLocatable, @xmlcomment { }
|
||||
|
||||
private class DiscardableXmlCharacters extends DiscardableLocatable, @xmlcharacters { }
|
||||
private class DiscardableXmlCharacters extends DiscardableXmlLocatable, @xmlcharacters { }
|
||||
|
||||
private class DiscardableXmlDtd extends DiscardableLocatable, @xmldtd { }
|
||||
private class DiscardableXmlDtd extends DiscardableXmlLocatable, @xmldtd { }
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 1.8.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.8.0
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
@@ -19,7 +19,7 @@ predicate isConstantExp(Expr e) {
|
||||
// A literal is constant.
|
||||
e instanceof Literal
|
||||
or
|
||||
e instanceof TypeAccess
|
||||
e instanceof TypeAccess and not e.(TypeAccess).getType() instanceof ErrorType
|
||||
or
|
||||
e instanceof ArrayTypeAccess
|
||||
or
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
|
||||
import java
|
||||
|
||||
private predicate hasASubclass(RefType t) {
|
||||
exists(RefType sub | sub != t | sub.getAnAncestor() = t)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this type is either `final` or
|
||||
* `private` and without subtypes.
|
||||
@@ -24,7 +28,11 @@ private predicate cannotBeExtended(RefType t) {
|
||||
or
|
||||
// If the class is private, all possible subclasses are known.
|
||||
t.isPrivate() and
|
||||
not exists(RefType sub | sub != t | sub.getAnAncestor() = t)
|
||||
not hasASubclass(t)
|
||||
or
|
||||
// If the class only has private constructors, all possible subclasses are known.
|
||||
forex(Constructor c | c.getDeclaringType() = t | c.isPrivate()) and
|
||||
not hasASubclass(t)
|
||||
}
|
||||
|
||||
from MethodCall m, Constructor c, Class clazz
|
||||
|
||||
3
java/ql/src/change-notes/released/1.8.1.md
Normal file
3
java/ql/src/change-notes/released/1.8.1.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 1.8.1
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.8.0
|
||||
lastReleaseVersion: 1.8.1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/java-queries
|
||||
version: 1.8.1-dev
|
||||
version: 1.8.2-dev
|
||||
groups:
|
||||
- java
|
||||
- queries
|
||||
|
||||
@@ -30,4 +30,18 @@ public class Test {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static class AllPrivateConstructors {
|
||||
Thread myThread;
|
||||
|
||||
private AllPrivateConstructors() {
|
||||
myThread = new Thread("myThread");
|
||||
// OK - class cannot be extended outside this file, and is not in fact extended
|
||||
myThread.start();
|
||||
}
|
||||
|
||||
public static AllPrivateConstructors create() {
|
||||
return new AllPrivateConstructors();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
## 2.6.12
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added modeling of `GraphQLObjectType` resolver function parameters as remote sources.
|
||||
* Support for the [graphql](https://www.npmjs.com/package/graphql) library has been improved. Data flow from GraphQL query sources and variables to resolver function parameters is now tracked.
|
||||
* Added support for the `aws-sdk` and `@aws-sdk/client-dynamodb`, `@aws-sdk/client-athena`, `@aws-sdk/client-s3`, and `@aws-sdk/client-rds-data` packages.
|
||||
|
||||
## 2.6.11
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added support for the `aws-sdk` and `@aws-sdk/client-dynamodb`, `@aws-sdk/client-athena`, `@aws-sdk/client-s3`, and `@aws-sdk/client-rds-data` packages.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Support for the [graphql](https://www.npmjs.com/package/graphql) library has been improved. Data flow from GraphQL query sources and variables to resolver function parameters is now tracked.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added modeling of `GraphQLObjectType` resolver function parameters as remote sources.
|
||||
7
javascript/ql/lib/change-notes/released/2.6.12.md
Normal file
7
javascript/ql/lib/change-notes/released/2.6.12.md
Normal file
@@ -0,0 +1,7 @@
|
||||
## 2.6.12
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added modeling of `GraphQLObjectType` resolver function parameters as remote sources.
|
||||
* Support for the [graphql](https://www.npmjs.com/package/graphql) library has been improved. Data flow from GraphQL query sources and variables to resolver function parameters is now tracked.
|
||||
* Added support for the `aws-sdk` and `@aws-sdk/client-dynamodb`, `@aws-sdk/client-athena`, `@aws-sdk/client-s3`, and `@aws-sdk/client-rds-data` packages.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 2.6.11
|
||||
lastReleaseVersion: 2.6.12
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/javascript-all
|
||||
version: 2.6.12-dev
|
||||
version: 2.6.13-dev
|
||||
groups: javascript
|
||||
dbscheme: semmlecode.javascript.dbscheme
|
||||
extractor: javascript
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 2.1.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 2.1.0
|
||||
|
||||
### Major Analysis Improvements
|
||||
@@ -10,7 +14,7 @@
|
||||
* Data flow is now tracked through the `Promise.try` and `Array.prototype.with` functions.
|
||||
* Query `js/index-out-of-bounds` no longer produces a false-positive when a strictly-less-than check overrides a previous less-than-or-equal test.
|
||||
* The query `js/remote-property-injection` now detects property injection vulnerabilities through object enumeration patterns such as `Object.keys()`.
|
||||
* The query "Permissive CORS configuration" (`js/cors-permissive-configuration`) has been promoted from experimental and is now part of the default security suite.
|
||||
* The query "Permissive CORS configuration" (`js/cors-permissive-configuration`) has been promoted from experimental and is now part of the default security suite. Thank you to @maikypedia who [submitted the original experimental query](https://github.com/github/codeql/pull/14342)!
|
||||
|
||||
## 2.0.3
|
||||
|
||||
|
||||
@@ -10,4 +10,4 @@
|
||||
* Data flow is now tracked through the `Promise.try` and `Array.prototype.with` functions.
|
||||
* Query `js/index-out-of-bounds` no longer produces a false-positive when a strictly-less-than check overrides a previous less-than-or-equal test.
|
||||
* The query `js/remote-property-injection` now detects property injection vulnerabilities through object enumeration patterns such as `Object.keys()`.
|
||||
* The query "Permissive CORS configuration" (`js/cors-permissive-configuration`) has been promoted from experimental and is now part of the default security suite.
|
||||
* The query "Permissive CORS configuration" (`js/cors-permissive-configuration`) has been promoted from experimental and is now part of the default security suite. Thank you to @maikypedia who [submitted the original experimental query](https://github.com/github/codeql/pull/14342)!
|
||||
|
||||
3
javascript/ql/src/change-notes/released/2.1.1.md
Normal file
3
javascript/ql/src/change-notes/released/2.1.1.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 2.1.1
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 2.1.0
|
||||
lastReleaseVersion: 2.1.1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/javascript-queries
|
||||
version: 2.1.1-dev
|
||||
version: 2.1.2-dev
|
||||
groups:
|
||||
- javascript
|
||||
- queries
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 1.0.32
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.0.31
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
3
misc/suite-helpers/change-notes/released/1.0.32.md
Normal file
3
misc/suite-helpers/change-notes/released/1.0.32.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 1.0.32
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.0.31
|
||||
lastReleaseVersion: 1.0.32
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: codeql/suite-helpers
|
||||
version: 1.0.32-dev
|
||||
version: 1.0.33-dev
|
||||
groups: shared
|
||||
warnOnImplicitThis: true
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user