diff --git a/go/ql/lib/change-notes/2026-09-22-nhooyr-package-rename.md b/go/ql/lib/change-notes/2026-09-22-nhooyr-package-rename.md new file mode 100644 index 000000000000..ac06b1f4a08c --- /dev/null +++ b/go/ql/lib/change-notes/2026-09-22-nhooyr-package-rename.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Models for the `nhooyr.io/websocket` package have been updated to also support its new import path `github.com/coder/websocket`. diff --git a/go/ql/lib/ext/github.com.coder.websocket.model.yml b/go/ql/lib/ext/github.com.coder.websocket.model.yml new file mode 100644 index 000000000000..cf94840ea910 --- /dev/null +++ b/go/ql/lib/ext/github.com.coder.websocket.model.yml @@ -0,0 +1,13 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: packageGrouping + data: + - ["coder/websocket", "github.com/coder/websocket"] + - ["coder/websocket", "nhooyr.io/websocket"] + - addsTo: + pack: codeql/go-all + extensible: sourceModel + data: + - ["group:coder/websocket", "Conn", True, "Read", "", "", "ReturnValue[1]", "remote", "manual"] + - ["group:coder/websocket", "Conn", True, "Reader", "", "", "ReturnValue[1]", "remote", "manual"] diff --git a/go/ql/lib/ext/nhooyr.io.websocket.model.yml b/go/ql/lib/ext/nhooyr.io.websocket.model.yml deleted file mode 100644 index bb94c1ce2d4c..000000000000 --- a/go/ql/lib/ext/nhooyr.io.websocket.model.yml +++ /dev/null @@ -1,7 +0,0 @@ -extensions: - - addsTo: - pack: codeql/go-all - extensible: sourceModel - data: - - ["nhooyr.io/websocket", "Conn", True, "Read", "", "", "ReturnValue[1]", "remote", "manual"] - - ["nhooyr.io/websocket", "Conn", True, "Reader", "", "", "ReturnValue[1]", "remote", "manual"] diff --git a/go/ql/lib/semmle/go/frameworks/WebSocket.qll b/go/ql/lib/semmle/go/frameworks/WebSocket.qll index 36c6db5c4536..e8657d296b3f 100644 --- a/go/ql/lib/semmle/go/frameworks/WebSocket.qll +++ b/go/ql/lib/semmle/go/frameworks/WebSocket.qll @@ -102,10 +102,10 @@ module WebSocketRequestCall { /** * A call to the `Dial` function of the `nhooyr.io/websocket` package. */ - private class NhooyrWebSocketDialFunc extends Range { - NhooyrWebSocketDialFunc() { + private class CoderWebSocketDialFunc extends Range { + CoderWebSocketDialFunc() { // func Dial(ctx context.Context, u string, opts *DialOptions) (*Conn, *http.Response, error) - this.getTarget().hasQualifiedName(NhooyrWebSocket::packagePath(), "Dial") + this.getTarget().hasQualifiedName(CoderWebSocket::packagePath(), "Dial") } override DataFlow::Node getRequestUrl() { result = this.getArgument(1) } @@ -188,10 +188,10 @@ module WebSocketReader { /** * The `Conn.Read` method of the `nhooyr.io/websocket` package. */ - private class NhooyrWebSocketRead extends Range, Method { - NhooyrWebSocketRead() { + private class CoderWebSocketRead extends Range, Method { + CoderWebSocketRead() { // func (c *Conn) Read(ctx context.Context) (MessageType, []byte, error) - this.hasQualifiedName(NhooyrWebSocket::packagePath(), "Conn", "Read") + this.hasQualifiedName(CoderWebSocket::packagePath(), "Conn", "Read") } override FunctionOutput getAnOutput() { result.isResult(1) } @@ -200,10 +200,10 @@ module WebSocketReader { /** * The `Conn.Reader` method of the `nhooyr.io/websocket` package. */ - private class NhooyrWebSocketReader extends Range, Method { - NhooyrWebSocketReader() { + private class CoderWebSocketReader extends Range, Method { + CoderWebSocketReader() { // func (c *Conn) Reader(ctx context.Context) (MessageType, io.Reader, error) - this.hasQualifiedName(NhooyrWebSocket::packagePath(), "Conn", "Reader") + this.hasQualifiedName(CoderWebSocket::packagePath(), "Conn", "Reader") } override FunctionOutput getAnOutput() { result.isResult(1) } @@ -313,12 +313,14 @@ module GolangOrgXNetWebsocket { } /** - * Provides classes for working with the [nhooyr.io/websocket](http://nhooyr.io/websocket) + * Provides classes for working with the [coder/websocket](http://github.com/coder/websocket) * package. */ -module NhooyrWebSocket { - /** Gets the package name `nhooyr.io/websocket/`. */ - string packagePath() { result = package("nhooyr.io/websocket", "") } +module CoderWebSocket { + /** Gets the package name `github.com/coder/websocket` or `nhooyr.io/websocket`. */ + string packagePath() { + result = package(["github.com/coder/websocket", "nhooyr.io/websocket"], "") + } } /** diff --git a/go/ql/test/query-tests/Security/CWE-079/CONSISTENCY/DataFlowConsistency.expected b/go/ql/test/query-tests/Security/CWE-079/CONSISTENCY/DataFlowConsistency.expected index 4c53dfb2b800..ac74617174f9 100644 --- a/go/ql/test/query-tests/Security/CWE-079/CONSISTENCY/DataFlowConsistency.expected +++ b/go/ql/test/query-tests/Security/CWE-079/CONSISTENCY/DataFlowConsistency.expected @@ -18,4 +18,4 @@ reverseRead | tst.go:33:15:33:15 | implicit-deref r | Origin of readStep is missing a PostUpdateNode. | | tst.go:48:14:48:14 | implicit-deref r | Origin of readStep is missing a PostUpdateNode. | | tst.go:66:15:66:15 | implicit-deref r | Origin of readStep is missing a PostUpdateNode. | -| websocketXss.go:26:9:26:9 | implicit-deref r | Origin of readStep is missing a PostUpdateNode. | +| websocketXss.go:27:9:27:9 | implicit-deref r | Origin of readStep is missing a PostUpdateNode. | diff --git a/go/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected b/go/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected index d388a119214f..48b7d7728df6 100644 --- a/go/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected +++ b/go/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected @@ -13,25 +13,26 @@ | reflectedxsstest.go:54:11:54:21 | type conversion | reflectedxsstest.go:51:14:51:18 | selection of URL | reflectedxsstest.go:54:11:54:21 | type conversion | Cross-site scripting vulnerability due to $@. | reflectedxsstest.go:51:14:51:18 | selection of URL | user-provided value | reflectedxsstest.go:0:0:0:0 | reflectedxsstest.go | | | tst.go:18:12:18:39 | type conversion | tst.go:14:15:14:20 | selection of Form | tst.go:18:12:18:39 | type conversion | Cross-site scripting vulnerability due to $@. | tst.go:14:15:14:20 | selection of Form | user-provided value | tst.go:0:0:0:0 | tst.go | | | tst.go:53:12:53:26 | type conversion | tst.go:48:14:48:19 | selection of Form | tst.go:53:12:53:26 | type conversion | Cross-site scripting vulnerability due to $@. | tst.go:48:14:48:19 | selection of Form | user-provided value | tst.go:0:0:0:0 | tst.go | | -| websocketXss.go:32:24:32:27 | xnet | websocketXss.go:31:11:31:14 | xnet [postupdate] | websocketXss.go:32:24:32:27 | xnet | Cross-site scripting vulnerability due to $@. | websocketXss.go:31:11:31:14 | xnet [postupdate] | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | -| websocketXss.go:36:24:36:28 | xnet2 | websocketXss.go:35:21:35:25 | xnet2 [postupdate] | websocketXss.go:36:24:36:28 | xnet2 | Cross-site scripting vulnerability due to $@. | websocketXss.go:35:21:35:25 | xnet2 [postupdate] | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | -| websocketXss.go:41:24:41:29 | nhooyr | websocketXss.go:40:3:40:40 | extract:1 ... := ... | websocketXss.go:41:24:41:29 | nhooyr | Cross-site scripting vulnerability due to $@. | websocketXss.go:40:3:40:40 | extract:1 ... := ... | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | -| websocketXss.go:48:24:48:33 | gorillaMsg | websocketXss.go:47:26:47:35 | gorillaMsg [postupdate] | websocketXss.go:48:24:48:33 | gorillaMsg | Cross-site scripting vulnerability due to $@. | websocketXss.go:47:26:47:35 | gorillaMsg [postupdate] | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | -| websocketXss.go:52:24:52:31 | gorilla2 | websocketXss.go:51:17:51:24 | gorilla2 [postupdate] | websocketXss.go:52:24:52:31 | gorilla2 | Cross-site scripting vulnerability due to $@. | websocketXss.go:51:17:51:24 | gorilla2 [postupdate] | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | -| websocketXss.go:55:24:55:31 | gorilla3 | websocketXss.go:54:3:54:38 | extract:1 ... := ... | websocketXss.go:55:24:55:31 | gorilla3 | Cross-site scripting vulnerability due to $@. | websocketXss.go:54:3:54:38 | extract:1 ... := ... | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | +| websocketXss.go:33:24:33:27 | xnet | websocketXss.go:32:11:32:14 | xnet [postupdate] | websocketXss.go:33:24:33:27 | xnet | Cross-site scripting vulnerability due to $@. | websocketXss.go:32:11:32:14 | xnet [postupdate] | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | +| websocketXss.go:37:24:37:28 | xnet2 | websocketXss.go:36:21:36:25 | xnet2 [postupdate] | websocketXss.go:37:24:37:28 | xnet2 | Cross-site scripting vulnerability due to $@. | websocketXss.go:36:21:36:25 | xnet2 [postupdate] | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | +| websocketXss.go:42:24:42:29 | nhooyr | websocketXss.go:41:3:41:40 | extract:1 ... := ... | websocketXss.go:42:24:42:29 | nhooyr | Cross-site scripting vulnerability due to $@. | websocketXss.go:41:3:41:40 | extract:1 ... := ... | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | +| websocketXss.go:47:24:47:31 | coderMsg | websocketXss.go:46:3:46:42 | extract:1 ... := ... | websocketXss.go:47:24:47:31 | coderMsg | Cross-site scripting vulnerability due to $@. | websocketXss.go:46:3:46:42 | extract:1 ... := ... | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | +| websocketXss.go:54:24:54:33 | gorillaMsg | websocketXss.go:53:26:53:35 | gorillaMsg [postupdate] | websocketXss.go:54:24:54:33 | gorillaMsg | Cross-site scripting vulnerability due to $@. | websocketXss.go:53:26:53:35 | gorillaMsg [postupdate] | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | +| websocketXss.go:58:24:58:31 | gorilla2 | websocketXss.go:57:17:57:24 | gorilla2 [postupdate] | websocketXss.go:58:24:58:31 | gorilla2 | Cross-site scripting vulnerability due to $@. | websocketXss.go:57:17:57:24 | gorilla2 [postupdate] | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | +| websocketXss.go:61:24:61:31 | gorilla3 | websocketXss.go:60:3:60:38 | extract:1 ... := ... | websocketXss.go:61:24:61:31 | gorilla3 | Cross-site scripting vulnerability due to $@. | websocketXss.go:60:3:60:38 | extract:1 ... := ... | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | edges -| ReflectedXss.go:11:15:11:20 | selection of Form | ReflectedXss.go:11:15:11:36 | call to Get | provenance | Src:MaD:6 MaD:18 | +| ReflectedXss.go:11:15:11:20 | selection of Form | ReflectedXss.go:11:15:11:36 | call to Get | provenance | Src:MaD:7 MaD:18 | | ReflectedXss.go:11:15:11:36 | call to Get | ReflectedXss.go:14:44:14:51 | username | provenance | | -| contenttype.go:11:11:11:16 | selection of Form | contenttype.go:11:11:11:28 | call to Get | provenance | Src:MaD:6 MaD:18 | +| contenttype.go:11:11:11:16 | selection of Form | contenttype.go:11:11:11:28 | call to Get | provenance | Src:MaD:7 MaD:18 | | contenttype.go:11:11:11:28 | call to Get | contenttype.go:17:11:17:22 | type conversion | provenance | | -| contenttype.go:49:11:49:16 | selection of Form | contenttype.go:49:11:49:28 | call to Get | provenance | Src:MaD:6 MaD:18 | +| contenttype.go:49:11:49:16 | selection of Form | contenttype.go:49:11:49:28 | call to Get | provenance | Src:MaD:7 MaD:18 | | contenttype.go:49:11:49:28 | call to Get | contenttype.go:53:34:53:37 | data | provenance | | -| contenttype.go:63:10:63:28 | call to FormValue | contenttype.go:64:52:64:55 | data | provenance | Src:MaD:8 | -| contenttype.go:73:10:73:28 | call to FormValue | contenttype.go:79:11:79:14 | data | provenance | Src:MaD:8 | -| contenttype.go:88:10:88:28 | call to FormValue | contenttype.go:91:4:91:7 | data | provenance | Src:MaD:8 | -| contenttype.go:113:10:113:28 | call to FormValue | contenttype.go:114:50:114:53 | data | provenance | Src:MaD:8 | -| reflectedxsstest.go:30:2:30:44 | extract:0 ... := ... | reflectedxsstest.go:31:30:31:33 | file | provenance | Src:MaD:7 | -| reflectedxsstest.go:30:2:30:44 | extract:1 ... := ... | reflectedxsstest.go:34:46:34:60 | selection of Filename | provenance | Src:MaD:7 | +| contenttype.go:63:10:63:28 | call to FormValue | contenttype.go:64:52:64:55 | data | provenance | Src:MaD:9 | +| contenttype.go:73:10:73:28 | call to FormValue | contenttype.go:79:11:79:14 | data | provenance | Src:MaD:9 | +| contenttype.go:88:10:88:28 | call to FormValue | contenttype.go:91:4:91:7 | data | provenance | Src:MaD:9 | +| contenttype.go:113:10:113:28 | call to FormValue | contenttype.go:114:50:114:53 | data | provenance | Src:MaD:9 | +| reflectedxsstest.go:30:2:30:44 | extract:0 ... := ... | reflectedxsstest.go:31:30:31:33 | file | provenance | Src:MaD:8 | +| reflectedxsstest.go:30:2:30:44 | extract:1 ... := ... | reflectedxsstest.go:34:46:34:60 | selection of Filename | provenance | Src:MaD:8 | | reflectedxsstest.go:31:2:31:34 | extract:0 ... := ... | reflectedxsstest.go:32:48:32:54 | content | provenance | | | reflectedxsstest.go:31:30:31:33 | file | reflectedxsstest.go:31:2:31:34 | extract:0 ... := ... | provenance | MaD:13 | | reflectedxsstest.go:32:48:32:54 | content | reflectedxsstest.go:33:49:33:55 | content | provenance | | @@ -43,7 +44,7 @@ edges | reflectedxsstest.go:34:17:34:61 | call to Sprintf | reflectedxsstest.go:34:10:34:62 | type conversion | provenance | | | reflectedxsstest.go:34:46:34:60 | selection of Filename | reflectedxsstest.go:34:17:34:61 | []type{args} [array] | provenance | | | reflectedxsstest.go:34:46:34:60 | selection of Filename | reflectedxsstest.go:34:17:34:61 | call to Sprintf | provenance | FunctionModel | -| reflectedxsstest.go:38:2:38:35 | extract:0 ... := ... | reflectedxsstest.go:39:16:39:21 | reader | provenance | Src:MaD:9 | +| reflectedxsstest.go:38:2:38:35 | extract:0 ... := ... | reflectedxsstest.go:39:16:39:21 | reader | provenance | Src:MaD:10 | | reflectedxsstest.go:39:2:39:32 | extract:0 ... := ... | reflectedxsstest.go:40:14:40:17 | part | provenance | | | reflectedxsstest.go:39:2:39:32 | extract:0 ... := ... | reflectedxsstest.go:42:2:42:5 | part | provenance | | | reflectedxsstest.go:39:16:39:21 | reader | reflectedxsstest.go:39:2:39:32 | extract:0 ... := ... | provenance | MaD:16 | @@ -55,34 +56,35 @@ edges | reflectedxsstest.go:44:17:44:54 | call to Sprintf | reflectedxsstest.go:44:10:44:55 | type conversion | provenance | | | reflectedxsstest.go:44:46:44:53 | partName | reflectedxsstest.go:44:17:44:54 | []type{args} [array] | provenance | | | reflectedxsstest.go:44:46:44:53 | partName | reflectedxsstest.go:44:17:44:54 | call to Sprintf | provenance | FunctionModel | -| reflectedxsstest.go:51:14:51:18 | selection of URL | reflectedxsstest.go:51:14:51:26 | call to Query | provenance | Src:MaD:10 MaD:17 | +| reflectedxsstest.go:51:14:51:18 | selection of URL | reflectedxsstest.go:51:14:51:26 | call to Query | provenance | Src:MaD:11 MaD:17 | | reflectedxsstest.go:51:14:51:26 | call to Query | reflectedxsstest.go:54:11:54:21 | type conversion | provenance | | -| tst.go:14:15:14:20 | selection of Form | tst.go:14:15:14:36 | call to Get | provenance | Src:MaD:6 MaD:18 | +| tst.go:14:15:14:20 | selection of Form | tst.go:14:15:14:36 | call to Get | provenance | Src:MaD:7 MaD:18 | | tst.go:14:15:14:36 | call to Get | tst.go:17:18:17:25 | username | provenance | | | tst.go:17:9:17:57 | slice literal [array] | tst.go:18:32:18:32 | a [array] | provenance | | | tst.go:17:18:17:25 | username | tst.go:17:9:17:57 | slice literal [array] | provenance | | | tst.go:18:19:18:38 | call to Join | tst.go:18:12:18:39 | type conversion | provenance | | | tst.go:18:32:18:32 | a [array] | tst.go:18:19:18:38 | call to Join | provenance | MaD:19 | -| tst.go:48:14:48:19 | selection of Form | tst.go:48:14:48:34 | call to Get | provenance | Src:MaD:6 MaD:18 | +| tst.go:48:14:48:19 | selection of Form | tst.go:48:14:48:34 | call to Get | provenance | Src:MaD:7 MaD:18 | | tst.go:48:14:48:34 | call to Get | tst.go:53:12:53:26 | type conversion | provenance | | -| websocketXss.go:31:11:31:14 | xnet [postupdate] | websocketXss.go:32:24:32:27 | xnet | provenance | Src:MaD:5 | -| websocketXss.go:35:21:35:25 | xnet2 [postupdate] | websocketXss.go:36:24:36:28 | xnet2 | provenance | Src:MaD:4 | -| websocketXss.go:40:3:40:40 | extract:1 ... := ... | websocketXss.go:41:24:41:29 | nhooyr | provenance | Src:MaD:11 | -| websocketXss.go:47:26:47:35 | gorillaMsg [postupdate] | websocketXss.go:48:24:48:33 | gorillaMsg | provenance | Src:MaD:1 | -| websocketXss.go:51:17:51:24 | gorilla2 [postupdate] | websocketXss.go:52:24:52:31 | gorilla2 | provenance | Src:MaD:2 | -| websocketXss.go:54:3:54:38 | extract:1 ... := ... | websocketXss.go:55:24:55:31 | gorilla3 | provenance | Src:MaD:3 | +| websocketXss.go:32:11:32:14 | xnet [postupdate] | websocketXss.go:33:24:33:27 | xnet | provenance | Src:MaD:5 | +| websocketXss.go:36:21:36:25 | xnet2 [postupdate] | websocketXss.go:37:24:37:28 | xnet2 | provenance | Src:MaD:4 | +| websocketXss.go:41:3:41:40 | extract:1 ... := ... | websocketXss.go:42:24:42:29 | nhooyr | provenance | Src:MaD:6 | +| websocketXss.go:46:3:46:42 | extract:1 ... := ... | websocketXss.go:47:24:47:31 | coderMsg | provenance | Src:MaD:6 | +| websocketXss.go:53:26:53:35 | gorillaMsg [postupdate] | websocketXss.go:54:24:54:33 | gorillaMsg | provenance | Src:MaD:1 | +| websocketXss.go:57:17:57:24 | gorilla2 [postupdate] | websocketXss.go:58:24:58:31 | gorilla2 | provenance | Src:MaD:2 | +| websocketXss.go:60:3:60:38 | extract:1 ... := ... | websocketXss.go:61:24:61:31 | gorilla3 | provenance | Src:MaD:3 | models | 1 | Source: github.com/gorilla/websocket; ; false; ReadJSON; ; ; Argument[1]; remote; manual | | 2 | Source: github.com/gorilla/websocket; Conn; true; ReadJSON; ; ; Argument[0]; remote; manual | | 3 | Source: github.com/gorilla/websocket; Conn; true; ReadMessage; ; ; ReturnValue[1]; remote; manual | | 4 | Source: golang.org/x/net/websocket; Codec; true; Receive; ; ; Argument[1]; remote; manual | | 5 | Source: golang.org/x/net/websocket; Conn; true; Read; ; ; Argument[0]; remote; manual | -| 6 | Source: net/http; Request; true; Form; ; ; ; remote; manual | -| 7 | Source: net/http; Request; true; FormFile; ; ; ReturnValue[0..1]; remote; manual | -| 8 | Source: net/http; Request; true; FormValue; ; ; ReturnValue; remote; manual | -| 9 | Source: net/http; Request; true; MultipartReader; ; ; ReturnValue[0]; remote; manual | -| 10 | Source: net/http; Request; true; URL; ; ; ; remote; manual | -| 11 | Source: nhooyr.io/websocket; Conn; true; Read; ; ; ReturnValue[1]; remote; manual | +| 6 | Source: group:coder/websocket; Conn; true; Read; ; ; ReturnValue[1]; remote; manual | +| 7 | Source: net/http; Request; true; Form; ; ; ; remote; manual | +| 8 | Source: net/http; Request; true; FormFile; ; ; ReturnValue[0..1]; remote; manual | +| 9 | Source: net/http; Request; true; FormValue; ; ; ReturnValue; remote; manual | +| 10 | Source: net/http; Request; true; MultipartReader; ; ; ReturnValue[0]; remote; manual | +| 11 | Source: net/http; Request; true; URL; ; ; ; remote; manual | | 12 | Summary: fmt; ; false; Sprintf; ; ; Argument[1].ArrayElement; ReturnValue; taint; manual | | 13 | Summary: io; ; false; ReadAll; ; ; Argument[0]; ReturnValue[0]; taint; manual | | 14 | Summary: io; Reader; true; Read; ; ; Argument[receiver]; Argument[0]; taint; manual | @@ -147,16 +149,18 @@ nodes | tst.go:48:14:48:19 | selection of Form | semmle.label | selection of Form | | tst.go:48:14:48:34 | call to Get | semmle.label | call to Get | | tst.go:53:12:53:26 | type conversion | semmle.label | type conversion | -| websocketXss.go:31:11:31:14 | xnet [postupdate] | semmle.label | xnet [postupdate] | -| websocketXss.go:32:24:32:27 | xnet | semmle.label | xnet | -| websocketXss.go:35:21:35:25 | xnet2 [postupdate] | semmle.label | xnet2 [postupdate] | -| websocketXss.go:36:24:36:28 | xnet2 | semmle.label | xnet2 | -| websocketXss.go:40:3:40:40 | extract:1 ... := ... | semmle.label | extract:1 ... := ... | -| websocketXss.go:41:24:41:29 | nhooyr | semmle.label | nhooyr | -| websocketXss.go:47:26:47:35 | gorillaMsg [postupdate] | semmle.label | gorillaMsg [postupdate] | -| websocketXss.go:48:24:48:33 | gorillaMsg | semmle.label | gorillaMsg | -| websocketXss.go:51:17:51:24 | gorilla2 [postupdate] | semmle.label | gorilla2 [postupdate] | -| websocketXss.go:52:24:52:31 | gorilla2 | semmle.label | gorilla2 | -| websocketXss.go:54:3:54:38 | extract:1 ... := ... | semmle.label | extract:1 ... := ... | -| websocketXss.go:55:24:55:31 | gorilla3 | semmle.label | gorilla3 | +| websocketXss.go:32:11:32:14 | xnet [postupdate] | semmle.label | xnet [postupdate] | +| websocketXss.go:33:24:33:27 | xnet | semmle.label | xnet | +| websocketXss.go:36:21:36:25 | xnet2 [postupdate] | semmle.label | xnet2 [postupdate] | +| websocketXss.go:37:24:37:28 | xnet2 | semmle.label | xnet2 | +| websocketXss.go:41:3:41:40 | extract:1 ... := ... | semmle.label | extract:1 ... := ... | +| websocketXss.go:42:24:42:29 | nhooyr | semmle.label | nhooyr | +| websocketXss.go:46:3:46:42 | extract:1 ... := ... | semmle.label | extract:1 ... := ... | +| websocketXss.go:47:24:47:31 | coderMsg | semmle.label | coderMsg | +| websocketXss.go:53:26:53:35 | gorillaMsg [postupdate] | semmle.label | gorillaMsg [postupdate] | +| websocketXss.go:54:24:54:33 | gorillaMsg | semmle.label | gorillaMsg | +| websocketXss.go:57:17:57:24 | gorilla2 [postupdate] | semmle.label | gorilla2 [postupdate] | +| websocketXss.go:58:24:58:31 | gorilla2 | semmle.label | gorilla2 | +| websocketXss.go:60:3:60:38 | extract:1 ... := ... | semmle.label | extract:1 ... := ... | +| websocketXss.go:61:24:61:31 | gorilla3 | semmle.label | gorilla3 | subpaths diff --git a/go/ql/test/query-tests/Security/CWE-079/go.mod b/go/ql/test/query-tests/Security/CWE-079/go.mod index aaab77bf0398..fa397e413d7e 100644 --- a/go/ql/test/query-tests/Security/CWE-079/go.mod +++ b/go/ql/test/query-tests/Security/CWE-079/go.mod @@ -3,6 +3,7 @@ module codeql-go-tests/CWE-079 go 1.24 require ( + github.com/coder/websocket v1.8.5 github.com/gobwas/ws v1.0.3 github.com/gorilla/websocket v1.4.2 golang.org/x/net v0.0.0-20200505041828-1ed23360d12c diff --git a/go/ql/test/query-tests/Security/CWE-079/vendor/github.com/coder/websocket/LICENSE b/go/ql/test/query-tests/Security/CWE-079/vendor/github.com/coder/websocket/LICENSE new file mode 100644 index 000000000000..b5b5fef31f0f --- /dev/null +++ b/go/ql/test/query-tests/Security/CWE-079/vendor/github.com/coder/websocket/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Anmol Sethi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/go/ql/test/query-tests/Security/CWE-079/vendor/github.com/coder/websocket/stub.go b/go/ql/test/query-tests/Security/CWE-079/vendor/github.com/coder/websocket/stub.go new file mode 100644 index 000000000000..7bf2a208daca --- /dev/null +++ b/go/ql/test/query-tests/Security/CWE-079/vendor/github.com/coder/websocket/stub.go @@ -0,0 +1,76 @@ +// Code generated by depstubber. DO NOT EDIT. +// This is a simple stub for nhooyr.io/websocket, strictly for use in testing. + +// See the LICENSE file for information about the licensing of the original library. +// Source: nhooyr.io/websocket (exports: ; functions: Dial) + +// Package websocket is a stub of nhooyr.io/websocket, generated by depstubber. +package websocket + +import ( + context "context" + io "io" + http "net/http" +) + +type CompressionMode int + +type Conn struct{} + +func (_ *Conn) Close(_ StatusCode, _ string) error { + return nil +} + +func (_ *Conn) CloseRead(_ context.Context) context.Context { + return nil +} + +func (_ *Conn) Ping(_ context.Context) error { + return nil +} + +func (_ *Conn) Read(_ context.Context) (MessageType, []byte, error) { + return 0, nil, nil +} + +func (_ *Conn) Reader(_ context.Context) (MessageType, io.Reader, error) { + return 0, nil, nil +} + +func (_ *Conn) SetReadLimit(_ int64) {} + +func (_ *Conn) Subprotocol() string { + return "" +} + +func (_ *Conn) Write(_ context.Context, _ MessageType, _ []byte) error { + return nil +} + +func (_ *Conn) Writer(_ context.Context, _ MessageType) (io.WriteCloser, error) { + return nil, nil +} + +func Dial(_ context.Context, _ string, _ *DialOptions) (*Conn, *http.Response, error) { + return nil, nil, nil +} + +type DialOptions struct { + HTTPClient *http.Client + HTTPHeader http.Header + Subprotocols []string + CompressionMode CompressionMode + CompressionThreshold int +} + +type MessageType int + +func (_ MessageType) String() string { + return "" +} + +type StatusCode int + +func (_ StatusCode) String() string { + return "" +} diff --git a/go/ql/test/query-tests/Security/CWE-079/vendor/modules.txt b/go/ql/test/query-tests/Security/CWE-079/vendor/modules.txt index f61f191db597..829fd45b3539 100644 --- a/go/ql/test/query-tests/Security/CWE-079/vendor/modules.txt +++ b/go/ql/test/query-tests/Security/CWE-079/vendor/modules.txt @@ -1,3 +1,6 @@ +# github.com/coder/websocket v1.8.5 +## explicit +github.com/coder/websocket # github.com/gobwas/ws v1.0.3 ## explicit github.com/gobwas/ws diff --git a/go/ql/test/query-tests/Security/CWE-079/websocketXss.go b/go/ql/test/query-tests/Security/CWE-079/websocketXss.go index eadc87b2c9f9..1bf77e72d8f6 100644 --- a/go/ql/test/query-tests/Security/CWE-079/websocketXss.go +++ b/go/ql/test/query-tests/Security/CWE-079/websocketXss.go @@ -10,6 +10,7 @@ import ( "fmt" "net/http" + coder "github.com/coder/websocket" gorilla "github.com/gorilla/websocket" websocket "golang.org/x/net/websocket" nhooyr "nhooyr.io/websocket" @@ -40,6 +41,11 @@ func xss(w http.ResponseWriter, r *http.Request) { _, nhooyr, _ := n.Read(context.TODO()) // $ Source[go/reflected-xss] fmt.Fprintf(w, "%v", nhooyr) // $ Alert[go/reflected-xss] } + { + n, _, _ := coder.Dial(context.TODO(), uri, nil) + _, coderMsg, _ := n.Read(context.TODO()) // $ Source[go/reflected-xss] + fmt.Fprintf(w, "%v", coderMsg) // $ Alert[go/reflected-xss] + } { dialer := gorilla.Dialer{} conn, _, _ := dialer.Dial(uri, nil)