Merge pull request #20000 from owen-mc/go/request-forgery

Go: Add `Head` and `Client.Head` from `net/http` as request forgery sinks
This commit is contained in:
Owen Mansel-Chan
2025-07-12 00:30:23 +01:00
committed by GitHub
7 changed files with 111 additions and 81 deletions

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added models for the `Head` function and the `Client.Head` method, from the `net/http` package, to the `Http::ClientRequest` class. This means that they will be recognized as sinks for the query `go/request-forgery` and the experimental query `go/ssrf`.

View File

@@ -179,12 +179,11 @@ module NetHttp {
private class RequestCall extends Http::ClientRequest::Range, DataFlow::CallNode {
RequestCall() {
exists(string functionName |
(
this.getTarget().hasQualifiedName("net/http", functionName)
or
this.getTarget().(Method).hasQualifiedName("net/http", "Client", functionName)
) and
(functionName = "Get" or functionName = "Post" or functionName = "PostForm")
this.getTarget().hasQualifiedName("net/http", functionName)
or
this.getTarget().(Method).hasQualifiedName("net/http", "Client", functionName)
|
functionName = ["Get", "Head", "Post", "PostForm"]
)
}

View File

@@ -1,12 +1,18 @@
#select
| RequestForgery.go:11:15:11:66 | call to Get | RequestForgery.go:8:12:8:34 | call to FormValue | RequestForgery.go:11:24:11:65 | ...+... | The $@ of this request depends on a $@. | RequestForgery.go:11:24:11:65 | ...+... | URL | RequestForgery.go:8:12:8:34 | call to FormValue | user-provided value |
| tst.go:14:2:14:18 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:14:11:14:17 | tainted | The $@ of this request depends on a $@. | tst.go:14:11:14:17 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
| tst.go:16:2:16:19 | call to Head | tst.go:10:13:10:35 | call to FormValue | tst.go:16:12:16:18 | tainted | The $@ of this request depends on a $@. | tst.go:16:12:16:18 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
| tst.go:18:2:18:38 | call to Post | tst.go:10:13:10:35 | call to FormValue | tst.go:18:12:18:18 | tainted | The $@ of this request depends on a $@. | tst.go:18:12:18:18 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
| tst.go:22:2:22:14 | call to Do | tst.go:10:13:10:35 | call to FormValue | tst.go:21:34:21:40 | tainted | The $@ of this request depends on a $@. | tst.go:21:34:21:40 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
| tst.go:25:2:25:14 | call to Do | tst.go:10:13:10:35 | call to FormValue | tst.go:24:66:24:72 | tainted | The $@ of this request depends on a $@. | tst.go:24:66:24:72 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
| tst.go:27:2:27:30 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:27:11:27:29 | ...+... | The $@ of this request depends on a $@. | tst.go:27:11:27:29 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
| tst.go:29:2:29:41 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:29:11:29:40 | ...+... | The $@ of this request depends on a $@. | tst.go:29:11:29:40 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
| tst.go:37:2:37:21 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:37:11:37:20 | call to String | The $@ of this request depends on a $@. | tst.go:37:11:37:20 | call to String | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
| tst.go:20:2:20:28 | call to PostForm | tst.go:10:13:10:35 | call to FormValue | tst.go:20:16:20:22 | tainted | The $@ of this request depends on a $@. | tst.go:20:16:20:22 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
| tst.go:24:2:24:15 | call to Do | tst.go:10:13:10:35 | call to FormValue | tst.go:23:35:23:41 | tainted | The $@ of this request depends on a $@. | tst.go:23:35:23:41 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
| tst.go:27:2:27:15 | call to Do | tst.go:10:13:10:35 | call to FormValue | tst.go:26:68:26:74 | tainted | The $@ of this request depends on a $@. | tst.go:26:68:26:74 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
| tst.go:29:2:29:20 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:29:13:29:19 | tainted | The $@ of this request depends on a $@. | tst.go:29:13:29:19 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
| tst.go:30:2:30:21 | call to Head | tst.go:10:13:10:35 | call to FormValue | tst.go:30:14:30:20 | tainted | The $@ of this request depends on a $@. | tst.go:30:14:30:20 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
| tst.go:31:2:31:40 | call to Post | tst.go:10:13:10:35 | call to FormValue | tst.go:31:14:31:20 | tainted | The $@ of this request depends on a $@. | tst.go:31:14:31:20 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
| tst.go:32:2:32:30 | call to PostForm | tst.go:10:13:10:35 | call to FormValue | tst.go:32:18:32:24 | tainted | The $@ of this request depends on a $@. | tst.go:32:18:32:24 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
| tst.go:34:2:34:30 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:34:11:34:29 | ...+... | The $@ of this request depends on a $@. | tst.go:34:11:34:29 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
| tst.go:36:2:36:41 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:36:11:36:40 | ...+... | The $@ of this request depends on a $@. | tst.go:36:11:36:40 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
| tst.go:44:2:44:21 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:44:11:44:20 | call to String | The $@ of this request depends on a $@. | tst.go:44:11:44:20 | call to String | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
| websocket.go:65:12:65:53 | call to Dial | websocket.go:60:21:60:31 | call to Referer | websocket.go:65:27:65:40 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:65:27:65:40 | untrustedInput | WebSocket URL | websocket.go:60:21:60:31 | call to Referer | user-provided value |
| websocket.go:79:13:79:40 | call to DialConfig | websocket.go:74:21:74:31 | call to Referer | websocket.go:78:36:78:49 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:78:36:78:49 | untrustedInput | WebSocket URL | websocket.go:74:21:74:31 | call to Referer | user-provided value |
| websocket.go:91:3:91:50 | call to Dial | websocket.go:88:21:88:31 | call to Referer | websocket.go:91:31:91:44 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:91:31:91:44 | untrustedInput | WebSocket URL | websocket.go:88:21:88:31 | call to Referer | user-provided value |
@@ -14,27 +20,33 @@
| websocket.go:129:3:129:62 | call to DialContext | websocket.go:126:21:126:31 | call to Referer | websocket.go:129:38:129:51 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:129:38:129:51 | untrustedInput | WebSocket URL | websocket.go:126:21:126:31 | call to Referer | user-provided value |
| websocket.go:155:3:155:45 | call to Dial | websocket.go:154:21:154:31 | call to Referer | websocket.go:155:31:155:44 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:155:31:155:44 | untrustedInput | WebSocket URL | websocket.go:154:21:154:31 | call to Referer | user-provided value |
| websocket.go:162:3:162:45 | call to Dial | websocket.go:160:21:160:31 | call to Referer | websocket.go:162:31:162:44 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:162:31:162:44 | untrustedInput | WebSocket URL | websocket.go:160:21:160:31 | call to Referer | user-provided value |
| websocket.go:197:3:197:32 | call to BuildProxy | websocket.go:195:21:195:31 | call to Referer | websocket.go:197:18:197:31 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:197:18:197:31 | untrustedInput | WebSocket URL | websocket.go:195:21:195:31 | call to Referer | user-provided value |
| websocket.go:204:3:204:25 | call to New | websocket.go:202:21:202:31 | call to Referer | websocket.go:204:11:204:24 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:204:11:204:24 | untrustedInput | WebSocket URL | websocket.go:202:21:202:31 | call to Referer | user-provided value |
| websocket.go:197:7:197:36 | call to BuildProxy | websocket.go:195:21:195:31 | call to Referer | websocket.go:197:22:197:35 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:197:22:197:35 | untrustedInput | WebSocket URL | websocket.go:195:21:195:31 | call to Referer | user-provided value |
| websocket.go:204:7:204:29 | call to New | websocket.go:202:21:202:31 | call to Referer | websocket.go:204:15:204:28 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:204:15:204:28 | untrustedInput | WebSocket URL | websocket.go:202:21:202:31 | call to Referer | user-provided value |
edges
| RequestForgery.go:8:12:8:34 | call to FormValue | RequestForgery.go:11:24:11:65 | ...+... | provenance | Src:MaD:1 |
| tst.go:10:13:10:35 | call to FormValue | tst.go:14:11:14:17 | tainted | provenance | Src:MaD:1 |
| tst.go:10:13:10:35 | call to FormValue | tst.go:16:12:16:18 | tainted | provenance | Src:MaD:1 |
| tst.go:10:13:10:35 | call to FormValue | tst.go:18:12:18:18 | tainted | provenance | Src:MaD:1 |
| tst.go:10:13:10:35 | call to FormValue | tst.go:21:34:21:40 | tainted | provenance | Src:MaD:1 |
| tst.go:10:13:10:35 | call to FormValue | tst.go:24:66:24:72 | tainted | provenance | Src:MaD:1 |
| tst.go:10:13:10:35 | call to FormValue | tst.go:27:11:27:29 | ...+... | provenance | Src:MaD:1 |
| tst.go:10:13:10:35 | call to FormValue | tst.go:29:11:29:40 | ...+... | provenance | Src:MaD:1 |
| tst.go:10:13:10:35 | call to FormValue | tst.go:36:11:36:17 | tainted | provenance | Src:MaD:1 |
| tst.go:35:2:35:2 | definition of u [pointer] | tst.go:36:2:36:2 | u [pointer] | provenance | |
| tst.go:36:2:36:2 | implicit dereference | tst.go:35:2:35:2 | definition of u [pointer] | provenance | |
| tst.go:36:2:36:2 | implicit dereference | tst.go:36:2:36:2 | u | provenance | |
| tst.go:36:2:36:2 | implicit dereference | tst.go:37:11:37:11 | u | provenance | |
| tst.go:36:2:36:2 | u | tst.go:36:2:36:2 | implicit dereference | provenance | |
| tst.go:36:2:36:2 | u | tst.go:37:11:37:11 | u | provenance | |
| tst.go:36:2:36:2 | u [pointer] | tst.go:36:2:36:2 | implicit dereference | provenance | |
| tst.go:36:11:36:17 | tainted | tst.go:36:2:36:2 | u | provenance | Config |
| tst.go:36:11:36:17 | tainted | tst.go:37:11:37:11 | u | provenance | Config |
| tst.go:37:11:37:11 | u | tst.go:37:11:37:20 | call to String | provenance | MaD:3 |
| tst.go:10:13:10:35 | call to FormValue | tst.go:20:16:20:22 | tainted | provenance | Src:MaD:1 |
| tst.go:10:13:10:35 | call to FormValue | tst.go:23:35:23:41 | tainted | provenance | Src:MaD:1 |
| tst.go:10:13:10:35 | call to FormValue | tst.go:26:68:26:74 | tainted | provenance | Src:MaD:1 |
| tst.go:10:13:10:35 | call to FormValue | tst.go:29:13:29:19 | tainted | provenance | Src:MaD:1 |
| tst.go:10:13:10:35 | call to FormValue | tst.go:30:14:30:20 | tainted | provenance | Src:MaD:1 |
| tst.go:10:13:10:35 | call to FormValue | tst.go:31:14:31:20 | tainted | provenance | Src:MaD:1 |
| tst.go:10:13:10:35 | call to FormValue | tst.go:32:18:32:24 | tainted | provenance | Src:MaD:1 |
| tst.go:10:13:10:35 | call to FormValue | tst.go:34:11:34:29 | ...+... | provenance | Src:MaD:1 |
| tst.go:10:13:10:35 | call to FormValue | tst.go:36:11:36:40 | ...+... | provenance | Src:MaD:1 |
| tst.go:10:13:10:35 | call to FormValue | tst.go:43:11:43:17 | tainted | provenance | Src:MaD:1 |
| tst.go:42:2:42:2 | definition of u [pointer] | tst.go:43:2:43:2 | u [pointer] | provenance | |
| tst.go:43:2:43:2 | implicit dereference | tst.go:42:2:42:2 | definition of u [pointer] | provenance | |
| tst.go:43:2:43:2 | implicit dereference | tst.go:43:2:43:2 | u | provenance | |
| tst.go:43:2:43:2 | implicit dereference | tst.go:44:11:44:11 | u | provenance | |
| tst.go:43:2:43:2 | u | tst.go:43:2:43:2 | implicit dereference | provenance | |
| tst.go:43:2:43:2 | u | tst.go:44:11:44:11 | u | provenance | |
| tst.go:43:2:43:2 | u [pointer] | tst.go:43:2:43:2 | implicit dereference | provenance | |
| tst.go:43:11:43:17 | tainted | tst.go:43:2:43:2 | u | provenance | Config |
| tst.go:43:11:43:17 | tainted | tst.go:44:11:44:11 | u | provenance | Config |
| tst.go:44:11:44:11 | u | tst.go:44:11:44:20 | call to String | provenance | MaD:3 |
| websocket.go:60:21:60:31 | call to Referer | websocket.go:65:27:65:40 | untrustedInput | provenance | Src:MaD:2 |
| websocket.go:74:21:74:31 | call to Referer | websocket.go:78:36:78:49 | untrustedInput | provenance | Src:MaD:2 |
| websocket.go:88:21:88:31 | call to Referer | websocket.go:91:31:91:44 | untrustedInput | provenance | Src:MaD:2 |
@@ -42,8 +54,8 @@ edges
| websocket.go:126:21:126:31 | call to Referer | websocket.go:129:38:129:51 | untrustedInput | provenance | Src:MaD:2 |
| websocket.go:154:21:154:31 | call to Referer | websocket.go:155:31:155:44 | untrustedInput | provenance | Src:MaD:2 |
| websocket.go:160:21:160:31 | call to Referer | websocket.go:162:31:162:44 | untrustedInput | provenance | Src:MaD:2 |
| websocket.go:195:21:195:31 | call to Referer | websocket.go:197:18:197:31 | untrustedInput | provenance | Src:MaD:2 |
| websocket.go:202:21:202:31 | call to Referer | websocket.go:204:11:204:24 | untrustedInput | provenance | Src:MaD:2 |
| websocket.go:195:21:195:31 | call to Referer | websocket.go:197:22:197:35 | untrustedInput | provenance | Src:MaD:2 |
| websocket.go:202:21:202:31 | call to Referer | websocket.go:204:15:204:28 | untrustedInput | provenance | Src:MaD:2 |
models
| 1 | Source: net/http; Request; true; FormValue; ; ; ReturnValue; remote; manual |
| 2 | Source: net/http; Request; true; Referer; ; ; ReturnValue; remote; manual |
@@ -53,18 +65,24 @@ nodes
| RequestForgery.go:11:24:11:65 | ...+... | semmle.label | ...+... |
| tst.go:10:13:10:35 | call to FormValue | semmle.label | call to FormValue |
| tst.go:14:11:14:17 | tainted | semmle.label | tainted |
| tst.go:16:12:16:18 | tainted | semmle.label | tainted |
| tst.go:18:12:18:18 | tainted | semmle.label | tainted |
| tst.go:21:34:21:40 | tainted | semmle.label | tainted |
| tst.go:24:66:24:72 | tainted | semmle.label | tainted |
| tst.go:27:11:27:29 | ...+... | semmle.label | ...+... |
| tst.go:29:11:29:40 | ...+... | semmle.label | ...+... |
| tst.go:35:2:35:2 | definition of u [pointer] | semmle.label | definition of u [pointer] |
| tst.go:36:2:36:2 | implicit dereference | semmle.label | implicit dereference |
| tst.go:36:2:36:2 | u | semmle.label | u |
| tst.go:36:2:36:2 | u [pointer] | semmle.label | u [pointer] |
| tst.go:36:11:36:17 | tainted | semmle.label | tainted |
| tst.go:37:11:37:11 | u | semmle.label | u |
| tst.go:37:11:37:20 | call to String | semmle.label | call to String |
| tst.go:20:16:20:22 | tainted | semmle.label | tainted |
| tst.go:23:35:23:41 | tainted | semmle.label | tainted |
| tst.go:26:68:26:74 | tainted | semmle.label | tainted |
| tst.go:29:13:29:19 | tainted | semmle.label | tainted |
| tst.go:30:14:30:20 | tainted | semmle.label | tainted |
| tst.go:31:14:31:20 | tainted | semmle.label | tainted |
| tst.go:32:18:32:24 | tainted | semmle.label | tainted |
| tst.go:34:11:34:29 | ...+... | semmle.label | ...+... |
| tst.go:36:11:36:40 | ...+... | semmle.label | ...+... |
| tst.go:42:2:42:2 | definition of u [pointer] | semmle.label | definition of u [pointer] |
| tst.go:43:2:43:2 | implicit dereference | semmle.label | implicit dereference |
| tst.go:43:2:43:2 | u | semmle.label | u |
| tst.go:43:2:43:2 | u [pointer] | semmle.label | u [pointer] |
| tst.go:43:11:43:17 | tainted | semmle.label | tainted |
| tst.go:44:11:44:11 | u | semmle.label | u |
| tst.go:44:11:44:20 | call to String | semmle.label | call to String |
| websocket.go:60:21:60:31 | call to Referer | semmle.label | call to Referer |
| websocket.go:65:27:65:40 | untrustedInput | semmle.label | untrustedInput |
| websocket.go:74:21:74:31 | call to Referer | semmle.label | call to Referer |
@@ -80,7 +98,7 @@ nodes
| websocket.go:160:21:160:31 | call to Referer | semmle.label | call to Referer |
| websocket.go:162:31:162:44 | untrustedInput | semmle.label | untrustedInput |
| websocket.go:195:21:195:31 | call to Referer | semmle.label | call to Referer |
| websocket.go:197:18:197:31 | untrustedInput | semmle.label | untrustedInput |
| websocket.go:197:22:197:35 | untrustedInput | semmle.label | untrustedInput |
| websocket.go:202:21:202:31 | call to Referer | semmle.label | call to Referer |
| websocket.go:204:11:204:24 | untrustedInput | semmle.label | untrustedInput |
| websocket.go:204:15:204:28 | untrustedInput | semmle.label | untrustedInput |
subpaths

View File

@@ -5,10 +5,10 @@ import (
)
func handler(w http.ResponseWriter, req *http.Request) {
target := req.FormValue("target")
target := req.FormValue("target") // $ Source
// BAD: `target` is controlled by the attacker
resp, err := http.Get("https://" + target + ".example.com/data/")
resp, err := http.Get("https://" + target + ".example.com/data/") // $ Alert
if err != nil {
// error handling
}

View File

@@ -1,2 +1,4 @@
query: Security/CWE-918/RequestForgery.ql
postprocess: utils/test/PrettyPrintModels.ql
postprocess:
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -7,26 +7,33 @@ import (
)
func handler2(w http.ResponseWriter, req *http.Request) {
tainted := req.FormValue("target")
tainted := req.FormValue("target") // $ Source
http.Get("example.com") // OK
http.Get(tainted) // Not OK
http.Get(tainted) // $ Alert
http.Head(tainted) // OK
http.Head(tainted) // $ Alert
http.Post(tainted, "text/basic", nil) // Not OK
http.Post(tainted, "text/basic", nil) // $ Alert
http.PostForm(tainted, nil) // $ Alert
client := &http.Client{}
rq, _ := http.NewRequest("GET", tainted, nil)
client.Do(rq) // Not OK
rq1, _ := http.NewRequest("GET", tainted, nil) // $ Sink
client.Do(rq1) // $ Alert
rq, _ = http.NewRequestWithContext(context.Background(), "GET", tainted, nil)
client.Do(rq) // Not OK
rq2, _ := http.NewRequestWithContext(context.Background(), "GET", tainted, nil) // $ Sink
client.Do(rq2) // $ Alert
http.Get("http://" + tainted) // Not OK
client.Get(tainted) // $ Alert
client.Head(tainted) // $ Alert
client.Post(tainted, "text/basic", nil) // $ Alert
client.PostForm(tainted, nil) // $ Alert
http.Get("http://example.com" + tainted) // Not OK
http.Get("http://" + tainted) // $ Alert
http.Get("http://example.com" + tainted) // $ Alert
http.Get("http://example.com/" + tainted) // OK
@@ -34,7 +41,7 @@ func handler2(w http.ResponseWriter, req *http.Request) {
u, _ := url.Parse("http://example.com/relative-path")
u.Host = tainted
http.Get(u.String()) // Not OK
http.Get(u.String()) // $ Alert
}
func main() {

View File

@@ -57,12 +57,12 @@ func test() {
// x net websocket dial bad
http.HandleFunc("/ex2", func(w http.ResponseWriter, r *http.Request) {
untrustedInput := r.Referer()
untrustedInput := r.Referer() // $ Source
origin := "http://localhost/"
// bad as input is directly passed to dial function
ws, _ := websocket.Dial(untrustedInput, "", origin)
ws, _ := websocket.Dial(untrustedInput, "", origin) // $ Alert
var msg = make([]byte, 512)
var n int
n, _ = ws.Read(msg)
@@ -71,12 +71,12 @@ func test() {
// x net websocket dialConfig bad
http.HandleFunc("/ex3", func(w http.ResponseWriter, r *http.Request) {
untrustedInput := r.Referer()
untrustedInput := r.Referer() // $ Source
origin := "http://localhost/"
// bad as input is directly used
config, _ := websocket.NewConfig(untrustedInput, origin) // good
ws2, _ := websocket.DialConfig(config)
config, _ := websocket.NewConfig(untrustedInput, origin) // $ Sink
ws2, _ := websocket.DialConfig(config) // $ Alert
var msg = make([]byte, 512)
var n int
n, _ = ws2.Read(msg)
@@ -85,10 +85,10 @@ func test() {
// nhooyr websocket dial bad
http.HandleFunc("/ex4", func(w http.ResponseWriter, r *http.Request) {
untrustedInput := r.Referer()
untrustedInput := r.Referer() // $ Source
// bad as input is used directly
nhooyr.Dial(context.TODO(), untrustedInput, nil)
nhooyr.Dial(context.TODO(), untrustedInput, nil) // $ Alert
w.WriteHeader(500)
})
@@ -104,10 +104,10 @@ func test() {
// gorilla websocket Dialer.Dial bad
http.HandleFunc("/ex6", func(w http.ResponseWriter, r *http.Request) {
untrustedInput := r.Referer()
untrustedInput := r.Referer() // $ Source
dialer := gorilla.Dialer{}
dialer.Dial(untrustedInput, r.Header)
dialer.Dial(untrustedInput, r.Header) // $ Alert
})
// gorilla websocket Dialer.Dial good
@@ -123,10 +123,10 @@ func test() {
// gorilla websocket Dialer.DialContext bad
http.HandleFunc("/ex8", func(w http.ResponseWriter, r *http.Request) {
untrustedInput := r.Referer()
untrustedInput := r.Referer() // $ Source
dialer := gorilla.Dialer{}
dialer.DialContext(context.TODO(), untrustedInput, r.Header)
dialer.DialContext(context.TODO(), untrustedInput, r.Header) // $ Alert
})
// gorilla websocket Dialer.DialContext good
@@ -151,22 +151,22 @@ func test() {
// gobwas websocket Dial bad
http.HandleFunc("/ex11", func(w http.ResponseWriter, r *http.Request) {
untrustedInput := r.Referer()
gobwas.Dial(context.TODO(), untrustedInput)
untrustedInput := r.Referer() // $ Source
gobwas.Dial(context.TODO(), untrustedInput) // $ Alert
})
// gobwas websocket Dialer.Dial bad
http.HandleFunc("/ex12", func(w http.ResponseWriter, r *http.Request) {
untrustedInput := r.Referer()
untrustedInput := r.Referer() // $ Source
dialer := gobwas.Dialer{}
dialer.Dial(context.TODO(), untrustedInput)
dialer.Dial(context.TODO(), untrustedInput) // $ Alert
})
// gobwas websocket Dialer.Dial good
http.HandleFunc("/ex12", func(w http.ResponseWriter, r *http.Request) {
untrustedInput := r.Referer()
if "localhost" == untrustedInput {
if untrustedInput == "localhost" {
dialer := gobwas.Dialer{}
dialer.Dial(context.TODO(), untrustedInput)
}
@@ -176,8 +176,8 @@ func test() {
http.HandleFunc("/ex13", func(w http.ResponseWriter, r *http.Request) {
untrustedInput := r.Referer()
if "localhost" == untrustedInput {
sac.New(untrustedInput)
if untrustedInput == "localhost" {
_ = sac.New(untrustedInput)
}
})
@@ -185,23 +185,23 @@ func test() {
http.HandleFunc("/ex14", func(w http.ResponseWriter, r *http.Request) {
untrustedInput := r.Referer()
if "localhost" == untrustedInput {
sac.BuildProxy(untrustedInput)
if untrustedInput == "localhost" {
_ = sac.BuildProxy(untrustedInput)
}
})
// sac007 websocket BuildProxy bad
http.HandleFunc("/ex15", func(w http.ResponseWriter, r *http.Request) {
untrustedInput := r.Referer()
untrustedInput := r.Referer() // $ Source
sac.BuildProxy(untrustedInput)
_ = sac.BuildProxy(untrustedInput) // $ Alert
})
// sac007 websocket New bad
http.HandleFunc("/ex16", func(w http.ResponseWriter, r *http.Request) {
untrustedInput := r.Referer()
untrustedInput := r.Referer() // $ Source
sac.New(untrustedInput)
_ = sac.New(untrustedInput) // $ Alert
})
log.Println(http.ListenAndServe(":80", nil))