Skip to content

Commit 13a989b

Browse files
authored
Merge pull request github#13194 from asgerf/js/remove-mention-of-tracked-node
JS: remove mention of TrackedNode from docs
2 parents 6a8855e + f47acfb commit 13a989b

File tree

4 files changed

+17
-37
lines changed

4 files changed

+17
-37
lines changed

docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ The class `ASTNode <https://codeql.github.com/codeql-standard-libraries/javascri
193193
.. pull-quote::
194194

195195
Note
196-
196+
197197
These predicates should only be used to perform generic AST traversal. To access children of specific AST node types, the specialized predicates introduced below should be used instead. In particular, queries should not rely on the numeric indices of child nodes relative to their parent nodes: these are considered an implementation detail that may change between versions of the library.
198198

199199
Top-levels
@@ -700,28 +700,7 @@ The data flow graph-based analyses described so far are all intraprocedural: the
700700

701701
We distinguish here between data flow proper, and *taint tracking*: the latter not only considers value-preserving flow (such as from variable definitions to uses), but also cases where one value influences ("taints") another without determining it entirely. For example, in the assignment ``s2 = s1.substring(i)``, the value of ``s1`` influences the value of ``s2``, because ``s2`` is assigned a substring of ``s1``. In general, ``s2`` will not be assigned ``s1`` itself, so there is no data flow from ``s1`` to ``s2``, but ``s1`` still taints ``s2``.
702702

703-
The simplest way of implementing an interprocedural data flow analysis is to extend either class ``DataFlow::TrackedNode`` or ``DataFlow::TrackedExpr``. The former is a subclass of ``DataFlow::Node``, the latter of ``Expr``, and extending them ensures that the newly added values are tracked interprocedurally. You can use the predicate ``flowsTo`` to find out which nodes/expressions the tracked value flows to.
704-
705-
For example, suppose that we are developing an analysis to find hard-coded passwords. We might start by writing a simple query that looks for string constants flowing into variables named ``"password"``. To do this, we can extend ``TrackedExpr`` to track all constant strings, ``flowsTo`` to find cases where such a string flows into a (SSA) definition of a password variable:
706-
707-
.. code-block:: ql
708-
709-
import javascript
710-
711-
class TrackedStringLiteral extends DataFlow::TrackedNode {
712-
TrackedStringLiteral() {
713-
this.asExpr() instanceof ConstantString
714-
}
715-
}
716-
717-
from TrackedStringLiteral source, DataFlow::Node sink, SsaExplicitDefinition def
718-
where source.flowsTo(sink) and sink = DataFlow::ssaDefinitionNode(def) and
719-
def.getSourceVariable().getName().toLowerCase() = "password"
720-
select sink
721-
722-
Note that ``TrackedNode`` and ``TrackedExpr`` do not restrict the set of "sinks" for the inter-procedural flow analysis, tracking flow into any expression that they might flow to. This can be expensive for large code bases, and is often unnecessary, since usually you are only interested in flow to a particular set of sinks. For example, the above query only looks for flow into assignments to password variables.
723-
724-
This is a particular instance of a general pattern, whereby we want to specify a data flow or taint analysis in terms of its *sources* (where flow starts), *sinks* (where it should be tracked), and *barriers* or *sanitizers* (where flow is interrupted). The example does not include any sanitizers, but they are very common in security analyses: for example, an analysis that tracks the flow of untrusted user input into, say, a SQL query has to keep track of code that validates the input, thereby making it safe to use. Such a validation step is an example of a sanitizer.
703+
It is a common pattern that we wish to specify data flow or taint analysis in terms of its *sources* (where flow starts), *sinks* (where it should be tracked), and *barriers* or *sanitizers* (where flow is interrupted). Sanitizers they are very common in security analyses: for example, an analysis that tracks the flow of untrusted user input into, say, a SQL query has to keep track of code that validates the input, thereby making it safe to use. Such a validation step is an example of a sanitizer.
725704

726705
The classes ``DataFlow::Configuration`` and ``TaintTracking::Configuration`` allow specifying a data flow or taint analysis, respectively, by overriding the following predicates:
727706

@@ -735,10 +714,12 @@ Since for technical reasons both ``Configuration`` classes are subtypes of ``str
735714

736715
The predicate ``Configuration.hasFlow`` performs the actual flow tracking, starting at a source and looking for flow to a sink that does not pass through a barrier node or edge.
737716

738-
To continue with our above example, we can phrase it as a data flow configuration as follows:
717+
For example, suppose that we are developing an analysis to find hard-coded passwords. We might write a simple query that looks for string constants flowing into variables named ``"password"``.
739718

740719
.. code-block:: ql
741720
721+
import javascript
722+
742723
class PasswordTracker extends DataFlow::Configuration {
743724
PasswordTracker() {
744725
// unique identifier for this configuration
@@ -754,11 +735,8 @@ To continue with our above example, we can phrase it as a data flow configuratio
754735
}
755736
756737
predicate passwordVarAssign(Variable v, DataFlow::Node nd) {
757-
exists (SsaExplicitDefinition def |
758-
nd = DataFlow::ssaDefinitionNode(def) and
759-
def.getSourceVariable() = v and
760-
v.getName().toLowerCase() = "password"
761-
)
738+
v.getAnAssignedExpr() = nd.asExpr() and
739+
v.getName().toLowerCase() = "password"
762740
}
763741
}
764742
@@ -770,7 +748,6 @@ Now we can rephrase our query to use ``Configuration.hasFlow``:
770748
where pt.hasFlow(source, sink) and pt.passwordVarAssign(v, sink)
771749
select sink, "Password variable " + v + " is assigned a constant string."
772750
773-
Note that while analyses implemented in this way are inter-procedural in that they track flow and taint across function calls and returns, flow through global variables is not tracked. Flow through object properties is only tracked in limited cases, for example through properties of object literals or CommonJS ``module`` and ``exports`` objects.
774751
775752
Syntax errors
776753
~~~~~~~~~~~~~
@@ -794,7 +771,7 @@ The ``semmle.javascript.frameworks.AngularJS`` library provides support for work
794771
HTTP framework libraries
795772
^^^^^^^^^^^^^^^^^^^^^^^^
796773

797-
The library ``semmle.javacript.frameworks.HTTP`` provides classes modeling common concepts from various HTTP frameworks.
774+
The library ``semmle.javacript.frameworks.HTTP`` provides classes modeling common concepts from various HTTP frameworks.
798775

799776
Currently supported frameworks are `Express <https://expressjs.com/>`__, the standard Node.js ``http`` and ``https`` modules, `Connect <https://github.com/senchalabs/connect>`__, `Koa <https://koajs.com>`__, `Hapi <https://hapi.dev/>`__ and `Restify <http://restify.com/>`__.
800777

javascript/ql/test/tutorials/Introducing the JavaScript libraries/query17.qll

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,8 @@ class PasswordTracker extends DataFlow::Configuration {
1111
override predicate isSink(DataFlow::Node nd) { this.passwordVarAssign(_, nd) }
1212

1313
predicate passwordVarAssign(Variable v, DataFlow::Node nd) {
14-
exists(SsaExplicitDefinition def |
15-
nd = DataFlow::ssaDefinitionNode(def) and
16-
def.getSourceVariable() = v and
17-
v.getName().toLowerCase() = "password"
18-
)
14+
v.getAnAssignedExpr() = nd.asExpr() and
15+
v.getName().toLowerCase() = "password"
1916
}
2017
}
2118

javascript/ql/test/tutorials/Introducing the JavaScript libraries/tests.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ test_query4
99
| tst.js:29:1:29:5 | 1 + 2 | This expression should be bracketed to clarify precedence rules. |
1010
test_query19
1111
test_query17
12+
| tst.js:38:18:38:23 | "blah" | Password variable password is assigned a constant string. |
1213
test_query18
1314
| m.js:1:1:3:0 | <toplevel> | 0 |
1415
test_query8
@@ -18,6 +19,7 @@ test_query11
1819
| tst.js:31:12:31:12 | x | Dead store of local variable. |
1920
| tst.js:31:15:31:15 | y | Dead store of local variable. |
2021
| tst.js:31:18:31:18 | x | Dead store of local variable. |
22+
| tst.js:38:7:38:23 | password = "blah" | Dead store of local variable. |
2123
test_query12
2224
test_query20
2325
test_query3

javascript/ql/test/tutorials/Introducing the JavaScript libraries/tst.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,8 @@ function l(x, y, x) {
3232
for (i=0;i<10;++i);
3333
}
3434

35-
var j, j;
35+
var j, j;
36+
37+
function foo() {
38+
var password = "blah";
39+
}

0 commit comments

Comments
 (0)