seaworthycode 1.1.2 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/dist/index.js +739 -42
  2. package/dist/index.js.map +1 -1
  3. package/package.json +14 -12
  4. package/rules/external/configuration/insecure-cookie-flags.test.yaml +114 -0
  5. package/rules/external/configuration/insecure-cookie-flags.yaml +77 -0
  6. package/rules/external/configuration/missing-ssl-verification.test.yaml +130 -0
  7. package/rules/external/configuration/missing-ssl-verification.yaml +123 -0
  8. package/rules/external/data-exposure/debug-artifacts.test.yaml +143 -0
  9. package/rules/external/data-exposure/debug-artifacts.yaml +57 -0
  10. package/rules/external/data-exposure/hardcoded-ip.test.yaml +131 -0
  11. package/rules/external/data-exposure/hardcoded-ip.yaml +67 -0
  12. package/rules/external/data-exposure/localstorage-sensitive-data.test.yaml +58 -0
  13. package/rules/external/data-exposure/localstorage-sensitive-data.yaml +60 -0
  14. package/rules/external/dependencies/deprecated-functions.test.yaml +92 -0
  15. package/rules/external/dependencies/deprecated-functions.yaml +66 -0
  16. package/rules/external/ops/hardcoded-port.test.yaml +141 -0
  17. package/rules/external/ops/hardcoded-port.yaml +91 -0
  18. package/rules/external/ops/insecure-file-permissions.test.yaml +111 -0
  19. package/rules/external/ops/insecure-file-permissions.yaml +91 -0
  20. package/rules/external/resilience/missing-memory-limit.test.yaml +54 -0
  21. package/rules/external/resilience/missing-memory-limit.yaml +59 -0
  22. package/rules/external/resilience/missing-timeout-config.test.yaml +179 -0
  23. package/rules/external/resilience/missing-timeout-config.yaml +124 -0
  24. package/rules/external/security/broken-crypto-algorithm.test.yaml +104 -0
  25. package/rules/external/security/broken-crypto-algorithm.yaml +79 -0
  26. package/rules/external/security/http-method-override.test.yaml +40 -0
  27. package/rules/external/security/http-method-override.yaml +35 -0
  28. package/rules/external/security/http-no-tls.test.yaml +115 -0
  29. package/rules/external/security/http-no-tls.yaml +59 -0
  30. package/rules/external/security/path-traversal.test.yaml +188 -0
  31. package/rules/external/security/path-traversal.yaml +210 -0
  32. package/rules/external/security/unsafe-innerhtml.test.yaml +72 -0
  33. package/rules/external/security/unsafe-innerhtml.yaml +46 -0
  34. package/rules/external/security/untrusted-deserialization.test.yaml +79 -0
  35. package/rules/external/security/untrusted-deserialization.yaml +48 -0
  36. package/rules/external/security/weak-encryption-mode.test.yaml +126 -0
  37. package/rules/external/security/weak-encryption-mode.yaml +104 -0
  38. package/rules/external/security/weak-hash-algorithm.test.yaml +121 -0
  39. package/rules/external/security/weak-hash-algorithm.yaml +87 -0
  40. package/rules/external/security/xxe-parsing.test.yaml +76 -0
  41. package/rules/external/security/xxe-parsing.yaml +63 -0
  42. package/rules/internal/security/dangerous-eval.test.yaml +126 -0
  43. package/rules/internal/security/dangerous-eval.yaml +134 -0
  44. package/rules/internal/security/no-document-write.test.yaml +33 -0
  45. package/rules/internal/security/no-document-write.yaml +40 -0
  46. package/rules/internal/taint/MATRIX.md +16 -0
  47. package/rules/internal/taint/bash.test.yaml +84 -0
  48. package/rules/internal/taint/bash.yaml +166 -0
  49. package/rules/internal/taint/dvwa.test.yaml +217 -0
  50. package/rules/internal/taint/go.test.yaml +207 -0
  51. package/rules/internal/taint/go.yaml +325 -0
  52. package/rules/internal/taint/java.test.yaml +158 -0
  53. package/rules/internal/taint/java.yaml +318 -0
  54. package/rules/internal/taint/javascript.test.yaml +374 -0
  55. package/rules/internal/taint/javascript.yaml +439 -0
  56. package/rules/internal/taint/php.test.yaml +134 -0
  57. package/rules/internal/taint/php.yaml +331 -0
  58. package/rules/internal/taint/python.test.yaml +427 -0
  59. package/rules/internal/taint/python.yaml +636 -0
  60. package/rules/internal/taint/ruby.test.yaml +148 -0
  61. package/rules/internal/taint/ruby.yaml +233 -0
  62. package/rules/internal/taint/rust.test.yaml +585 -0
  63. package/rules/internal/taint/rust.yaml +483 -0
  64. package/rules/internal/taint/tsx.test.yaml +140 -0
  65. package/rules/internal/taint/tsx.yaml +51 -0
  66. package/rules/internal/taint/typescript.test.yaml +393 -0
  67. package/rules/internal/taint/typescript.yaml +660 -0
  68. package/wasm/tree-sitter-sql.wasm +0 -0
@@ -0,0 +1,84 @@
1
+ language: bash
2
+ cases:
3
+ - name: "SQL injection from positional argument to psql"
4
+ language: bash
5
+ code: |
6
+ QUERY="$1"
7
+ psql -c "$QUERY"
8
+ expect:
9
+ count: 1
10
+ flows:
11
+ - sourceId: bash.argv
12
+ sinkId: bash.psql
13
+
14
+ - name: "XSS from interactive read to CGI echo"
15
+ language: bash
16
+ code: |
17
+ read INPUT
18
+ echo "$INPUT"
19
+ expect:
20
+ count: 1
21
+ flows:
22
+ - sourceId: bash.read
23
+ sinkId: bash.cgi_echo
24
+
25
+ - name: "Path traversal from positional argument to rm"
26
+ language: bash
27
+ code: |
28
+ DIR="$1"
29
+ rm -rf "$DIR/"
30
+ expect:
31
+ count: 1
32
+ flows:
33
+ - sourceId: bash.argv
34
+ sinkId: bash.path
35
+
36
+ - name: "Command injection from positional argument to eval"
37
+ language: bash
38
+ code: |
39
+ CMD="$1"
40
+ eval "$CMD"
41
+ expect:
42
+ count: 1
43
+ flows:
44
+ - sourceId: bash.argv
45
+ sinkId: bash.eval
46
+
47
+ - name: "Code execution direct positional argument to eval"
48
+ language: bash
49
+ code: |
50
+ eval "$1"
51
+ expect:
52
+ count: 1
53
+ flows:
54
+ - sourceId: bash.argv
55
+ sinkId: bash.eval
56
+
57
+ - name: "URL injection from positional argument to curl"
58
+ language: bash
59
+ code: |
60
+ URL="$1"
61
+ curl "$URL"
62
+ expect:
63
+ count: 1
64
+ flows:
65
+ - sourceId: bash.argv
66
+ sinkId: bash.url
67
+
68
+ - name: "SQL injection sanitised by regex validation"
69
+ language: bash
70
+ code: |
71
+ [[ "$1" =~ ^[0-9]+$ ]] && psql -c "$1"
72
+ expect:
73
+ count: 0
74
+
75
+ - name: "Command injection sanitised by quoted expansion"
76
+ language: bash
77
+ code: |
78
+ MODE="$1"
79
+ exec "$MODE"
80
+ expect:
81
+ count: 1
82
+ flows:
83
+ - sourceId: bash.argv
84
+ sinkId: bash.exec
@@ -0,0 +1,166 @@
1
+ # attribution: CWE-78
2
+ attribution: CWE-78
3
+ language: bash
4
+ applies-to: []
5
+
6
+ sources:
7
+ - id: bash.argv
8
+ class: cli-arg
9
+ query: |
10
+ ((simple_expansion (variable_name) @name) @source
11
+ (#match? @name "^[0-9]+$"))
12
+
13
+ - id: bash.argv.all
14
+ class: cli-arg
15
+ query: |
16
+ ((simple_expansion (special_variable_name) @name) @source
17
+ (#match? @name "^[@*]$"))
18
+
19
+ - id: bash.read
20
+ class: interactive-input
21
+ query: |
22
+ (command
23
+ name: (command_name (word) @cmd)
24
+ argument: (word) @source
25
+ (#eq? @cmd "read"))
26
+
27
+ - id: bash.env
28
+ class: env
29
+ query: |
30
+ ((simple_expansion (variable_name) @name) @source
31
+ (#match? @name "^(HOME|PATH|USER|SHELL|PWD|TMPDIR|QUERY_STRING|REQUEST_METHOD|CONTENT_TYPE|CONTENT_LENGTH)$"))
32
+
33
+ - id: bash.command_substitution
34
+ class: external-input
35
+ query: |
36
+ (command_substitution) @source
37
+
38
+ - id: bash.stdin
39
+ class: stdin
40
+ query: |
41
+ (pipeline) @source
42
+
43
+ sinks:
44
+ - id: bash.eval
45
+ sink-class: code-execution
46
+ query: |
47
+ (command
48
+ name: (command_name (word) @cmd)
49
+ argument: (_) @sink
50
+ (#match? @cmd "^(eval|source|\\.)$"))
51
+
52
+ - id: bash.bash_c
53
+ sink-class: code-execution
54
+ query: |
55
+ (command
56
+ name: (command_name (word) @cmd)
57
+ argument: (word) @flag
58
+ argument: (_) @sink
59
+ (#match? @cmd "^(bash|sh|zsh)$")
60
+ (#eq? @flag "-c"))
61
+
62
+ - id: bash.dynamic_command
63
+ sink-class: command-injection
64
+ query: |
65
+ (command
66
+ name: (command_name (simple_expansion) @sink))
67
+
68
+ - id: bash.exec
69
+ sink-class: command-injection
70
+ query: |
71
+ (command
72
+ name: (command_name (word) @cmd)
73
+ argument: (_) @sink
74
+ (#eq? @cmd "exec"))
75
+
76
+ - id: bash.path
77
+ sink-class: path-traversal
78
+ query: |
79
+ (command
80
+ name: (command_name (word) @cmd)
81
+ argument: (_) @sink
82
+ (#match? @cmd "^(rm|cat|mv|cp|mkdir|touch|chmod|chown)$"))
83
+
84
+ - id: bash.redirect_path
85
+ sink-class: path-traversal
86
+ query: |
87
+ (redirected_statement
88
+ redirect: (_ (_) @sink))
89
+
90
+ - id: bash.url
91
+ sink-class: url-injection
92
+ query: |
93
+ (command
94
+ name: (command_name (word) @cmd)
95
+ argument: (_) @sink
96
+ (#match? @cmd "^(curl|wget|lynx)$"))
97
+
98
+ - id: bash.psql
99
+ sink-class: sql-injection
100
+ query: |
101
+ (command
102
+ name: (command_name (word) @cmd)
103
+ argument: (word) @flag
104
+ argument: (_) @sink
105
+ (#eq? @cmd "psql")
106
+ (#eq? @flag "-c"))
107
+
108
+ - id: bash.mysql
109
+ sink-class: sql-injection
110
+ query: |
111
+ (command
112
+ name: (command_name (word) @cmd)
113
+ argument: (word) @flag
114
+ argument: (_) @sink
115
+ (#eq? @cmd "mysql")
116
+ (#eq? @flag "-e"))
117
+
118
+ - id: bash.sqlite3
119
+ sink-class: sql-injection
120
+ query: |
121
+ (command
122
+ name: (command_name (word) @cmd)
123
+ argument: (_) @db
124
+ argument: (_) @sink
125
+ (#eq? @cmd "sqlite3"))
126
+
127
+ - id: bash.cgi_echo
128
+ sink-class: xss
129
+ query: |
130
+ (command
131
+ name: (command_name (word) @cmd)
132
+ argument: (_) @sink
133
+ (#match? @cmd "^(echo|printf)$"))
134
+
135
+ # prototype-pollution is intentionally excluded: shell has no prototype chain.
136
+
137
+ sanitisers:
138
+ - id: bash.regex_validation
139
+ sanitises:
140
+ - command-injection
141
+ - path-traversal
142
+ - sql-injection
143
+ query: |
144
+ (test_command
145
+ (binary_expression
146
+ left: (string (simple_expansion (variable_name) @sanitiser))
147
+ right: (regex)))
148
+
149
+ - id: bash.case_validation
150
+ sanitises:
151
+ - command-injection
152
+ - path-traversal
153
+ - url-injection
154
+ query: |
155
+ (case_statement
156
+ value: (string (simple_expansion (variable_name) @sanitiser)))
157
+
158
+ - id: bash.printf_string
159
+ sanitises:
160
+ - xss
161
+ query: |
162
+ (command
163
+ name: (command_name (word) @cmd)
164
+ argument: (raw_string) @fmt
165
+ (#eq? @cmd "printf")
166
+ (#eq? @fmt "'%s'")) @sanitiser
@@ -0,0 +1,217 @@
1
+ language: php
2
+ cases:
3
+ # Benchmark: DVWA sqli module (low difficulty).
4
+ # Vulnerability class: CWE-89 (SQL Injection).
5
+ # Clean-room snippet authored for Seaworthy calibration; no DVWA source copied.
6
+ # Recall tier: baseline
7
+ - name: "DVWA/sqli/low: GET id concatenated into mysqli query"
8
+ language: php
9
+ code: |
10
+ <?php
11
+ $userId = $_GET['uid'];
12
+ $sqlText = "SELECT profile FROM accounts WHERE user_id = '" . $userId . "'";
13
+ mysqli_query($dbLink, $sqlText);
14
+ expect:
15
+ count: 1
16
+ flows:
17
+ - sourceId: superglobal.GET
18
+ sinkId: mysqli_query
19
+
20
+ # Benchmark: DVWA sqli module (medium difficulty).
21
+ # Vulnerability class: CWE-89 (SQL Injection).
22
+ # Clean-room snippet authored for Seaworthy calibration; no DVWA source copied.
23
+ # Recall tier: stretch
24
+ - name: "DVWA/sqli/medium: escaped id still concatenated into query"
25
+ language: php
26
+ code: |
27
+ <?php
28
+ $rawId = $_POST['record_id'];
29
+ $safeId = mysqli_real_escape_string($dbLink, $rawId);
30
+ $sqlText = "SELECT name FROM records WHERE id = " . $safeId;
31
+ mysqli_query($dbLink, $sqlText);
32
+ expect:
33
+ count: 0
34
+
35
+ # Benchmark: DVWA sqli module (impossible difficulty).
36
+ # Vulnerability class: CWE-89 (SQL Injection).
37
+ # Clean-room snippet authored for Seaworthy calibration; no DVWA source copied.
38
+ # Recall tier: anti
39
+ - name: "DVWA/sqli/impossible: prepared statement"
40
+ language: php
41
+ code: |
42
+ <?php
43
+ $stmt = $pdo->prepare("SELECT name FROM records WHERE id = ?");
44
+ $stmt->execute([$_GET['record_id']]);
45
+ expect:
46
+ count: 0
47
+
48
+ # Benchmark: DVWA sqli_blind module (low difficulty).
49
+ # Vulnerability class: CWE-89 (SQL Injection).
50
+ # Clean-room snippet authored for Seaworthy calibration; no DVWA source copied.
51
+ # Recall tier: baseline
52
+ - name: "DVWA/sqli_blind/low: blind boolean SQL concat"
53
+ language: php
54
+ code: |
55
+ <?php
56
+ $guess = $_GET['char'];
57
+ $query = "SELECT 1 FROM secrets WHERE SUBSTRING(flag, 1, 1) = '" . $guess . "'";
58
+ mysqli_query($dbLink, $query);
59
+ expect:
60
+ count: 1
61
+ flows:
62
+ - sourceId: superglobal.GET
63
+ sinkId: mysqli_query
64
+
65
+ # Benchmark: DVWA exec module (low difficulty).
66
+ # Vulnerability class: CWE-78 (OS Command Injection).
67
+ # Clean-room snippet authored for Seaworthy calibration; no DVWA source copied.
68
+ # Recall tier: baseline
69
+ - name: "DVWA/exec/low: shell_exec with user ping target"
70
+ language: php
71
+ code: |
72
+ <?php
73
+ $hostTarget = $_POST['host'];
74
+ shell_exec('ping -c 2 ' . $hostTarget);
75
+ expect:
76
+ count: 1
77
+ flows:
78
+ - sourceId: superglobal.POST
79
+ sinkId: shell_exec
80
+
81
+ # Benchmark: DVWA exec module (impossible difficulty).
82
+ # Vulnerability class: CWE-78 (OS Command Injection).
83
+ # Clean-room snippet authored for Seaworthy calibration; no DVWA source copied.
84
+ # Recall tier: anti
85
+ - name: "DVWA/exec/impossible: escapeshellarg on command arg"
86
+ language: php
87
+ code: |
88
+ <?php
89
+ shell_exec(escapeshellarg($_POST['host']));
90
+ expect:
91
+ count: 0
92
+
93
+ # Benchmark: DVWA fi module (low difficulty).
94
+ # Vulnerability class: CWE-98 (PHP File Inclusion).
95
+ # Clean-room snippet authored for Seaworthy calibration; no DVWA source copied.
96
+ # Recall tier: stretch
97
+ - name: "DVWA/fi/low: GET page passed to include"
98
+ language: php
99
+ code: |
100
+ <?php
101
+ $pagePath = $_GET['doc'];
102
+ include($pagePath);
103
+ expect:
104
+ count: 1
105
+ flows:
106
+ - sourceId: superglobal.GET
107
+ sinkId: include
108
+
109
+ # Benchmark: DVWA fi module (high difficulty).
110
+ # Vulnerability class: CWE-98 (PHP File Inclusion).
111
+ # Clean-room snippet authored for Seaworthy calibration; no DVWA source copied.
112
+ # Recall tier: baseline
113
+ - name: "DVWA/fi/high: GET page with weak fnmatch guard"
114
+ language: php
115
+ code: |
116
+ <?php
117
+ $pagePath = $_GET['doc'];
118
+ if (!fnmatch('docs/*', $pagePath)) {
119
+ exit('blocked');
120
+ }
121
+ include($pagePath);
122
+ expect:
123
+ count: 1
124
+ flows:
125
+ - sourceId: superglobal.GET
126
+ sinkId: include
127
+
128
+ # Benchmark: DVWA xss_r module (low difficulty).
129
+ # Vulnerability class: CWE-79 (Cross-site Scripting).
130
+ # Clean-room snippet authored for Seaworthy calibration; no DVWA source copied.
131
+ # Recall tier: stretch
132
+ - name: "DVWA/xss_r/low: GET name appended to html buffer"
133
+ language: php
134
+ code: |
135
+ <?php
136
+ $outputHtml .= '<section>' . $_GET['label'] . '</section>';
137
+ echo $outputHtml;
138
+ expect:
139
+ count: 1
140
+ flows:
141
+ - sourceId: superglobal.GET
142
+ sinkId: echo
143
+
144
+ # Benchmark: DVWA xss_r module (impossible difficulty).
145
+ # Vulnerability class: CWE-79 (Cross-site Scripting).
146
+ # Clean-room snippet authored for Seaworthy calibration; no DVWA source copied.
147
+ # Recall tier: anti
148
+ - name: "DVWA/xss_r/impossible: htmlspecialchars on input"
149
+ language: php
150
+ code: |
151
+ <?php
152
+ $safeLabel = htmlspecialchars($_GET['label']);
153
+ echo $safeLabel;
154
+ expect:
155
+ count: 0
156
+
157
+ # Benchmark: DVWA xss_s module (low difficulty).
158
+ # Vulnerability class: CWE-79 (Cross-site Scripting — stored).
159
+ # Clean-room snippet authored for Seaworthy calibration; no DVWA source copied.
160
+ # Recall tier: stretch
161
+ - name: "DVWA/xss_s/low: POST message echoed later"
162
+ language: php
163
+ code: |
164
+ <?php
165
+ $storedMessage = $_POST['message'];
166
+ echo $storedMessage;
167
+ expect:
168
+ count: 1
169
+ flows:
170
+ - sourceId: superglobal.POST
171
+ sinkId: echo
172
+
173
+ # Benchmark: DVWA open_redirect module (low difficulty).
174
+ # Vulnerability class: CWE-601 (URL Redirection to Untrusted Site).
175
+ # Clean-room snippet authored for Seaworthy calibration; no DVWA source copied.
176
+ # Recall tier: baseline
177
+ - name: "DVWA/open_redirect/low: Location header with GET redirect"
178
+ language: php
179
+ code: |
180
+ <?php
181
+ header('Location: ' . $_GET['next']);
182
+ expect:
183
+ count: 1
184
+ flows:
185
+ - sourceId: superglobal.GET
186
+ sinkId: header
187
+
188
+ # Benchmark: DVWA-style Bash exec module (low difficulty).
189
+ # Vulnerability class: CWE-78 (OS Command Injection).
190
+ # Clean-room snippet authored for Seaworthy calibration; no DVWA source copied.
191
+ # Recall tier: baseline
192
+ - name: "DVWA_BASH/exec/low: positional command executed directly"
193
+ language: bash
194
+ code: |
195
+ #!/usr/bin/env bash
196
+ CMD="$1"
197
+ $CMD
198
+ expect:
199
+ count: 1
200
+ flows:
201
+ - sourceId: bash.argv
202
+ sinkId: bash.dynamic_command
203
+
204
+ # Benchmark: DVWA-style Bash code execution module (low difficulty).
205
+ # Vulnerability class: CWE-94 (Code Injection).
206
+ # Clean-room snippet authored for Seaworthy calibration; no DVWA source copied.
207
+ # Recall tier: baseline
208
+ - name: "DVWA_BASH/code_exec/low: positional argument passed to eval"
209
+ language: bash
210
+ code: |
211
+ #!/usr/bin/env bash
212
+ eval "$1"
213
+ expect:
214
+ count: 1
215
+ flows:
216
+ - sourceId: bash.argv
217
+ sinkId: bash.eval
@@ -0,0 +1,207 @@
1
+ language: go
2
+ cases:
3
+ - name: "AC-4.6: XSS flow — FormValue to fmt.Fprintf"
4
+ language: go
5
+ code: |
6
+ fmt.Fprintf(w, r.FormValue("name"))
7
+ expect:
8
+ count: 1
9
+ flows:
10
+ - sourceId: net/http.FormValue
11
+ sinkId: fmt.Fprintf
12
+
13
+ - name: "AC-4.7: XSS sanitised by html.EscapeString — no finding"
14
+ language: go
15
+ code: |
16
+ fmt.Fprintf(w, html.EscapeString(r.FormValue("name")))
17
+ expect:
18
+ count: 0
19
+
20
+ - name: "AC-4.8: html.EscapeString does not cover sql-injection"
21
+ language: go
22
+ code: |
23
+ db.Query(html.EscapeString(r.FormValue("id")))
24
+ expect:
25
+ count: 1
26
+ flows:
27
+ - sourceId: net/http.FormValue
28
+ sinkId: db.Query
29
+
30
+ - name: "SQL injection — FormValue to db.Query concat"
31
+ language: go
32
+ code: |
33
+ db.Query("SELECT * FROM users WHERE id = " + r.FormValue("id"))
34
+ expect:
35
+ count: 1
36
+ flows:
37
+ - sourceId: net/http.FormValue
38
+ sinkId: db.Query
39
+
40
+ - name: "SQL injection via short var declaration"
41
+ language: go
42
+ code: |
43
+ id := r.FormValue("id")
44
+ db.Query("SELECT * FROM users WHERE id = " + id)
45
+ expect:
46
+ count: 1
47
+ flows:
48
+ - sourceId: net/http.FormValue
49
+ sinkId: db.Query
50
+
51
+ - name: "SQL injection sanitised by parameterised query"
52
+ language: go
53
+ code: |
54
+ db.Query("SELECT * FROM users WHERE id = ?", r.FormValue("id"))
55
+ expect:
56
+ count: 0
57
+
58
+ - name: "Command injection — os.Args to exec.Command"
59
+ language: go
60
+ code: |
61
+ exec.Command("sh", "-c", os.Args[1])
62
+ expect:
63
+ count: 1
64
+ flows:
65
+ - sourceId: os.Args
66
+ sinkId: exec.Command
67
+
68
+ - name: "Path traversal — FormValue to os.Open"
69
+ language: go
70
+ code: |
71
+ os.Open(r.FormValue("file"))
72
+ expect:
73
+ count: 1
74
+ flows:
75
+ - sourceId: net/http.FormValue
76
+ sinkId: os.Open
77
+
78
+ - name: "Path traversal sanitised by filepath.Clean"
79
+ language: go
80
+ code: |
81
+ os.Open(filepath.Clean(r.FormValue("file")))
82
+ expect:
83
+ count: 0
84
+
85
+ - name: "URL injection — FormValue to http.Redirect"
86
+ language: go
87
+ code: |
88
+ http.Redirect(w, r, r.FormValue("next"), 302)
89
+ expect:
90
+ count: 1
91
+ flows:
92
+ - sourceId: net/http.FormValue
93
+ sinkId: http.Redirect
94
+
95
+ - name: "URL injection sanitised by url.QueryEscape"
96
+ language: go
97
+ code: |
98
+ http.Redirect(w, r, url.QueryEscape(r.FormValue("next")), 302)
99
+ expect:
100
+ count: 0
101
+
102
+ - name: "Gin: c.Query to fmt.Fprintf"
103
+ language: go
104
+ code: |
105
+ fmt.Fprintf(w, c.Query("name"))
106
+ expect:
107
+ count: 1
108
+ flows:
109
+ - sourceId: gin.Context.Query
110
+ sinkId: fmt.Fprintf
111
+
112
+ - name: "Echo: c.QueryParam to io.WriteString"
113
+ language: go
114
+ code: |
115
+ io.WriteString(w, c.QueryParam("label"))
116
+ expect:
117
+ count: 1
118
+ flows:
119
+ - sourceId: echo.Context.Query
120
+ sinkId: io.WriteString
121
+
122
+ - name: "Prototype pollution via maps.Copy"
123
+ language: go
124
+ code: |
125
+ maps.Copy(dst, r.FormValue("payload"))
126
+ expect:
127
+ count: 1
128
+ flows:
129
+ - sourceId: net/http.FormValue
130
+ sinkId: maps.Copy
131
+
132
+ - name: "Environment variable to os.Open"
133
+ language: go
134
+ code: |
135
+ os.Open(os.Getenv("USER_PATH"))
136
+ expect:
137
+ count: 1
138
+ flows:
139
+ - sourceId: os.Getenv
140
+ sinkId: os.Open
141
+
142
+ - name: "Request body via io.ReadAll to template.HTML"
143
+ language: go
144
+ code: |
145
+ body, _ := io.ReadAll(r.Body)
146
+ template.HTML(string(body))
147
+ expect:
148
+ count: 1
149
+ flows:
150
+ - sourceId: net/http.Request.Body
151
+ sinkId: template.HTML
152
+
153
+ - name: "URL query param via r.URL.Query().Get"
154
+ language: go
155
+ code: |
156
+ db.Query("SELECT * FROM t WHERE id = " + r.URL.Query().Get("id"))
157
+ expect:
158
+ count: 1
159
+ flows:
160
+ - sourceId: net/http.URL.Query
161
+ sinkId: db.Query
162
+
163
+ - name: "Code execution via plugin.Open"
164
+ language: go
165
+ code: |
166
+ plugin.Open(os.Getenv("PLUGIN"))
167
+ expect:
168
+ count: 1
169
+ flows:
170
+ - sourceId: os.Getenv
171
+ sinkId: plugin.Open
172
+
173
+ - name: "Gin redirect with c.Redirect"
174
+ language: go
175
+ code: |
176
+ c.Redirect(http.StatusFound, c.Query("next"))
177
+ expect:
178
+ count: 1
179
+ flows:
180
+ - sourceId: gin.Context.Query
181
+ sinkId: gin.Context.Redirect
182
+
183
+ - name: "fmt.Sprintf SQL sink"
184
+ language: go
185
+ code: |
186
+ db.Query(fmt.Sprintf("SELECT * FROM users WHERE id = %s", r.FormValue("id")))
187
+ expect:
188
+ count: 1
189
+ flows:
190
+ - sourceId: net/http.FormValue
191
+ sinkId: db.Query
192
+
193
+ - name: "Go — no source match returns zero flows"
194
+ language: go
195
+ code: |
196
+ fmt.Println("hello world")
197
+ expect:
198
+ count: 0
199
+
200
+ - name: "Go safe anti-fixture: escape and parameterised query"
201
+ language: go
202
+ code: |
203
+ safe := html.EscapeString(r.FormValue("name"))
204
+ db.Query("SELECT * FROM users WHERE name = ?", r.FormValue("name"))
205
+ fmt.Fprintf(w, safe)
206
+ expect:
207
+ count: 0