diff --git a/go/ql/test/library-tests/semmle/go/security/SafeUrlFlow/SafeUrlFlow.expected b/go/ql/test/library-tests/semmle/go/security/SafeUrlFlow/SafeUrlFlow.expected index 4cbe81bf2be..79e0c9145fe 100644 --- a/go/ql/test/library-tests/semmle/go/security/SafeUrlFlow/SafeUrlFlow.expected +++ b/go/ql/test/library-tests/semmle/go/security/SafeUrlFlow/SafeUrlFlow.expected @@ -1,115 +1,115 @@ #select -| SafeUrlFlow.go:11:24:11:46 | ...+... | SafeUrlFlow.go:10:10:10:17 | selection of Host | SafeUrlFlow.go:11:24:11:46 | ...+... | A safe URL flows here from $@. | SafeUrlFlow.go:10:10:10:17 | selection of Host | here | +| SafeUrlFlow.go:11:24:11:50 | ...+... | SafeUrlFlow.go:10:14:10:21 | selection of Host | SafeUrlFlow.go:11:24:11:50 | ...+... | A safe URL flows here from $@. | SafeUrlFlow.go:10:14:10:21 | selection of Host | here | | SafeUrlFlow.go:14:29:14:44 | call to String | SafeUrlFlow.go:13:13:13:19 | selection of URL | SafeUrlFlow.go:14:29:14:44 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:13:13:13:19 | selection of URL | here | -| SafeUrlFlow.go:18:11:18:28 | call to String | SafeUrlFlow.go:10:10:10:17 | selection of Host | SafeUrlFlow.go:18:11:18:28 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:10:10:10:17 | selection of Host | here | -| SafeUrlFlow.go:47:24:47:57 | ...+... | SafeUrlFlow.go:37:13:37:19 | selection of URL | SafeUrlFlow.go:47:24:47:57 | ...+... | A safe URL flows here from $@. | SafeUrlFlow.go:37:13:37:19 | selection of URL | here | -| SafeUrlFlow.go:48:29:48:51 | ...+... | SafeUrlFlow.go:37:13:37:19 | selection of URL | SafeUrlFlow.go:48:29:48:51 | ...+... | A safe URL flows here from $@. | SafeUrlFlow.go:37:13:37:19 | selection of URL | here | -| SafeUrlFlow.go:49:11:49:38 | ...+... | SafeUrlFlow.go:37:13:37:19 | selection of URL | SafeUrlFlow.go:49:11:49:38 | ...+... | A safe URL flows here from $@. | SafeUrlFlow.go:37:13:37:19 | selection of URL | here | -| SafeUrlFlow.go:58:11:58:26 | call to String | SafeUrlFlow.go:55:13:55:19 | selection of URL | SafeUrlFlow.go:58:11:58:26 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:55:13:55:19 | selection of URL | here | -| SafeUrlFlow.go:59:12:59:27 | call to String | SafeUrlFlow.go:55:13:55:19 | selection of URL | SafeUrlFlow.go:59:12:59:27 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:55:13:55:19 | selection of URL | here | -| SafeUrlFlow.go:60:16:60:31 | call to String | SafeUrlFlow.go:55:13:55:19 | selection of URL | SafeUrlFlow.go:60:16:60:31 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:55:13:55:19 | selection of URL | here | -| SafeUrlFlow.go:61:12:61:27 | call to String | SafeUrlFlow.go:55:13:55:19 | selection of URL | SafeUrlFlow.go:61:12:61:27 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:55:13:55:19 | selection of URL | here | -| SafeUrlFlow.go:65:13:65:28 | call to String | SafeUrlFlow.go:55:13:55:19 | selection of URL | SafeUrlFlow.go:65:13:65:28 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:55:13:55:19 | selection of URL | here | -| SafeUrlFlow.go:66:14:66:29 | call to String | SafeUrlFlow.go:55:13:55:19 | selection of URL | SafeUrlFlow.go:66:14:66:29 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:55:13:55:19 | selection of URL | here | -| SafeUrlFlow.go:67:18:67:33 | call to String | SafeUrlFlow.go:55:13:55:19 | selection of URL | SafeUrlFlow.go:67:18:67:33 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:55:13:55:19 | selection of URL | here | -| SafeUrlFlow.go:68:14:68:29 | call to String | SafeUrlFlow.go:55:13:55:19 | selection of URL | SafeUrlFlow.go:68:14:68:29 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:55:13:55:19 | selection of URL | here | -| SafeUrlFlow.go:71:39:71:54 | call to String | SafeUrlFlow.go:55:13:55:19 | selection of URL | SafeUrlFlow.go:71:39:71:54 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:55:13:55:19 | selection of URL | here | -| SafeUrlFlow.go:75:70:75:85 | call to String | SafeUrlFlow.go:55:13:55:19 | selection of URL | SafeUrlFlow.go:75:70:75:85 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:55:13:55:19 | selection of URL | here | -| SafeUrlFlow.go:79:40:79:55 | call to String | SafeUrlFlow.go:55:13:55:19 | selection of URL | SafeUrlFlow.go:79:40:79:55 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:55:13:55:19 | selection of URL | here | -| SafeUrlFlow.go:90:24:90:41 | call to String | SafeUrlFlow.go:85:10:85:17 | selection of Host | SafeUrlFlow.go:90:24:90:41 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:85:10:85:17 | selection of Host | here | -| SafeUrlFlow.go:111:11:111:23 | reconstructed | SafeUrlFlow.go:101:13:101:19 | selection of URL | SafeUrlFlow.go:111:11:111:23 | reconstructed | A safe URL flows here from $@. | SafeUrlFlow.go:101:13:101:19 | selection of URL | here | -| SafeUrlFlow.go:114:24:114:46 | ...+... | SafeUrlFlow.go:101:13:101:19 | selection of URL | SafeUrlFlow.go:114:24:114:46 | ...+... | A safe URL flows here from $@. | SafeUrlFlow.go:101:13:101:19 | selection of URL | here | -| SafeUrlFlow.go:115:29:115:54 | ...+... | SafeUrlFlow.go:101:13:101:19 | selection of URL | SafeUrlFlow.go:115:29:115:54 | ...+... | A safe URL flows here from $@. | SafeUrlFlow.go:101:13:101:19 | selection of URL | here | -| SafeUrlFlow.go:116:12:116:38 | ...+... | SafeUrlFlow.go:101:13:101:19 | selection of URL | SafeUrlFlow.go:116:12:116:38 | ...+... | A safe URL flows here from $@. | SafeUrlFlow.go:101:13:101:19 | selection of URL | here | -| SafeUrlFlow.go:117:12:117:21 | opaquePart | SafeUrlFlow.go:101:13:101:19 | selection of URL | SafeUrlFlow.go:117:12:117:21 | opaquePart | A safe URL flows here from $@. | SafeUrlFlow.go:101:13:101:19 | selection of URL | here | +| SafeUrlFlow.go:18:11:18:28 | call to String | SafeUrlFlow.go:10:14:10:21 | selection of Host | SafeUrlFlow.go:18:11:18:28 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:10:14:10:21 | selection of Host | here | +| SafeUrlFlow.go:45:24:45:61 | ...+... | SafeUrlFlow.go:37:13:37:19 | selection of URL | SafeUrlFlow.go:45:24:45:61 | ...+... | A safe URL flows here from $@. | SafeUrlFlow.go:37:13:37:19 | selection of URL | here | +| SafeUrlFlow.go:46:29:46:55 | ...+... | SafeUrlFlow.go:37:13:37:19 | selection of URL | SafeUrlFlow.go:46:29:46:55 | ...+... | A safe URL flows here from $@. | SafeUrlFlow.go:37:13:37:19 | selection of URL | here | +| SafeUrlFlow.go:47:11:47:42 | ...+... | SafeUrlFlow.go:37:13:37:19 | selection of URL | SafeUrlFlow.go:47:11:47:42 | ...+... | A safe URL flows here from $@. | SafeUrlFlow.go:37:13:37:19 | selection of URL | here | +| SafeUrlFlow.go:57:11:57:26 | call to String | SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:57:11:57:26 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:54:13:54:19 | selection of URL | here | +| SafeUrlFlow.go:58:12:58:27 | call to String | SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:58:12:58:27 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:54:13:54:19 | selection of URL | here | +| SafeUrlFlow.go:59:16:59:31 | call to String | SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:59:16:59:31 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:54:13:54:19 | selection of URL | here | +| SafeUrlFlow.go:60:12:60:27 | call to String | SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:60:12:60:27 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:54:13:54:19 | selection of URL | here | +| SafeUrlFlow.go:64:13:64:28 | call to String | SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:64:13:64:28 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:54:13:54:19 | selection of URL | here | +| SafeUrlFlow.go:65:14:65:29 | call to String | SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:65:14:65:29 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:54:13:54:19 | selection of URL | here | +| SafeUrlFlow.go:66:18:66:33 | call to String | SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:66:18:66:33 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:54:13:54:19 | selection of URL | here | +| SafeUrlFlow.go:67:14:67:29 | call to String | SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:67:14:67:29 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:54:13:54:19 | selection of URL | here | +| SafeUrlFlow.go:70:39:70:54 | call to String | SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:70:39:70:54 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:54:13:54:19 | selection of URL | here | +| SafeUrlFlow.go:74:70:74:85 | call to String | SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:74:70:74:85 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:54:13:54:19 | selection of URL | here | +| SafeUrlFlow.go:78:40:78:55 | call to String | SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:78:40:78:55 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:54:13:54:19 | selection of URL | here | +| SafeUrlFlow.go:89:24:89:41 | call to String | SafeUrlFlow.go:84:14:84:21 | selection of Host | SafeUrlFlow.go:89:24:89:41 | call to String | A safe URL flows here from $@. | SafeUrlFlow.go:84:14:84:21 | selection of Host | here | +| SafeUrlFlow.go:109:11:109:23 | reconstructed | SafeUrlFlow.go:100:13:100:19 | selection of URL | SafeUrlFlow.go:109:11:109:23 | reconstructed | A safe URL flows here from $@. | SafeUrlFlow.go:100:13:100:19 | selection of URL | here | +| SafeUrlFlow.go:112:24:112:50 | ...+... | SafeUrlFlow.go:100:13:100:19 | selection of URL | SafeUrlFlow.go:112:24:112:50 | ...+... | A safe URL flows here from $@. | SafeUrlFlow.go:100:13:100:19 | selection of URL | here | +| SafeUrlFlow.go:113:29:113:58 | ...+... | SafeUrlFlow.go:100:13:100:19 | selection of URL | SafeUrlFlow.go:113:29:113:58 | ...+... | A safe URL flows here from $@. | SafeUrlFlow.go:100:13:100:19 | selection of URL | here | +| SafeUrlFlow.go:114:12:114:42 | ...+... | SafeUrlFlow.go:100:13:100:19 | selection of URL | SafeUrlFlow.go:114:12:114:42 | ...+... | A safe URL flows here from $@. | SafeUrlFlow.go:100:13:100:19 | selection of URL | here | +| SafeUrlFlow.go:115:12:115:25 | safeOpaquePart | SafeUrlFlow.go:100:13:100:19 | selection of URL | SafeUrlFlow.go:115:12:115:25 | safeOpaquePart | A safe URL flows here from $@. | SafeUrlFlow.go:100:13:100:19 | selection of URL | here | edges -| SafeUrlFlow.go:10:10:10:17 | selection of Host | SafeUrlFlow.go:11:24:11:46 | ...+... | provenance | Sink:MaD:1 | -| SafeUrlFlow.go:10:10:10:17 | selection of Host | SafeUrlFlow.go:17:19:17:22 | host | provenance | | -| SafeUrlFlow.go:13:13:13:19 | selection of URL | SafeUrlFlow.go:14:29:14:35 | baseURL | provenance | Src:MaD:2 | -| SafeUrlFlow.go:14:29:14:35 | baseURL | SafeUrlFlow.go:14:29:14:44 | call to String | provenance | MaD:3 | -| SafeUrlFlow.go:17:19:17:22 | host | SafeUrlFlow.go:18:11:18:19 | targetURL | provenance | Config | +| SafeUrlFlow.go:10:14:10:21 | selection of Host | SafeUrlFlow.go:11:24:11:50 | ...+... | provenance | Sink:MaD:1 | +| SafeUrlFlow.go:10:14:10:21 | selection of Host | SafeUrlFlow.go:17:19:17:26 | safeHost | provenance | | +| SafeUrlFlow.go:13:13:13:19 | selection of URL | SafeUrlFlow.go:14:29:14:35 | safeURL | provenance | Src:MaD:2 | +| SafeUrlFlow.go:14:29:14:35 | safeURL | SafeUrlFlow.go:14:29:14:44 | call to String | provenance | MaD:3 | +| SafeUrlFlow.go:17:19:17:26 | safeHost | SafeUrlFlow.go:18:11:18:19 | targetURL | provenance | Config | | SafeUrlFlow.go:18:11:18:19 | targetURL | SafeUrlFlow.go:18:11:18:28 | call to String | provenance | MaD:3 | -| SafeUrlFlow.go:37:13:37:19 | selection of URL | SafeUrlFlow.go:47:24:47:57 | ...+... | provenance | Src:MaD:2 Sink:MaD:1 | -| SafeUrlFlow.go:37:13:37:19 | selection of URL | SafeUrlFlow.go:48:29:48:51 | ...+... | provenance | Src:MaD:2 | -| SafeUrlFlow.go:37:13:37:19 | selection of URL | SafeUrlFlow.go:49:11:49:38 | ...+... | provenance | Src:MaD:2 | -| SafeUrlFlow.go:55:13:55:19 | selection of URL | SafeUrlFlow.go:58:11:58:17 | baseURL | provenance | Src:MaD:2 | -| SafeUrlFlow.go:55:13:55:19 | selection of URL | SafeUrlFlow.go:59:12:59:18 | baseURL | provenance | Src:MaD:2 | -| SafeUrlFlow.go:55:13:55:19 | selection of URL | SafeUrlFlow.go:60:16:60:22 | baseURL | provenance | Src:MaD:2 | -| SafeUrlFlow.go:55:13:55:19 | selection of URL | SafeUrlFlow.go:61:12:61:18 | baseURL | provenance | Src:MaD:2 | -| SafeUrlFlow.go:55:13:55:19 | selection of URL | SafeUrlFlow.go:65:13:65:19 | baseURL | provenance | Src:MaD:2 | -| SafeUrlFlow.go:55:13:55:19 | selection of URL | SafeUrlFlow.go:66:14:66:20 | baseURL | provenance | Src:MaD:2 | -| SafeUrlFlow.go:55:13:55:19 | selection of URL | SafeUrlFlow.go:67:18:67:24 | baseURL | provenance | Src:MaD:2 | -| SafeUrlFlow.go:55:13:55:19 | selection of URL | SafeUrlFlow.go:68:14:68:20 | baseURL | provenance | Src:MaD:2 | -| SafeUrlFlow.go:55:13:55:19 | selection of URL | SafeUrlFlow.go:71:39:71:45 | baseURL | provenance | Src:MaD:2 | -| SafeUrlFlow.go:55:13:55:19 | selection of URL | SafeUrlFlow.go:75:70:75:76 | baseURL | provenance | Src:MaD:2 | -| SafeUrlFlow.go:55:13:55:19 | selection of URL | SafeUrlFlow.go:79:40:79:46 | baseURL | provenance | Src:MaD:2 | -| SafeUrlFlow.go:58:11:58:17 | baseURL | SafeUrlFlow.go:58:11:58:26 | call to String | provenance | MaD:3 | -| SafeUrlFlow.go:59:12:59:18 | baseURL | SafeUrlFlow.go:59:12:59:27 | call to String | provenance | MaD:3 | -| SafeUrlFlow.go:60:16:60:22 | baseURL | SafeUrlFlow.go:60:16:60:31 | call to String | provenance | MaD:3 | -| SafeUrlFlow.go:61:12:61:18 | baseURL | SafeUrlFlow.go:61:12:61:27 | call to String | provenance | MaD:3 | -| SafeUrlFlow.go:65:13:65:19 | baseURL | SafeUrlFlow.go:65:13:65:28 | call to String | provenance | MaD:3 | -| SafeUrlFlow.go:66:14:66:20 | baseURL | SafeUrlFlow.go:66:14:66:29 | call to String | provenance | MaD:3 | -| SafeUrlFlow.go:67:18:67:24 | baseURL | SafeUrlFlow.go:67:18:67:33 | call to String | provenance | MaD:3 | -| SafeUrlFlow.go:68:14:68:20 | baseURL | SafeUrlFlow.go:68:14:68:29 | call to String | provenance | MaD:3 | -| SafeUrlFlow.go:71:39:71:45 | baseURL | SafeUrlFlow.go:71:39:71:54 | call to String | provenance | MaD:3 | -| SafeUrlFlow.go:75:70:75:76 | baseURL | SafeUrlFlow.go:75:70:75:85 | call to String | provenance | MaD:3 | -| SafeUrlFlow.go:79:40:79:46 | baseURL | SafeUrlFlow.go:79:40:79:55 | call to String | provenance | MaD:3 | -| SafeUrlFlow.go:85:10:85:17 | selection of Host | SafeUrlFlow.go:88:19:88:22 | host | provenance | | -| SafeUrlFlow.go:88:19:88:22 | host | SafeUrlFlow.go:90:24:90:32 | targetURL | provenance | Config | -| SafeUrlFlow.go:90:24:90:32 | targetURL | SafeUrlFlow.go:90:24:90:41 | call to String | provenance | MaD:3 Sink:MaD:1 | -| SafeUrlFlow.go:101:13:101:19 | selection of URL | SafeUrlFlow.go:111:11:111:23 | reconstructed | provenance | Src:MaD:2 | -| SafeUrlFlow.go:101:13:101:19 | selection of URL | SafeUrlFlow.go:114:24:114:46 | ...+... | provenance | Src:MaD:2 Sink:MaD:1 | -| SafeUrlFlow.go:101:13:101:19 | selection of URL | SafeUrlFlow.go:115:29:115:54 | ...+... | provenance | Src:MaD:2 | -| SafeUrlFlow.go:101:13:101:19 | selection of URL | SafeUrlFlow.go:116:12:116:38 | ...+... | provenance | Src:MaD:2 | -| SafeUrlFlow.go:101:13:101:19 | selection of URL | SafeUrlFlow.go:117:12:117:21 | opaquePart | provenance | Src:MaD:2 | +| SafeUrlFlow.go:37:13:37:19 | selection of URL | SafeUrlFlow.go:45:24:45:61 | ...+... | provenance | Src:MaD:2 Sink:MaD:1 | +| SafeUrlFlow.go:37:13:37:19 | selection of URL | SafeUrlFlow.go:46:29:46:55 | ...+... | provenance | Src:MaD:2 | +| SafeUrlFlow.go:37:13:37:19 | selection of URL | SafeUrlFlow.go:47:11:47:42 | ...+... | provenance | Src:MaD:2 | +| SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:57:11:57:17 | safeURL | provenance | Src:MaD:2 | +| SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:58:12:58:18 | safeURL | provenance | Src:MaD:2 | +| SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:59:16:59:22 | safeURL | provenance | Src:MaD:2 | +| SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:60:12:60:18 | safeURL | provenance | Src:MaD:2 | +| SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:64:13:64:19 | safeURL | provenance | Src:MaD:2 | +| SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:65:14:65:20 | safeURL | provenance | Src:MaD:2 | +| SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:66:18:66:24 | safeURL | provenance | Src:MaD:2 | +| SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:67:14:67:20 | safeURL | provenance | Src:MaD:2 | +| SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:70:39:70:45 | safeURL | provenance | Src:MaD:2 | +| SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:74:70:74:76 | safeURL | provenance | Src:MaD:2 | +| SafeUrlFlow.go:54:13:54:19 | selection of URL | SafeUrlFlow.go:78:40:78:46 | safeURL | provenance | Src:MaD:2 | +| SafeUrlFlow.go:57:11:57:17 | safeURL | SafeUrlFlow.go:57:11:57:26 | call to String | provenance | MaD:3 | +| SafeUrlFlow.go:58:12:58:18 | safeURL | SafeUrlFlow.go:58:12:58:27 | call to String | provenance | MaD:3 | +| SafeUrlFlow.go:59:16:59:22 | safeURL | SafeUrlFlow.go:59:16:59:31 | call to String | provenance | MaD:3 | +| SafeUrlFlow.go:60:12:60:18 | safeURL | SafeUrlFlow.go:60:12:60:27 | call to String | provenance | MaD:3 | +| SafeUrlFlow.go:64:13:64:19 | safeURL | SafeUrlFlow.go:64:13:64:28 | call to String | provenance | MaD:3 | +| SafeUrlFlow.go:65:14:65:20 | safeURL | SafeUrlFlow.go:65:14:65:29 | call to String | provenance | MaD:3 | +| SafeUrlFlow.go:66:18:66:24 | safeURL | SafeUrlFlow.go:66:18:66:33 | call to String | provenance | MaD:3 | +| SafeUrlFlow.go:67:14:67:20 | safeURL | SafeUrlFlow.go:67:14:67:29 | call to String | provenance | MaD:3 | +| SafeUrlFlow.go:70:39:70:45 | safeURL | SafeUrlFlow.go:70:39:70:54 | call to String | provenance | MaD:3 | +| SafeUrlFlow.go:74:70:74:76 | safeURL | SafeUrlFlow.go:74:70:74:85 | call to String | provenance | MaD:3 | +| SafeUrlFlow.go:78:40:78:46 | safeURL | SafeUrlFlow.go:78:40:78:55 | call to String | provenance | MaD:3 | +| SafeUrlFlow.go:84:14:84:21 | selection of Host | SafeUrlFlow.go:87:19:87:26 | safeHost | provenance | | +| SafeUrlFlow.go:87:19:87:26 | safeHost | SafeUrlFlow.go:89:24:89:32 | targetURL | provenance | Config | +| SafeUrlFlow.go:89:24:89:32 | targetURL | SafeUrlFlow.go:89:24:89:41 | call to String | provenance | MaD:3 Sink:MaD:1 | +| SafeUrlFlow.go:100:13:100:19 | selection of URL | SafeUrlFlow.go:109:11:109:23 | reconstructed | provenance | Src:MaD:2 | +| SafeUrlFlow.go:100:13:100:19 | selection of URL | SafeUrlFlow.go:112:24:112:50 | ...+... | provenance | Src:MaD:2 Sink:MaD:1 | +| SafeUrlFlow.go:100:13:100:19 | selection of URL | SafeUrlFlow.go:113:29:113:58 | ...+... | provenance | Src:MaD:2 | +| SafeUrlFlow.go:100:13:100:19 | selection of URL | SafeUrlFlow.go:114:12:114:42 | ...+... | provenance | Src:MaD:2 | +| SafeUrlFlow.go:100:13:100:19 | selection of URL | SafeUrlFlow.go:115:12:115:25 | safeOpaquePart | provenance | Src:MaD:2 | models | 1 | Sink: net/http; ; false; Redirect; ; ; Argument[2]; url-redirection[0]; manual | | 2 | Source: net/http; Request; true; URL; ; ; ; remote; manual | | 3 | Summary: fmt; Stringer; true; String; ; ; Argument[receiver]; ReturnValue; taint; manual | nodes -| SafeUrlFlow.go:10:10:10:17 | selection of Host | semmle.label | selection of Host | -| SafeUrlFlow.go:11:24:11:46 | ...+... | semmle.label | ...+... | +| SafeUrlFlow.go:10:14:10:21 | selection of Host | semmle.label | selection of Host | +| SafeUrlFlow.go:11:24:11:50 | ...+... | semmle.label | ...+... | | SafeUrlFlow.go:13:13:13:19 | selection of URL | semmle.label | selection of URL | -| SafeUrlFlow.go:14:29:14:35 | baseURL | semmle.label | baseURL | +| SafeUrlFlow.go:14:29:14:35 | safeURL | semmle.label | safeURL | | SafeUrlFlow.go:14:29:14:44 | call to String | semmle.label | call to String | -| SafeUrlFlow.go:17:19:17:22 | host | semmle.label | host | +| SafeUrlFlow.go:17:19:17:26 | safeHost | semmle.label | safeHost | | SafeUrlFlow.go:18:11:18:19 | targetURL | semmle.label | targetURL | | SafeUrlFlow.go:18:11:18:28 | call to String | semmle.label | call to String | | SafeUrlFlow.go:37:13:37:19 | selection of URL | semmle.label | selection of URL | -| SafeUrlFlow.go:47:24:47:57 | ...+... | semmle.label | ...+... | -| SafeUrlFlow.go:48:29:48:51 | ...+... | semmle.label | ...+... | -| SafeUrlFlow.go:49:11:49:38 | ...+... | semmle.label | ...+... | -| SafeUrlFlow.go:55:13:55:19 | selection of URL | semmle.label | selection of URL | -| SafeUrlFlow.go:58:11:58:17 | baseURL | semmle.label | baseURL | -| SafeUrlFlow.go:58:11:58:26 | call to String | semmle.label | call to String | -| SafeUrlFlow.go:59:12:59:18 | baseURL | semmle.label | baseURL | -| SafeUrlFlow.go:59:12:59:27 | call to String | semmle.label | call to String | -| SafeUrlFlow.go:60:16:60:22 | baseURL | semmle.label | baseURL | -| SafeUrlFlow.go:60:16:60:31 | call to String | semmle.label | call to String | -| SafeUrlFlow.go:61:12:61:18 | baseURL | semmle.label | baseURL | -| SafeUrlFlow.go:61:12:61:27 | call to String | semmle.label | call to String | -| SafeUrlFlow.go:65:13:65:19 | baseURL | semmle.label | baseURL | -| SafeUrlFlow.go:65:13:65:28 | call to String | semmle.label | call to String | -| SafeUrlFlow.go:66:14:66:20 | baseURL | semmle.label | baseURL | -| SafeUrlFlow.go:66:14:66:29 | call to String | semmle.label | call to String | -| SafeUrlFlow.go:67:18:67:24 | baseURL | semmle.label | baseURL | -| SafeUrlFlow.go:67:18:67:33 | call to String | semmle.label | call to String | -| SafeUrlFlow.go:68:14:68:20 | baseURL | semmle.label | baseURL | -| SafeUrlFlow.go:68:14:68:29 | call to String | semmle.label | call to String | -| SafeUrlFlow.go:71:39:71:45 | baseURL | semmle.label | baseURL | -| SafeUrlFlow.go:71:39:71:54 | call to String | semmle.label | call to String | -| SafeUrlFlow.go:75:70:75:76 | baseURL | semmle.label | baseURL | -| SafeUrlFlow.go:75:70:75:85 | call to String | semmle.label | call to String | -| SafeUrlFlow.go:79:40:79:46 | baseURL | semmle.label | baseURL | -| SafeUrlFlow.go:79:40:79:55 | call to String | semmle.label | call to String | -| SafeUrlFlow.go:85:10:85:17 | selection of Host | semmle.label | selection of Host | -| SafeUrlFlow.go:88:19:88:22 | host | semmle.label | host | -| SafeUrlFlow.go:90:24:90:32 | targetURL | semmle.label | targetURL | -| SafeUrlFlow.go:90:24:90:41 | call to String | semmle.label | call to String | -| SafeUrlFlow.go:101:13:101:19 | selection of URL | semmle.label | selection of URL | -| SafeUrlFlow.go:111:11:111:23 | reconstructed | semmle.label | reconstructed | -| SafeUrlFlow.go:114:24:114:46 | ...+... | semmle.label | ...+... | -| SafeUrlFlow.go:115:29:115:54 | ...+... | semmle.label | ...+... | -| SafeUrlFlow.go:116:12:116:38 | ...+... | semmle.label | ...+... | -| SafeUrlFlow.go:117:12:117:21 | opaquePart | semmle.label | opaquePart | +| SafeUrlFlow.go:45:24:45:61 | ...+... | semmle.label | ...+... | +| SafeUrlFlow.go:46:29:46:55 | ...+... | semmle.label | ...+... | +| SafeUrlFlow.go:47:11:47:42 | ...+... | semmle.label | ...+... | +| SafeUrlFlow.go:54:13:54:19 | selection of URL | semmle.label | selection of URL | +| SafeUrlFlow.go:57:11:57:17 | safeURL | semmle.label | safeURL | +| SafeUrlFlow.go:57:11:57:26 | call to String | semmle.label | call to String | +| SafeUrlFlow.go:58:12:58:18 | safeURL | semmle.label | safeURL | +| SafeUrlFlow.go:58:12:58:27 | call to String | semmle.label | call to String | +| SafeUrlFlow.go:59:16:59:22 | safeURL | semmle.label | safeURL | +| SafeUrlFlow.go:59:16:59:31 | call to String | semmle.label | call to String | +| SafeUrlFlow.go:60:12:60:18 | safeURL | semmle.label | safeURL | +| SafeUrlFlow.go:60:12:60:27 | call to String | semmle.label | call to String | +| SafeUrlFlow.go:64:13:64:19 | safeURL | semmle.label | safeURL | +| SafeUrlFlow.go:64:13:64:28 | call to String | semmle.label | call to String | +| SafeUrlFlow.go:65:14:65:20 | safeURL | semmle.label | safeURL | +| SafeUrlFlow.go:65:14:65:29 | call to String | semmle.label | call to String | +| SafeUrlFlow.go:66:18:66:24 | safeURL | semmle.label | safeURL | +| SafeUrlFlow.go:66:18:66:33 | call to String | semmle.label | call to String | +| SafeUrlFlow.go:67:14:67:20 | safeURL | semmle.label | safeURL | +| SafeUrlFlow.go:67:14:67:29 | call to String | semmle.label | call to String | +| SafeUrlFlow.go:70:39:70:45 | safeURL | semmle.label | safeURL | +| SafeUrlFlow.go:70:39:70:54 | call to String | semmle.label | call to String | +| SafeUrlFlow.go:74:70:74:76 | safeURL | semmle.label | safeURL | +| SafeUrlFlow.go:74:70:74:85 | call to String | semmle.label | call to String | +| SafeUrlFlow.go:78:40:78:46 | safeURL | semmle.label | safeURL | +| SafeUrlFlow.go:78:40:78:55 | call to String | semmle.label | call to String | +| SafeUrlFlow.go:84:14:84:21 | selection of Host | semmle.label | selection of Host | +| SafeUrlFlow.go:87:19:87:26 | safeHost | semmle.label | safeHost | +| SafeUrlFlow.go:89:24:89:32 | targetURL | semmle.label | targetURL | +| SafeUrlFlow.go:89:24:89:41 | call to String | semmle.label | call to String | +| SafeUrlFlow.go:100:13:100:19 | selection of URL | semmle.label | selection of URL | +| SafeUrlFlow.go:109:11:109:23 | reconstructed | semmle.label | reconstructed | +| SafeUrlFlow.go:112:24:112:50 | ...+... | semmle.label | ...+... | +| SafeUrlFlow.go:113:29:113:58 | ...+... | semmle.label | ...+... | +| SafeUrlFlow.go:114:12:114:42 | ...+... | semmle.label | ...+... | +| SafeUrlFlow.go:115:12:115:25 | safeOpaquePart | semmle.label | safeOpaquePart | subpaths diff --git a/go/ql/test/library-tests/semmle/go/security/SafeUrlFlow/SafeUrlFlow.go b/go/ql/test/library-tests/semmle/go/security/SafeUrlFlow/SafeUrlFlow.go index 45a2b20b8d4..9a1b2e5677e 100644 --- a/go/ql/test/library-tests/semmle/go/security/SafeUrlFlow/SafeUrlFlow.go +++ b/go/ql/test/library-tests/semmle/go/security/SafeUrlFlow/SafeUrlFlow.go @@ -7,126 +7,120 @@ import ( ) func testStdlibSources(w http.ResponseWriter, req *http.Request) { - host := req.Host // $ Source - http.Redirect(w, req, "https://"+host+"/path", http.StatusFound) // $ Alert + safeHost := req.Host // $ Source + http.Redirect(w, req, "https://"+safeHost+"/path", http.StatusFound) // $ Alert - baseURL := req.URL // $ Source - w.Header().Set("Location", baseURL.String()) // $ Alert + safeURL := req.URL // $ Source + w.Header().Set("Location", safeURL.String()) // $ Alert targetURL := url.URL{} - targetURL.Host = host // additional flow step from Host field to URL struct + targetURL.Host = safeHost // URL is safe if Host is safe http.Get(targetURL.String()) // $ Alert } func testBarrierEdge1(w http.ResponseWriter, req *http.Request) { - baseURL := req.URL + safeURL := req.URL - query := baseURL.Query() // barrier edge blocks flow here - http.Redirect(w, req, query.Get("redirect"), http.StatusFound) // no flow expected + query := safeURL.Query() // query is not guaranteed to be safe + http.Redirect(w, req, query.Get("redirect"), http.StatusFound) // not guaranteed to be safe } func testBarrierEdge2(w http.ResponseWriter, req *http.Request) { - baseURL := req.URL + safeURL := req.URL - urlString := baseURL.String() - sliced := urlString[0:10] // barrier edge (string slicing) blocks flow here - w.Header().Set("Location", sliced) // no flow expected + urlString := safeURL.String() + sliced := urlString[0:10] // a substring of a safe URL is not guaranteed to be safe + w.Header().Set("Location", sliced) // not guaranteed to be safe } func testFieldReads(w http.ResponseWriter, req *http.Request) { - baseURL := req.URL // $ Source + safeURL := req.URL // $ Source - // Test that other URL methods preserve flow - scheme := baseURL.Scheme // should preserve flow - host := baseURL.Host // should preserve flow - path := baseURL.Path // should preserve flow - fragment := baseURL.Fragment // should not preserve flow - user := baseURL.User // should not preserve flow + safeScheme := safeURL.Scheme // the scheme of a safe URL is safe + safeHost := safeURL.Host // the host of a safe URL is safe + safePath := safeURL.Path // the path of a safe URL is safe + fragment := safeURL.Fragment // the fragment of a safe URL is not guaranteed to be safe + user := safeURL.User // the user of a safe URL is not guaranteed to be safe - // These should still have flow (not sanitized) - http.Redirect(w, req, "https://"+scheme+"://example.com", http.StatusFound) // $ Alert - w.Header().Set("Location", "https://"+host+"/path") // $ Alert - http.Get("https://example.com" + path) // $ Alert - http.Get(fragment) - http.Get(user.String()) + http.Redirect(w, req, "https://"+safeScheme+"://example.com", http.StatusFound) // $ Alert + w.Header().Set("Location", "https://"+safeHost+"/path") // $ Alert + http.Get("https://example.com" + safePath) // $ Alert + + http.Get(fragment) // not guaranteed to be safe + http.Get(user.String()) // not guaranteed to be safe } func testRequestForgerySinks(req *http.Request) { - baseURL := req.URL // $ Source + safeURL := req.URL // $ Source // Standard library HTTP functions (request-forgery sinks) - http.Get(baseURL.String()) // $ Alert - http.Post(baseURL.String(), "application/json", nil) // $ Alert - http.PostForm(baseURL.String(), nil) // $ Alert - http.Head(baseURL.String()) // $ Alert + http.Get(safeURL.String()) // $ Alert + http.Post(safeURL.String(), "application/json", nil) // $ Alert + http.PostForm(safeURL.String(), nil) // $ Alert + http.Head(safeURL.String()) // $ Alert // HTTP Client methods (request-forgery sinks) client := &http.Client{} - client.Get(baseURL.String()) // $ Alert - client.Post(baseURL.String(), "application/json", nil) // $ Alert - client.PostForm(baseURL.String(), nil) // $ Alert - client.Head(baseURL.String()) // $ Alert + client.Get(safeURL.String()) // $ Alert + client.Post(safeURL.String(), "application/json", nil) // $ Alert + client.PostForm(safeURL.String(), nil) // $ Alert + client.Head(safeURL.String()) // $ Alert // NewRequest + Client.Do (request-forgery sinks) - request, _ := http.NewRequest("GET", baseURL.String(), nil) // $ Alert + request, _ := http.NewRequest("GET", safeURL.String(), nil) // $ Alert client.Do(request) // NewRequestWithContext + Client.Do (request-forgery sinks) - reqWithCtx, _ := http.NewRequestWithContext(context.TODO(), "POST", baseURL.String(), nil) // $ Alert + reqWithCtx, _ := http.NewRequestWithContext(context.TODO(), "POST", safeURL.String(), nil) // $ Alert client.Do(reqWithCtx) // RoundTrip method (request-forgery sink) - request2, _ := http.NewRequest("GET", baseURL.String(), nil) // $ Alert + request2, _ := http.NewRequest("GET", safeURL.String(), nil) // $ Alert transport := &http.Transport{} transport.RoundTrip(request2) } func testHostFieldAssignmentFlow(w http.ResponseWriter, req *http.Request) { - host := req.Host // $ Source + safeHost := req.Host // $ Source targetURL, _ := url.Parse("http://example.com/data") - targetURL.Host = host // additional flow step from Host field to URL struct + targetURL.Host = safeHost // URL is safe if Host is safe http.Redirect(w, req, targetURL.String(), http.StatusFound) // $ Alert } func testHostFieldOverwritten(w http.ResponseWriter, req *http.Request) { - baseURL := req.URL + safeURL := req.URL - baseURL.Host = "something.else.com" // barrier edge (Host field overwritten) blocks flow here - http.Get(baseURL.String()) + safeURL.Host = "something.else.com" // safeURL is not guaranteed to be safe now that Host is overwritten + http.Get(safeURL.String()) // not guaranteed to be safe } func testFieldAccess(w http.ResponseWriter, req *http.Request) { - baseURL := req.URL // $ Source + safeURL := req.URL // $ Source - // These field accesses should preserve flow - host := baseURL.Host - path := baseURL.Path - scheme := baseURL.Scheme - opaquePart := baseURL.Opaque + safeHost := safeURL.Host // the host of a safe URL is safe + safePath := safeURL.Path // the path of a safe URL is safe + safeScheme := safeURL.Scheme // the scheme of a safe URL is safe + safeOpaquePart := safeURL.Opaque // the opaque part of a safe URL is safe - // Reconstruct URL - flow should be preserved through field access - reconstructed := scheme + "://" + host + path + // Reconstruct URL - still guaranteed to be safe + reconstructed := safeScheme + "://" + safeHost + safePath http.Get(reconstructed) // $ Alert // Test individual fields - http.Redirect(w, req, "https://"+host+"/path", http.StatusFound) // $ Alert - w.Header().Set("Location", "https://example.com"+path) // $ Alert - http.Post(scheme+"://example.com/api", "application/json", nil) // $ Alert - http.Post(opaquePart, "application/json", nil) // $ Alert + http.Redirect(w, req, "https://"+safeHost+"/path", http.StatusFound) // $ Alert + w.Header().Set("Location", "https://example.com"+safePath) // $ Alert + http.Post(safeScheme+"://example.com/api", "application/json", nil) // $ Alert + http.Post(safeOpaquePart, "application/json", nil) // $ Alert - // These field accesses should block flow - user := baseURL.User // barrier edge (User field) - query := baseURL.RawQuery // barrier edge (RawQuery field) - fragment := baseURL.Fragment // barrier edge (Fragment field) + user := safeURL.User // the user of a safe URL is not guaranteed to be safe + query := safeURL.RawQuery // the query of a safe URL is not guaranteed to be safe + fragment := safeURL.Fragment // the fragment of a safe URL is not guaranteed to be safe if user != nil { - http.Redirect(w, req, user.String(), http.StatusFound) // no flow expected + http.Redirect(w, req, user.String(), http.StatusFound) // not guaranteed to be safe } - w.Header().Set("Location", "https://example.com/?"+query) // no flow expected - http.Get("https://example.com/#" + fragment) // no flow expected + w.Header().Set("Location", "https://example.com/?"+query) // not guaranteed to be safe + http.Get("https://example.com/#" + fragment) // not guaranteed to be safe } - -// Helper function to avoid unused variable warnings -func use(vars ...interface{}) {}