Skip to content

Commit 4e5a865

Browse files
committed
Manually fix copilot's mistakes and get query working
1 parent ce4be6d commit 4e5a865

File tree

2 files changed

+63
-82
lines changed

2 files changed

+63
-82
lines changed

go/ql/src/Security/CWE-079/HTMLTemplateEscapingPassthrough.ql

Lines changed: 44 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -36,69 +36,75 @@ predicate isSinkToTemplateExec(DataFlow::Node sink, DataFlow::CallNode call) {
3636
}
3737

3838
/**
39-
* Flow state for tracking whether a conversion to a passthrough type has occurred.
39+
* Data flow configuration that tracks flows from untrusted sources (A) to template execution calls (C),
40+
* and tracks whether a conversion to a passthrough type (B) has occurred.
4041
*/
41-
class FlowState extends int {
42-
FlowState() { this = 0 or this = 1 }
42+
module UntrustedToTemplateExecWithConversionConfig implements DataFlow::StateConfigSig {
43+
private newtype TConversionState =
44+
TUnconverted() or
45+
TConverted(PassthroughTypeName x)
4346

44-
predicate isBeforeConversion() { this = 0 }
47+
/**
48+
* Flow state for tracking whether a conversion to a passthrough type has occurred.
49+
*/
50+
class FlowState extends TConversionState {
51+
predicate isBeforeConversion() { this instanceof TUnconverted }
4552

46-
predicate isAfterConversion() { this = 1 }
47-
}
53+
predicate isAfterConversion(PassthroughTypeName x) { this = TConverted(x) }
54+
55+
/** Gets a textual representation of this element. */
56+
string toString() {
57+
this.isBeforeConversion() and result = "Unconverted"
58+
or
59+
exists(PassthroughTypeName x | this.isAfterConversion(x) |
60+
result = "Converted to template." + x
61+
)
62+
}
63+
}
4864

49-
/**
50-
* Data flow configuration that tracks flows from untrusted sources (A) to template execution calls (C),
51-
* and tracks whether a conversion to a passthrough type (B) has occurred.
52-
*/
53-
module UntrustedToTemplateExecWithConversionConfig implements DataFlow::ConfigSig {
5465
predicate isSource(DataFlow::Node source, FlowState state) {
5566
state.isBeforeConversion() and source instanceof ActiveThreatModelSource
5667
}
5768

5869
predicate isSink(DataFlow::Node sink, FlowState state) {
59-
state.isAfterConversion() and isSinkToTemplateExec(sink, _)
70+
state.isAfterConversion(_) and isSinkToTemplateExec(sink, _)
6071
}
6172

62-
predicate isBarrier(DataFlow::Node node, FlowState state) {
63-
node instanceof SharedXss::Sanitizer or node.getType() instanceof NumericType
73+
predicate isBarrier(DataFlow::Node node) {
74+
node instanceof SharedXss::Sanitizer and not node instanceof SharedXss::HtmlTemplateSanitizer
75+
or
76+
node.getType() instanceof NumericType
6477
}
6578

6679
/**
6780
* When a conversion to a passthrough type is encountered, transition the flow state.
6881
*/
69-
predicate step(DataFlow::Node pred, FlowState predState, DataFlow::Node succ, FlowState succState) {
70-
// If not yet converted, look for a conversion to a passthrough type
71-
predState.isBeforeConversion() and
72-
succState.isAfterConversion() and
73-
pred = succ and
74-
exists(Type typ, PassthroughTypeName name |
75-
typ = pred.getType() and
76-
typ.getUnderlyingType*().hasQualifiedName("html/template", name)
82+
predicate isAdditionalFlowStep(
83+
DataFlow::Node pred, FlowState predState, DataFlow::Node succ, FlowState succState
84+
) {
85+
exists(ConversionExpr conversion, PassthroughTypeName name |
86+
// If not yet converted, look for a conversion to a passthrough type
87+
predState.isBeforeConversion() and
88+
succState.isAfterConversion(name) and
89+
succ.(DataFlow::TypeCastNode).getExpr() = conversion and
90+
pred.asExpr() = conversion.getOperand() and
91+
conversion.getType().getUnderlyingType*().hasQualifiedName("html/template", name)
7792
)
78-
or
79-
// Otherwise, normal flow with unchanged state
80-
predState = succState
8193
}
8294
}
8395

8496
module UntrustedToTemplateExecWithConversionFlow =
85-
DataFlow::PathGraph<UntrustedToTemplateExecWithConversionConfig>;
97+
TaintTracking::GlobalWithState<UntrustedToTemplateExecWithConversionConfig>;
98+
99+
import UntrustedToTemplateExecWithConversionFlow::PathGraph
86100

87101
from
88102
UntrustedToTemplateExecWithConversionFlow::PathNode untrustedSource,
89-
UntrustedToTemplateExecWithConversionFlow::PathNode templateExecCall, DataFlow::Node conversion,
103+
UntrustedToTemplateExecWithConversionFlow::PathNode templateExecCall,
90104
PassthroughTypeName targetTypeName
91105
where
92106
UntrustedToTemplateExecWithConversionFlow::flowPath(untrustedSource, templateExecCall) and
93-
// Find the conversion node in the path
94-
exists(int i |
95-
i = templateExecCall.getPathIndex() - 1 and
96-
conversion = templateExecCall.getPathNode(i).getNode() and
97-
exists(Type typ |
98-
typ = conversion.getType() and
99-
typ.getUnderlyingType*().hasQualifiedName("html/template", targetTypeName)
100-
)
101-
)
107+
templateExecCall.getState().isAfterConversion(targetTypeName)
102108
select templateExecCall.getNode(), untrustedSource, templateExecCall,
103-
"Data from an $@ will not be auto-escaped because it was $@ to template." + targetTypeName,
104-
untrustedSource.getNode(), "untrusted source", conversion, "converted"
109+
"Data from an $@ will not be auto-escaped because it was converted to template." + targetTypeName,
110+
untrustedSource.getNode(), "untrusted source"
Lines changed: 19 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,34 @@
11
#select
2-
| HTMLTemplateEscapingPassthrough.go:30:39:30:39 | a | HTMLTemplateEscapingPassthrough.go:29:26:29:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:30:39:30:39 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:29:26:29:40 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:29:12:29:41 | type conversion | converted |
3-
| HTMLTemplateEscapingPassthrough.go:36:40:36:40 | a | HTMLTemplateEscapingPassthrough.go:35:23:35:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:36:40:36:40 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:35:23:35:37 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:35:9:35:38 | type conversion | converted |
4-
| HTMLTemplateEscapingPassthrough.go:41:40:41:40 | a | HTMLTemplateEscapingPassthrough.go:40:19:40:33 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:41:40:41:40 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:40:19:40:33 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:40:9:40:34 | type conversion | converted |
5-
| HTMLTemplateEscapingPassthrough.go:47:41:47:41 | c | HTMLTemplateEscapingPassthrough.go:46:29:46:43 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:47:41:47:41 | c | Data from an $@ will not be auto-escaped because it was $@ to template.HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:29:46:43 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:46:11:46:44 | type conversion | converted |
6-
| HTMLTemplateEscapingPassthrough.go:51:44:51:44 | d | HTMLTemplateEscapingPassthrough.go:50:23:50:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:51:44:51:44 | d | Data from an $@ will not be auto-escaped because it was $@ to template.JS | HTMLTemplateEscapingPassthrough.go:50:23:50:37 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:50:11:50:38 | type conversion | converted |
7-
| HTMLTemplateEscapingPassthrough.go:55:44:55:44 | e | HTMLTemplateEscapingPassthrough.go:54:26:54:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:55:44:55:44 | e | Data from an $@ will not be auto-escaped because it was $@ to template.JSStr | HTMLTemplateEscapingPassthrough.go:54:26:54:40 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:54:11:54:41 | type conversion | converted |
8-
| HTMLTemplateEscapingPassthrough.go:59:38:59:38 | b | HTMLTemplateEscapingPassthrough.go:58:24:58:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:59:38:59:38 | b | Data from an $@ will not be auto-escaped because it was $@ to template.CSS | HTMLTemplateEscapingPassthrough.go:58:24:58:38 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:58:11:58:39 | type conversion | converted |
9-
| HTMLTemplateEscapingPassthrough.go:63:44:63:44 | f | HTMLTemplateEscapingPassthrough.go:62:27:62:41 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:63:44:63:44 | f | Data from an $@ will not be auto-escaped because it was $@ to template.Srcset | HTMLTemplateEscapingPassthrough.go:62:27:62:41 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:62:11:62:42 | type conversion | converted |
10-
| HTMLTemplateEscapingPassthrough.go:67:38:67:38 | g | HTMLTemplateEscapingPassthrough.go:66:24:66:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:67:38:67:38 | g | Data from an $@ will not be auto-escaped because it was $@ to template.URL | HTMLTemplateEscapingPassthrough.go:66:24:66:38 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:66:11:66:39 | type conversion | converted |
2+
| HTMLTemplateEscapingPassthrough.go:30:39:30:39 | a | HTMLTemplateEscapingPassthrough.go:29:26:29:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:30:39:30:39 | a | Data from an $@ will not be auto-escaped because it was converted to template.HTML | HTMLTemplateEscapingPassthrough.go:29:26:29:40 | call to UserAgent | untrusted source |
3+
| HTMLTemplateEscapingPassthrough.go:36:40:36:40 | a | HTMLTemplateEscapingPassthrough.go:35:23:35:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:36:40:36:40 | a | Data from an $@ will not be auto-escaped because it was converted to template.HTML | HTMLTemplateEscapingPassthrough.go:35:23:35:37 | call to UserAgent | untrusted source |
4+
| HTMLTemplateEscapingPassthrough.go:41:40:41:40 | a | HTMLTemplateEscapingPassthrough.go:40:19:40:33 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:41:40:41:40 | a | Data from an $@ will not be auto-escaped because it was converted to template.HTML | HTMLTemplateEscapingPassthrough.go:40:19:40:33 | call to UserAgent | untrusted source |
5+
| HTMLTemplateEscapingPassthrough.go:47:41:47:41 | c | HTMLTemplateEscapingPassthrough.go:46:29:46:43 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:47:41:47:41 | c | Data from an $@ will not be auto-escaped because it was converted to template.HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:29:46:43 | call to UserAgent | untrusted source |
6+
| HTMLTemplateEscapingPassthrough.go:51:44:51:44 | d | HTMLTemplateEscapingPassthrough.go:50:23:50:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:51:44:51:44 | d | Data from an $@ will not be auto-escaped because it was converted to template.JS | HTMLTemplateEscapingPassthrough.go:50:23:50:37 | call to UserAgent | untrusted source |
7+
| HTMLTemplateEscapingPassthrough.go:55:44:55:44 | e | HTMLTemplateEscapingPassthrough.go:54:26:54:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:55:44:55:44 | e | Data from an $@ will not be auto-escaped because it was converted to template.JSStr | HTMLTemplateEscapingPassthrough.go:54:26:54:40 | call to UserAgent | untrusted source |
8+
| HTMLTemplateEscapingPassthrough.go:59:38:59:38 | b | HTMLTemplateEscapingPassthrough.go:58:24:58:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:59:38:59:38 | b | Data from an $@ will not be auto-escaped because it was converted to template.CSS | HTMLTemplateEscapingPassthrough.go:58:24:58:38 | call to UserAgent | untrusted source |
9+
| HTMLTemplateEscapingPassthrough.go:63:44:63:44 | f | HTMLTemplateEscapingPassthrough.go:62:27:62:41 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:63:44:63:44 | f | Data from an $@ will not be auto-escaped because it was converted to template.Srcset | HTMLTemplateEscapingPassthrough.go:62:27:62:41 | call to UserAgent | untrusted source |
10+
| HTMLTemplateEscapingPassthrough.go:67:38:67:38 | g | HTMLTemplateEscapingPassthrough.go:66:24:66:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:67:38:67:38 | g | Data from an $@ will not be auto-escaped because it was converted to template.URL | HTMLTemplateEscapingPassthrough.go:66:24:66:38 | call to UserAgent | untrusted source |
1111
edges
1212
| HTMLTemplateEscapingPassthrough.go:29:12:29:41 | type conversion | HTMLTemplateEscapingPassthrough.go:30:39:30:39 | a | provenance | |
13-
| HTMLTemplateEscapingPassthrough.go:29:26:29:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:29:12:29:41 | type conversion | provenance | Src:MaD:2 |
13+
| HTMLTemplateEscapingPassthrough.go:29:26:29:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:29:12:29:41 | type conversion | provenance | Src:MaD:1 Config |
1414
| HTMLTemplateEscapingPassthrough.go:35:9:35:38 | type conversion | HTMLTemplateEscapingPassthrough.go:36:40:36:40 | a | provenance | |
15-
| HTMLTemplateEscapingPassthrough.go:35:23:35:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:35:9:35:38 | type conversion | provenance | Src:MaD:2 |
15+
| HTMLTemplateEscapingPassthrough.go:35:23:35:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:35:9:35:38 | type conversion | provenance | Src:MaD:1 Config |
1616
| HTMLTemplateEscapingPassthrough.go:40:9:40:34 | type conversion | HTMLTemplateEscapingPassthrough.go:41:40:41:40 | a | provenance | |
17-
| HTMLTemplateEscapingPassthrough.go:40:19:40:33 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:40:9:40:34 | type conversion | provenance | Src:MaD:2 |
17+
| HTMLTemplateEscapingPassthrough.go:40:19:40:33 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:40:9:40:34 | type conversion | provenance | Src:MaD:1 Config |
1818
| HTMLTemplateEscapingPassthrough.go:46:11:46:44 | type conversion | HTMLTemplateEscapingPassthrough.go:47:41:47:41 | c | provenance | |
19-
| HTMLTemplateEscapingPassthrough.go:46:29:46:43 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:46:11:46:44 | type conversion | provenance | Src:MaD:2 |
19+
| HTMLTemplateEscapingPassthrough.go:46:29:46:43 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:46:11:46:44 | type conversion | provenance | Src:MaD:1 Config |
2020
| HTMLTemplateEscapingPassthrough.go:50:11:50:38 | type conversion | HTMLTemplateEscapingPassthrough.go:51:44:51:44 | d | provenance | |
21-
| HTMLTemplateEscapingPassthrough.go:50:23:50:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:50:11:50:38 | type conversion | provenance | Src:MaD:2 |
21+
| HTMLTemplateEscapingPassthrough.go:50:23:50:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:50:11:50:38 | type conversion | provenance | Src:MaD:1 Config |
2222
| HTMLTemplateEscapingPassthrough.go:54:11:54:41 | type conversion | HTMLTemplateEscapingPassthrough.go:55:44:55:44 | e | provenance | |
23-
| HTMLTemplateEscapingPassthrough.go:54:26:54:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:54:11:54:41 | type conversion | provenance | Src:MaD:2 |
23+
| HTMLTemplateEscapingPassthrough.go:54:26:54:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:54:11:54:41 | type conversion | provenance | Src:MaD:1 Config |
2424
| HTMLTemplateEscapingPassthrough.go:58:11:58:39 | type conversion | HTMLTemplateEscapingPassthrough.go:59:38:59:38 | b | provenance | |
25-
| HTMLTemplateEscapingPassthrough.go:58:24:58:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:58:11:58:39 | type conversion | provenance | Src:MaD:2 |
25+
| HTMLTemplateEscapingPassthrough.go:58:24:58:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:58:11:58:39 | type conversion | provenance | Src:MaD:1 Config |
2626
| HTMLTemplateEscapingPassthrough.go:62:11:62:42 | type conversion | HTMLTemplateEscapingPassthrough.go:63:44:63:44 | f | provenance | |
27-
| HTMLTemplateEscapingPassthrough.go:62:27:62:41 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:62:11:62:42 | type conversion | provenance | Src:MaD:2 |
27+
| HTMLTemplateEscapingPassthrough.go:62:27:62:41 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:62:11:62:42 | type conversion | provenance | Src:MaD:1 Config |
2828
| HTMLTemplateEscapingPassthrough.go:66:11:66:39 | type conversion | HTMLTemplateEscapingPassthrough.go:67:38:67:38 | g | provenance | |
29-
| HTMLTemplateEscapingPassthrough.go:66:24:66:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:66:11:66:39 | type conversion | provenance | Src:MaD:2 |
30-
| HTMLTemplateEscapingPassthrough.go:75:17:75:31 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:76:38:76:44 | escaped | provenance | Src:MaD:2 |
31-
| HTMLTemplateEscapingPassthrough.go:81:10:81:24 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:84:38:84:40 | src | provenance | Src:MaD:2 |
32-
| HTMLTemplateEscapingPassthrough.go:89:10:89:24 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:91:64:91:66 | src | provenance | Src:MaD:2 |
33-
| HTMLTemplateEscapingPassthrough.go:91:16:91:77 | type conversion | HTMLTemplateEscapingPassthrough.go:92:38:92:46 | converted | provenance | |
34-
| HTMLTemplateEscapingPassthrough.go:91:38:91:67 | call to HTMLEscapeString | HTMLTemplateEscapingPassthrough.go:91:16:91:77 | type conversion | provenance | |
35-
| HTMLTemplateEscapingPassthrough.go:91:64:91:66 | src | HTMLTemplateEscapingPassthrough.go:91:38:91:67 | call to HTMLEscapeString | provenance | MaD:3 |
36-
| ReflectedXssGood.go:15:15:15:20 | selection of Form | ReflectedXssGood.go:15:15:15:36 | call to Get | provenance | Src:MaD:1 MaD:4 |
37-
| ReflectedXssGood.go:15:15:15:36 | call to Get | ReflectedXssGood.go:20:24:20:31 | username | provenance | |
38-
| ReflectedXssGood.go:15:15:15:36 | call to Get | ReflectedXssGood.go:21:40:21:47 | username | provenance | |
29+
| HTMLTemplateEscapingPassthrough.go:66:24:66:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:66:11:66:39 | type conversion | provenance | Src:MaD:1 Config |
3930
models
40-
| 1 | Source: net/http; Request; true; Form; ; ; ; remote; manual |
41-
| 2 | Source: net/http; Request; true; UserAgent; ; ; ReturnValue; remote; manual |
42-
| 3 | Summary: html/template; ; false; HTMLEscapeString; ; ; Argument[0]; ReturnValue; taint; manual |
43-
| 4 | Summary: net/url; Values; true; Get; ; ; Argument[receiver]; ReturnValue; taint; manual |
31+
| 1 | Source: net/http; Request; true; UserAgent; ; ; ReturnValue; remote; manual |
4432
nodes
4533
| HTMLTemplateEscapingPassthrough.go:29:12:29:41 | type conversion | semmle.label | type conversion |
4634
| HTMLTemplateEscapingPassthrough.go:29:26:29:40 | call to UserAgent | semmle.label | call to UserAgent |
@@ -69,17 +57,4 @@ nodes
6957
| HTMLTemplateEscapingPassthrough.go:66:11:66:39 | type conversion | semmle.label | type conversion |
7058
| HTMLTemplateEscapingPassthrough.go:66:24:66:38 | call to UserAgent | semmle.label | call to UserAgent |
7159
| HTMLTemplateEscapingPassthrough.go:67:38:67:38 | g | semmle.label | g |
72-
| HTMLTemplateEscapingPassthrough.go:75:17:75:31 | call to UserAgent | semmle.label | call to UserAgent |
73-
| HTMLTemplateEscapingPassthrough.go:76:38:76:44 | escaped | semmle.label | escaped |
74-
| HTMLTemplateEscapingPassthrough.go:81:10:81:24 | call to UserAgent | semmle.label | call to UserAgent |
75-
| HTMLTemplateEscapingPassthrough.go:84:38:84:40 | src | semmle.label | src |
76-
| HTMLTemplateEscapingPassthrough.go:89:10:89:24 | call to UserAgent | semmle.label | call to UserAgent |
77-
| HTMLTemplateEscapingPassthrough.go:91:16:91:77 | type conversion | semmle.label | type conversion |
78-
| HTMLTemplateEscapingPassthrough.go:91:38:91:67 | call to HTMLEscapeString | semmle.label | call to HTMLEscapeString |
79-
| HTMLTemplateEscapingPassthrough.go:91:64:91:66 | src | semmle.label | src |
80-
| HTMLTemplateEscapingPassthrough.go:92:38:92:46 | converted | semmle.label | converted |
81-
| ReflectedXssGood.go:15:15:15:20 | selection of Form | semmle.label | selection of Form |
82-
| ReflectedXssGood.go:15:15:15:36 | call to Get | semmle.label | call to Get |
83-
| ReflectedXssGood.go:20:24:20:31 | username | semmle.label | username |
84-
| ReflectedXssGood.go:21:40:21:47 | username | semmle.label | username |
8560
subpaths

0 commit comments

Comments
 (0)