Add path query example to other lang data flow docs

This commit is contained in:
Owen Mansel-Chan
2025-10-10 16:22:50 +01:00
parent 3c80690ba8
commit 944e116cc0
8 changed files with 334 additions and 0 deletions

View File

@@ -411,6 +411,48 @@ Exercise 4
GetenvToGethostbynameFlow::flow(source, sink)
select getenv, fc
Path Query Example
~~~~~~~~~~~~~~~~~~
Here is the answer to exercise 4 above, converted into a path query:
.. code-block:: ql
/**
* @kind path-problem
* @problem.severity warning
* @id getenv-to-gethostbyname
*/
import cpp
import semmle.code.cpp.dataflow.new.DataFlow
class GetenvSource extends DataFlow::Node {
GetenvSource() { this.asIndirectExpr(1).(FunctionCall).getTarget().hasGlobalName("getenv") }
}
module GetenvToGethostbynameConfiguration implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof GetenvSource }
predicate isSink(DataFlow::Node sink) {
exists(FunctionCall fc |
sink.asIndirectExpr(1) = fc.getArgument(0) and
fc.getTarget().hasName("gethostbyname")
)
}
}
module GetenvToGethostbynameFlow = DataFlow::Global<GetenvToGethostbynameConfiguration>;
import GetenvToGethostbynameFlow::PathGraph
from GetenvToGethostbynameFlow::PathNode source, GetenvToGethostbynameFlow::PathNode sink
where GetenvToGethostbynameFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This file access uses data from $@.",
source, "user-controllable input."
For more information, see "`Creating path queries <https://codeql.github.com/docs/writing-codeql-queries/creating-path-queries/>`__".
Further reading
---------------

View File

@@ -537,6 +537,48 @@ This can be adapted from the ``SystemUriFlow`` class:
}
}
Path Query Example
~~~~~~~~~~~~~~~~~~
Here is the answer to exercise 4 above, converted into a path query:
.. code-block:: ql
/**
* @kind path-problem
* @problem.severity warning
* @id getenv-to-gethostbyname
*/
import csharp
class EnvironmentVariableFlowSource extends DataFlow::ExprNode {
EnvironmentVariableFlowSource() {
this.getExpr().(MethodCall).getTarget().hasQualifiedName("System.Environment.GetEnvironmentVariable")
}
}
module EnvironmentToUriConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) {
src instanceof EnvironmentVariableFlowSource
}
predicate isSink(DataFlow::Node sink) {
exists(Call c | c.getTarget().(Constructor).getDeclaringType().hasQualifiedName("System.Uri")
and sink.asExpr()=c.getArgument(0))
}
}
module EnvironmentToUriFlow = DataFlow::Global<EnvironmentToUriConfig>;
import EnvironmentToUriFlow::PathGraph
from EnvironmentToUriFlow::PathNode src, EnvironmentToUriFlow::PathNode sink
where EnvironmentToUriFlow::flowPath(src, sink)
select src.getNode(), src, sink, "This environment variable constructs a 'System.Uri' $@.", sink, "here"
For more information, see "`Creating path queries <https://codeql.github.com/docs/writing-codeql-queries/creating-path-queries/>`__".
Further reading
---------------

View File

@@ -358,6 +358,54 @@ Exercise 4
where GetenvToURLFlow::flow(src, sink)
select src, "This environment variable constructs a URL $@.", sink, "here"
Path Query Example
~~~~~~~~~~~~~~~~~~
Here is the answer to exercise 4 above, converted into a path query:
.. code-block:: ql
/**
* @kind path-problem
* @problem.severity warning
* @id getenv-to-url
*/
import go
class GetenvSource extends DataFlow::CallNode {
GetenvSource() {
exists(Function m | m = this.getTarget() |
m.hasQualifiedName("os", "Getenv")
)
}
}
module GetenvToURLConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source instanceof GetenvSource
}
predicate isSink(DataFlow::Node sink) {
exists(Function urlParse, CallExpr call |
(
urlParse.hasQualifiedName("url", "Parse") or
urlParse.hasQualifiedName("url", "ParseRequestURI")
) and
call.getTarget() = urlParse and
sink.asExpr() = call.getArgument(0)
)
}
}
module GetenvToURLFlow = DataFlow::Global<GetenvToURLConfig>;
import GetenvToURLFlow::PathGraph
from GetenvToURLFlow::PathNode src, GetenvToURLFlow::PathNode sink
where GetenvToURLFlow::flowPath(src, sink)
select src.getNode(), src, sink, "This environment variable constructs a URL $@.", sink, "here"
Further reading
---------------

View File

@@ -361,6 +361,52 @@ Exercise 4
where GetenvToURLFlow::flow(src, sink)
select src, "This environment variable constructs a URL $@.", sink, "here"
Path Query Example
~~~~~~~~~~~~~~~~~~
Here is the answer to exercise 4 above, converted into a path query:
.. code-block:: ql
/**
* @kind path-problem
* @problem.severity warning
* @id getenv-to-url
*/
import java
import semmle.code.java.dataflow.DataFlow
class GetenvSource extends DataFlow::ExprNode {
GetenvSource() {
exists(Method m | m = this.asExpr().(MethodCall).getMethod() |
m.hasName("getenv") and
m.getDeclaringType() instanceof TypeSystem
)
}
}
module GetenvToURLConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source instanceof GetenvSource
}
predicate isSink(DataFlow::Node sink) {
exists(Call call |
sink.asExpr() = call.getArgument(0) and
call.getCallee().(Constructor).getDeclaringType().hasQualifiedName("java.net", "URL")
)
}
}
module GetenvToURLFlow = DataFlow::Global<GetenvToURLConfig>;
import GetenvToURLFlow::PathGraph
from GetenvToURLFlow::PathNode src, GetenvToURLFlow::PathNode sink
where GetenvToURLFlow::flowPath(src, sink)
select src.getNode(), src, sink, "This environment variable constructs a URL $@.", sink, "here"
Further reading
---------------

View File

@@ -541,6 +541,46 @@ Exercise 4
where HardCodedTagNameFlow::flow(source, sink)
select source, sink
Path Query Example
~~~~~~~~~~~~~~~~~~
Here is the answer to exercise 4 above, converted into a path query:
.. code-block:: ql
/**
* @kind path-problem
* @problem.severity warning
* @id hard-coded-tag-name
*/
import javascript
class ArrayEntryCallResult extends DataFlow::Node {
ArrayEntryCallResult() {
exists(DataFlow::CallNode call, string index |
this = call.getAPropertyRead(index) and
index.regexpMatch("\\d+")
)
}
}
module HardCodedTagNameConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof ArrayEntryCallResult }
predicate isSink(DataFlow::Node sink) {
sink = DataFlow::globalVarRef("document").getAMethodCall("createElement").getArgument(0)
}
}
module HardCodedTagNameFlow = DataFlow::Global<HardCodedTagNameConfig>;
import HardCodedTagNameFlow::PathGraph
from HardCodedTagNameFlow::PathNode source, HardCodedTagNameFlow::PathNode sink
where HardCodedTagNameFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Hard-coded tag name $@.", source, "here"
Further reading
---------------

View File

@@ -372,6 +372,43 @@ The following global data-flow query finds calls to ``File.open`` where the file
select fileOpen, "This call to 'File.open' uses data from $@.", environment,
"an environment variable"
Path Query Example
~~~~~~~~~~~~~~~~~~
Here is the first example above, converted into a path query:
.. code-block:: ql
/**
* @kind path-problem
* @problem.severity warning
* @id file-system-access-from-remote-input
*/
import codeql.ruby.DataFlow
import codeql.ruby.TaintTracking
import codeql.ruby.Concepts
import codeql.ruby.dataflow.RemoteFlowSources
module RemoteToFileConfiguration implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) {
sink = any(FileSystemAccess fa).getAPathArgument()
}
}
module RemoteToFileFlow = TaintTracking::Global<RemoteToFileConfiguration>;
import RemoteToFileFlow::PathGraph
from RemoteToFileFlow::PathNode input, RemoteToFileFlow::PathNode fileAccess
where RemoteToFileFlow::flowPath(input, fileAccess)
select fileAccess.getNode(), input, fileAccess, "This file access uses data from $@.",
input, "user-controllable input."
For more information, see "`Creating path queries <https://codeql.github.com/docs/writing-codeql-queries/creating-path-queries/>`__".
Further reading
---------------

View File

@@ -231,6 +231,46 @@ The following global taint-tracking query finds places where a string literal is
where ConstantPasswordFlow::flow(sourceNode, sinkNode)
select sinkNode, "The value $@ is used as a constant password.", sourceNode, sourceNode.toString()
Path Query Example
~~~~~~~~~~~~~~~~~~
Here is the first example above, converted into a path query:
.. code-block:: ql
/**
* @kind path-problem
* @problem.severity warning
* @id constant-password
*/
import rust
import codeql.rust.dataflow.DataFlow
import codeql.rust.dataflow.TaintTracking
module ConstantPasswordConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { node.asExpr().getExpr() instanceof StringLiteralExpr }
predicate isSink(DataFlow::Node node) {
// any argument going to a parameter called `password`
exists(Function f, CallExpr call, int index |
call.getArg(index) = node.asExpr().getExpr() and
call.getStaticTarget() = f and
f.getParam(index).getPat().(IdentPat).getName().getText() = "password"
)
}
}
module ConstantPasswordFlow = TaintTracking::Global<ConstantPasswordConfig>;
import ConstantPasswordFlow::PathGraph
from ConstantPasswordFlow::PathNode sourceNode, ConstantPasswordFlow::PathNode sinkNode
where ConstantPasswordFlow::flowPath(sourceNode, sinkNode)
select sinkNode.getNode(), sourceNode, sinkNode, "The value $@ is used as a constant password.", sourceNode, sourceNode.toString()
For more information, see "`Creating path queries <https://codeql.github.com/docs/writing-codeql-queries/creating-path-queries/>`__".
Further reading
---------------

View File

@@ -278,6 +278,45 @@ The following global taint-tracking query finds places where a value from a remo
where SqlInjectionFlow::flow(sourceNode, sinkNode)
select sinkNode, "This query depends on a $@.", sourceNode, "user-provided value"
Path Query Example
~~~~~~~~~~~~~~~~~~
Here is the first example above, converted into a path query:
.. code-block:: ql
/**
* @kind path-problem
* @problem.severity warning
* @id sql-injection
*/
import swift
import codeql.swift.dataflow.DataFlow
import codeql.swift.dataflow.TaintTracking
import codeql.swift.dataflow.FlowSources
module SqlInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { node instanceof FlowSource }
predicate isSink(DataFlow::Node node) {
exists(CallExpr call |
call.getStaticTarget().(Method).hasQualifiedName("Connection", "execute(_:)") and
call.getArgument(0).getExpr() = node.asExpr()
)
}
}
module SqlInjectionFlow = TaintTracking::Global<SqlInjectionConfig>;
import SqlInjectionFlow::PathGraph
from SqlInjectionFlow::PathNode sourceNode, SqlInjectionFlow::PathNode sinkNode
where SqlInjectionFlow::flowPath(sourceNode, sinkNode)
select sinkNode.getNode(), sourceNode, sinkNode, "This query depends on a $@.", sourceNode, "user-provided value"
For more information, see "`Creating path queries <https://codeql.github.com/docs/writing-codeql-queries/creating-path-queries/>`__".
Further reading
---------------