Skip to content

Commit 47f5c97

Browse files
committed
Python: Port py/stack-trace-exposure to use proper source/sink customization
1 parent 934007c commit 47f5c97

File tree

3 files changed

+91
-21
lines changed

3 files changed

+91
-21
lines changed

python/ql/src/Security/CWE-209/StackTraceExposure.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import python
1717
import semmle.python.security.dataflow.StackTraceExposure
1818
import DataFlow::PathGraph
1919

20-
from StackTraceExposureConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink
20+
from StackTraceExposure::Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
2121
where config.hasFlowPath(source, sink)
2222
select sink.getNode(), source, sink, "$@ may be exposed to an external user", source.getNode(),
2323
"Error information"
Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,51 @@
11
/**
2-
* Provides a taint-tracking configuration for detecting stack trace exposure
3-
* vulnerabilities.
2+
* Provides a taint-tracking configuration for detecting "stack trace exposure" vulnerabilities.
3+
*
4+
* Note, for performance reasons: only import this file if
5+
* `StackTraceExposure::Configuration` is needed, otherwise
6+
* `StackTraceExposureCustomizations` should be imported instead.
47
*/
58

6-
import python
9+
private import python
710
import semmle.python.dataflow.new.DataFlow
811
import semmle.python.dataflow.new.TaintTracking
9-
import semmle.python.Concepts
10-
import semmle.python.dataflow.new.internal.Attributes
11-
private import ExceptionInfo
1212

1313
/**
14-
* A taint-tracking configuration for detecting stack trace exposure.
14+
* Provides a taint-tracking configuration for detecting "stack trace exposure" vulnerabilities.
1515
*/
16-
class StackTraceExposureConfiguration extends TaintTracking::Configuration {
17-
StackTraceExposureConfiguration() { this = "StackTraceExposureConfiguration" }
16+
module StackTraceExposure {
17+
import StackTraceExposureCustomizations::StackTraceExposure
1818

19-
override predicate isSource(DataFlow::Node source) { source instanceof ExceptionInfo }
19+
/**
20+
* A taint-tracking configuration for detecting "stack trace exposure" vulnerabilities.
21+
*/
22+
class Configuration extends TaintTracking::Configuration {
23+
Configuration() { this = "StackTraceExposure" }
2024

21-
override predicate isSink(DataFlow::Node sink) {
22-
sink = any(HTTP::Server::HttpResponse response).getBody()
23-
}
25+
override predicate isSource(DataFlow::Node source) { source instanceof Source }
26+
27+
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
28+
29+
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
30+
31+
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
32+
guard instanceof SanitizerGuard
33+
}
2434

25-
// A stack trace is accessible as the `__traceback__` attribute of a caught exception.
26-
// seehttps://docs.python.org/3/reference/datamodel.html#traceback-objects
27-
override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
28-
exists(AttrRead attr | attr.getAttributeName() = "__traceback__" |
29-
nodeFrom = attr.getObject() and
30-
nodeTo = attr
31-
)
35+
// A stack trace is accessible as the `__traceback__` attribute of a caught exception.
36+
// seehttps://docs.python.org/3/reference/datamodel.html#traceback-objects
37+
override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
38+
exists(DataFlow::AttrRead attr | attr.getAttributeName() = "__traceback__" |
39+
nodeFrom = attr.getObject() and
40+
nodeTo = attr
41+
)
42+
}
3243
}
3344
}
45+
46+
/**
47+
* DEPRECATED: Don't extend this class for customization, since this will lead to bad
48+
* performance, instead use the new `StackTraceExposureCustomizations.qll` file, and extend
49+
* its' classes.
50+
*/
51+
deprecated class StackTraceExposureConfiguration = StackTraceExposure::Configuration;
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/**
2+
* Provides default sources, sinks and sanitizers for detecting
3+
* "stack trace exposure"
4+
* vulnerabilities, as well as extension points for adding your own.
5+
*/
6+
7+
private import python
8+
private import semmle.python.dataflow.new.DataFlow
9+
private import semmle.python.Concepts
10+
private import semmle.python.dataflow.new.BarrierGuards
11+
private import ExceptionInfo
12+
13+
/**
14+
* Provides default sources, sinks and sanitizers for detecting
15+
* "stack trace exposure"
16+
* vulnerabilities, as well as extension points for adding your own.
17+
*/
18+
module StackTraceExposure {
19+
/**
20+
* A data flow source for "stack trace exposure" vulnerabilities.
21+
*/
22+
abstract class Source extends DataFlow::Node { }
23+
24+
/**
25+
* A data flow sink for "stack trace exposure" vulnerabilities.
26+
*/
27+
abstract class Sink extends DataFlow::Node { }
28+
29+
/**
30+
* A sanitizer for "stack trace exposure" vulnerabilities.
31+
*/
32+
abstract class Sanitizer extends DataFlow::Node { }
33+
34+
/**
35+
* A sanitizer guard for "stack trace exposure" vulnerabilities.
36+
*/
37+
abstract class SanitizerGuard extends DataFlow::BarrierGuard { }
38+
39+
/**
40+
* A source of exception info, considered as a flow source.
41+
*/
42+
class ExceptionInfoAsSource extends Source {
43+
ExceptionInfoAsSource() { this instanceof ExceptionInfo }
44+
}
45+
46+
/**
47+
* The body of a HTTP response that will be returned from a server, considered as a flow sink.
48+
*/
49+
class ServerHttpResponseBodyAsSink extends Sink {
50+
ServerHttpResponseBodyAsSink() { this = any(HTTP::Server::HttpResponse response).getBody() }
51+
}
52+
}

0 commit comments

Comments
 (0)