Skip to content

Commit bf8c7a2

Browse files
committed
Added Sanitizer Guard
1 parent e11c74c commit bf8c7a2

File tree

3 files changed

+20
-6
lines changed

3 files changed

+20
-6
lines changed

python/ql/src/experimental/Security/CWE-1236/CsvInjection.qhelp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<overview>
66
<p>CSV Injection, also known as Formula Injection, occurs when websites embed untrusted input inside CSV files.</p>
77
<p>When a CSV format file is opened with a spreadsheet program such as Microsoft Excel or LibreOffice Calc.
8-
this software interprets entries beginning with <code>=</code> as formulas. may attempt information exfiltration
8+
this software interprets entries beginning with <code>=</code> as formulas, which may attempt information exfiltration
99
or other malicious activity when automatically executed by the spreadsheet software.</p>
1010
</overview>
1111
<recommendation>
@@ -18,7 +18,7 @@ Risky characters include <code>=</code>(equal), <code>+</code>(plus), <code>-</c
1818

1919
<p>The following examples show the bad case and the good case respectively.
2020
In <code>bad1</code> method, the data provided by the user is directly stored in the CSV file, which may be attacked.
21-
But in the <code>good1</code> method,, the program will check the data provided by the user, and process the data starting with <code>=</code>(equal), <code>+</code>(plus), <code>-</code>(minus), and <code>@</code>(at) characters safely.</p>
21+
But in the <code>good1</code> method, the program will check the data provided by the user, and process the data starting with <code>=</code>(equal), <code>+</code>(plus), <code>-</code>(minus), and <code>@</code>(at) characters safely.</p>
2222

2323
<sample src="CsvInjection.py" />
2424

python/ql/src/experimental/semmle/python/Concepts.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,9 @@ class CsvWriter extends DataFlow::Node {
294294

295295
CsvWriter() { this = range }
296296

297+
/**
298+
* Get the parameter value of the csv writer function.
299+
*/
297300
DataFlow::Node getAnInput() { result = range.getAnInput() }
298301
}
299302

python/ql/src/experimental/semmle/python/security/injection/CsvInjection.qll

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import python
22
import experimental.semmle.python.Concepts
33
import semmle.python.dataflow.new.DataFlow
44
import semmle.python.dataflow.new.TaintTracking
5+
import semmle.python.dataflow.new.BarrierGuards
56
import semmle.python.dataflow.new.RemoteFlowSources
67

78
/**
@@ -10,11 +11,21 @@ import semmle.python.dataflow.new.RemoteFlowSources
1011
class CsvInjectionFlowConfig extends TaintTracking::Configuration {
1112
CsvInjectionFlowConfig() { this = "CsvInjectionFlowConfig" }
1213

13-
override predicate isSource(DataFlow::Node source) {
14-
source instanceof RemoteFlowSource
14+
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
15+
16+
override predicate isSink(DataFlow::Node sink) { sink = any(CsvWriter cw).getAnInput() }
17+
18+
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
19+
guard instanceof StartsWithCheck or
20+
guard instanceof StringConstCompare
1521
}
22+
}
23+
24+
class StartsWithCheck extends DataFlow::BarrierGuard {
25+
StartsWithCheck() { this.(CallNode).getNode().getFunc().(Attribute).getName() = "startswith" }
1626

17-
override predicate isSink(DataFlow::Node sink) {
18-
exists(CsvWriter csvwriter | sink = csvwriter.getAnInput())
27+
override predicate checks(ControlFlowNode node, boolean branch) {
28+
node = this.(CallNode).getNode().getFunc().(Attribute).getObject().getAFlowNode() and
29+
branch = true
1930
}
2031
}

0 commit comments

Comments
 (0)