Skip to content

Commit 7de6a1e

Browse files
committed
JS: Add documentation and example
1 parent 13d2453 commit 7de6a1e

File tree

1 file changed

+47
-0
lines changed

1 file changed

+47
-0
lines changed

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

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,48 @@ Note that this flow is already recognized by the CodeQL JS analysis, but for thi
349349
- The last column, **value**, indicates the kind of flow to add. The value **value** means the input value is unchanged as
350350
it flows to the output.
351351

352+
353+
Example: Modeling properties injected by a middleware function
354+
--------------------------------------------------------------
355+
356+
In this example, we'll show how to model a hypothetical middleware function that adds a tainted value
357+
on the incoming request objects:
358+
359+
.. code-block:: js
360+
361+
const express = require('express')
362+
const app = express()
363+
364+
app.use(require('@example/middleware').injectData())
365+
366+
app.get('/foo', (req, res) => {
367+
req.data; // <-- mark 'req.data' as a taint source
368+
});
369+
370+
This can be achieved with the following data extension:
371+
372+
.. code-block:: yaml
373+
374+
extensions:
375+
- addsTo:
376+
pack: codeql/javascript-all
377+
extensible: sourceModel
378+
data:
379+
- [
380+
"@example/middleware",
381+
"Member[injectData].ReturnValue.GuardedRouteHandler.Parameter[0].Member[data]",
382+
"remote",
383+
]
384+
385+
- Since we're adding a new taint source, we add a tuple to the **sourceModel** extensible predicate.
386+
- The first column, **"@example/middleware"**, begins the search at imports of the hypothetical NPM package **@example/middleware**.
387+
- **Member[injectData]** selects accesses to the **injectData** member.
388+
- **ReturnValue** selects the return value of the call to **injectData**.
389+
- **GuardedRouteHandler** interprets the current value as a middleware function and selects all route handlers guarded by that middleware. Since the current value is passd to **app.use()**, the callback subsequently passed to **app.get()** is seen as a guarded route handler.
390+
- **Parameter[0]** selects the first parameter of the callback (the parameter named **req**).
391+
- **Member[data]** selects accesses to the **data** property of the **req** object.
392+
- Finally, the kind **remote** indicates that this is considered a source of remote flow.
393+
352394
Reference material
353395
------------------
354396

@@ -494,6 +536,11 @@ Components related to decorators:
494536
- **DecoratedParameter** selects a parameter that is decorated by the current value.
495537
- **DecoratedMember** selects a method, field, or accessor that is decorated by the current value.
496538

539+
Additionally there is a component related to middleware functions:
540+
541+
- **GuardedRouteHandler** interprets the current value as a middleware function, and selects any route handler function that comes after it in the routing hierarchy.
542+
This can be used to model properties injected onto request and response objects, such as **req.db** after a middleware that injects a database connection.
543+
497544
Additional notes about the syntax of operands:
498545

499546
- Multiple operands may be given to a single component, as a shorthand for the union of the operands. For example, **Member[foo,bar]** matches the union of **Member[foo]** and **Member[bar]**.

0 commit comments

Comments
 (0)