Skip to content

Commit 7ad63fc

Browse files
committed
Convert sqlx sql-injection sinks to MaD
1 parent db559f7 commit 7ad63fc

File tree

7 files changed

+92
-42
lines changed

7 files changed

+92
-42
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
extensions:
2+
- addsTo:
3+
pack: codeql/go-all
4+
extensible: sinkModel
5+
data:
6+
- ["github.com/jmoiron/sqlx", "DB", True, "Get", "", "", "Argument[1]", "sql-injection", "manual"]
7+
- ["github.com/jmoiron/sqlx", "DB", True, "MustExec", "", "", "Argument[0]", "sql-injection", "manual"]
8+
- ["github.com/jmoiron/sqlx", "DB", True, "NamedExec", "", "", "Argument[0]", "sql-injection", "manual"]
9+
- ["github.com/jmoiron/sqlx", "DB", True, "NamedQuery", "", "", "Argument[0]", "sql-injection", "manual"]
10+
- ["github.com/jmoiron/sqlx", "DB", True, "Queryx", "", "", "Argument[0]", "sql-injection", "manual"]
11+
- ["github.com/jmoiron/sqlx", "DB", True, "Select", "", "", "Argument[1]", "sql-injection", "manual"]
12+
- ["github.com/jmoiron/sqlx", "Tx", True, "Get", "", "", "Argument[1]", "sql-injection", "manual"]
13+
- ["github.com/jmoiron/sqlx", "Tx", True, "MustExec", "", "", "Argument[0]", "sql-injection", "manual"]
14+
- ["github.com/jmoiron/sqlx", "Tx", True, "NamedExec", "", "", "Argument[0]", "sql-injection", "manual"]
15+
- ["github.com/jmoiron/sqlx", "Tx", True, "NamedQuery", "", "", "Argument[0]", "sql-injection", "manual"]
16+
- ["github.com/jmoiron/sqlx", "Tx", True, "Queryx", "", "", "Argument[0]", "sql-injection", "manual"]
17+
- ["github.com/jmoiron/sqlx", "Tx", True, "Select", "", "", "Argument[1]", "sql-injection", "manual"]

go/ql/lib/semmle/go/frameworks/SQL.qll

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -165,20 +165,6 @@ module SQL {
165165
)
166166
}
167167
}
168-
169-
/** A model for sinks of github.com/jmoiron/sqlx. */
170-
private class SqlxSink extends SQL::QueryString::Range {
171-
SqlxSink() {
172-
exists(Method meth, string name, int n |
173-
meth.hasQualifiedName(package("github.com/jmoiron/sqlx", ""), ["DB", "Tx"], name) and
174-
this = meth.getACall().getArgument(n)
175-
|
176-
name = ["Select", "Get"] and n = 1
177-
or
178-
name = ["MustExec", "Queryx", "NamedExec", "NamedQuery"] and n = 0
179-
)
180-
}
181-
}
182168
}
183169

184170
/**
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
testFailures
2+
invalidModelRow
3+
failures
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import go
2+
import semmle.go.dataflow.ExternalFlow
3+
import ModelValidation
4+
import TestUtilities.InlineExpectationsTest
5+
6+
module SqlTest implements TestSig {
7+
string getARelevantTag() { result = "query" }
8+
9+
predicate hasActualResult(Location location, string element, string tag, string value) {
10+
tag = "query" and
11+
exists(SQL::Query q, SQL::QueryString qs | qs = q.getAQueryString() |
12+
q.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
13+
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and
14+
element = q.toString() and
15+
value = qs.toString()
16+
)
17+
}
18+
}
19+
20+
module QueryString implements TestSig {
21+
string getARelevantTag() { result = "querystring" }
22+
23+
predicate hasActualResult(Location location, string element, string tag, string value) {
24+
tag = "querystring" and
25+
element = "" and
26+
exists(SQL::QueryString qs | not exists(SQL::Query q | qs = q.getAQueryString()) |
27+
qs.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
28+
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and
29+
value = qs.toString()
30+
)
31+
}
32+
}
33+
34+
module Config implements DataFlow::ConfigSig {
35+
predicate isSource(DataFlow::Node n) { n.asExpr() instanceof StringLit }
36+
37+
predicate isSink(DataFlow::Node n) {
38+
n = any(DataFlow::CallNode cn | cn.getTarget().getName() = "sink").getAnArgument()
39+
}
40+
}
41+
42+
module Flow = TaintTracking::Global<Config>;
43+
44+
module TaintFlow implements TestSig {
45+
string getARelevantTag() { result = "flowfrom" }
46+
47+
predicate hasActualResult(Location location, string element, string tag, string value) {
48+
tag = "flowfrom" and
49+
element = "" and
50+
exists(DataFlow::Node fromNode, DataFlow::Node toNode |
51+
toNode
52+
.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
53+
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and
54+
Flow::flow(fromNode, toNode) and
55+
value = fromNode.asExpr().(StringLit).getValue()
56+
)
57+
}
58+
}
59+
60+
import MakeTest<MergeTests3<SqlTest, QueryString, TaintFlow>>

go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/sqlx.expected

Lines changed: 0 additions & 12 deletions
This file was deleted.

go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/sqlx.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,19 @@ func main() {
1212

1313
db := sqlx.DB{}
1414
untrusted := getUntrustedString()
15-
db.Select(nil, untrusted)
16-
db.Get(nil, untrusted)
17-
db.MustExec(untrusted)
18-
db.Queryx(untrusted)
19-
db.NamedExec(untrusted, nil)
20-
db.NamedQuery(untrusted, nil)
15+
db.Select(nil, untrusted) // $ querystring=untrusted
16+
db.Get(nil, untrusted) // $ querystring=untrusted
17+
db.MustExec(untrusted) // $ querystring=untrusted
18+
db.Queryx(untrusted) // $ querystring=untrusted
19+
db.NamedExec(untrusted, nil) // $ querystring=untrusted
20+
db.NamedQuery(untrusted, nil) // $ querystring=untrusted
2121

2222
tx := sqlx.Tx{}
23-
tx.Select(nil, untrusted)
24-
tx.Get(nil, untrusted)
25-
tx.MustExec(untrusted)
26-
tx.Queryx(untrusted)
27-
tx.NamedExec(untrusted, nil)
28-
tx.NamedQuery(untrusted, nil)
23+
tx.Select(nil, untrusted) // $ querystring=untrusted
24+
tx.Get(nil, untrusted) // $ querystring=untrusted
25+
tx.MustExec(untrusted) // $ querystring=untrusted
26+
tx.Queryx(untrusted) // $ querystring=untrusted
27+
tx.NamedExec(untrusted, nil) // $ querystring=untrusted
28+
tx.NamedQuery(untrusted, nil) // $ querystring=untrusted
2929

3030
}

go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/sqlx.ql

Lines changed: 0 additions & 4 deletions
This file was deleted.

0 commit comments

Comments
 (0)