@gendigital/sage-opencode 0.10.0 → 0.12.0
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.
- package/README.md +6 -6
- package/dist/bundled-dirs.d.ts +1 -1
- package/dist/bundled-dirs.d.ts.map +1 -1
- package/dist/bundled-dirs.js +1 -1
- package/dist/bundled-dirs.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +291 -71
- package/dist/index.js.map +1 -1
- package/dist/mcp-server.cjs +31882 -0
- package/dist/mcp-server.cjs.map +7 -0
- package/dist/plugin-discovery.d.ts +1 -0
- package/dist/plugin-discovery.d.ts.map +1 -1
- package/dist/plugin-discovery.js +27 -1
- package/dist/plugin-discovery.js.map +1 -1
- package/dist/startup-scan.d.ts +11 -3
- package/dist/startup-scan.d.ts.map +1 -1
- package/dist/startup-scan.js +60 -21
- package/dist/startup-scan.js.map +1 -1
- package/dist/tool-handler.d.ts +3 -2
- package/dist/tool-handler.d.ts.map +1 -1
- package/dist/tool-handler.js +22 -5
- package/dist/tool-handler.js.map +1 -1
- package/package.json +5 -3
- package/resources/threats/agent-layer.yaml +186 -0
- package/resources/threats/commands.yaml +24 -53
- package/resources/threats/credentials.yaml +12 -20
- package/resources/threats/dummy.yaml +44 -50
- package/resources/threats/files.yaml +34 -53
- package/resources/threats/mac-commands.yaml +20 -47
- package/resources/threats/mac-credentials.yaml +4 -12
- package/resources/threats/mac-files.yaml +5 -15
- package/resources/threats/mac-obfuscation.yaml +6 -13
- package/resources/threats/mac-persistence.yaml +11 -20
- package/resources/threats/mac-supply-chain.yaml +5 -8
- package/resources/threats/mitre.yaml +105 -167
- package/resources/threats/obfuscation.yaml +7 -15
- package/resources/threats/persistence.yaml +10 -17
- package/resources/threats/prompt-injection.yaml +92 -43
- package/resources/threats/self-defense.yaml +8 -12
- package/resources/threats/supply_chain.yaml +1 -2
- package/resources/threats/urls.yaml +9 -14
- package/resources/threats/win-commands.yaml +46 -106
- package/resources/threats/win-credentials.yaml +14 -24
- package/resources/threats/win-files.yaml +10 -20
- package/resources/threats/win-obfuscation.yaml +21 -37
- package/resources/threats/win-persistence.yaml +8 -16
- package/resources/threats/win-supply-chain.yaml +2 -3
- /package/resources/{allowlists → trusted-domains}/trusted-installer-domains.yaml +0 -0
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
# Command threat patterns for Sage
|
|
2
2
|
# Author: Gen Digital Inc.
|
|
3
3
|
# License: DRL-1.1 (see threats/LICENSE)
|
|
4
|
-
# Schema: id, category, severity, confidence,
|
|
4
|
+
# Schema: id, category, severity, confidence, pattern, match_on, title, expires_at, revoked, flags
|
|
5
5
|
|
|
6
6
|
# --- Pipe to shell (Remote Code Execution) ---
|
|
7
7
|
- id: "CLT-CMD-001"
|
|
8
8
|
category: tool
|
|
9
9
|
severity: critical
|
|
10
10
|
confidence: 0.95
|
|
11
|
-
action: block
|
|
12
11
|
pattern: "curl\\s[^|]*\\|\\s*(bash|sh|zsh|ksh|dash)"
|
|
13
12
|
match_on: command
|
|
14
13
|
title: "Remote code execution via curl pipe to shell"
|
|
@@ -19,7 +18,6 @@
|
|
|
19
18
|
category: tool
|
|
20
19
|
severity: critical
|
|
21
20
|
confidence: 0.95
|
|
22
|
-
action: block
|
|
23
21
|
pattern: "wget\\s[^|]*\\|\\s*(bash|sh|zsh|ksh|dash)"
|
|
24
22
|
match_on: command
|
|
25
23
|
title: "Remote code execution via wget pipe to shell"
|
|
@@ -31,8 +29,7 @@
|
|
|
31
29
|
category: tool
|
|
32
30
|
severity: critical
|
|
33
31
|
confidence: 0.90
|
|
34
|
-
|
|
35
|
-
pattern: "/dev/tcp/"
|
|
32
|
+
pattern: "\\b(bash|sh|zsh|ksh|dash)\\s+-i\\b[\\s\\S]{0,160}/dev/tcp/"
|
|
36
33
|
match_on: command
|
|
37
34
|
title: "Reverse shell via /dev/tcp"
|
|
38
35
|
expires_at: null
|
|
@@ -42,7 +39,6 @@
|
|
|
42
39
|
category: tool
|
|
43
40
|
severity: critical
|
|
44
41
|
confidence: 0.90
|
|
45
|
-
action: block
|
|
46
42
|
pattern: "\\bnc\\b.*\\s-e\\s"
|
|
47
43
|
match_on: command
|
|
48
44
|
title: "Reverse shell via netcat -e"
|
|
@@ -53,7 +49,6 @@
|
|
|
53
49
|
category: tool
|
|
54
50
|
severity: critical
|
|
55
51
|
confidence: 0.85
|
|
56
|
-
action: block
|
|
57
52
|
pattern: "bash\\s+-i\\s+>\\s*&\\s*/dev/"
|
|
58
53
|
match_on: command
|
|
59
54
|
title: "Interactive reverse shell via bash"
|
|
@@ -65,7 +60,6 @@
|
|
|
65
60
|
category: tool
|
|
66
61
|
severity: critical
|
|
67
62
|
confidence: 0.95
|
|
68
|
-
action: block
|
|
69
63
|
pattern: "\\brm\\s+(-[a-zA-Z]*f[a-zA-Z]*\\s+)?(-[a-zA-Z]*r[a-zA-Z]*\\s+)?/(\\s|$|[;&|*])|\\brm\\s+(-[a-zA-Z]*r[a-zA-Z]*\\s+)?(-[a-zA-Z]*f[a-zA-Z]*\\s+)?/(\\s|$|[;&|*])|\\brm\\s+-[a-zA-Z]*rf[a-zA-Z]*\\s+/(\\s|$|[;&|*])"
|
|
70
64
|
match_on: command
|
|
71
65
|
title: "Recursive forced deletion from root"
|
|
@@ -76,7 +70,6 @@
|
|
|
76
70
|
category: tool
|
|
77
71
|
severity: critical
|
|
78
72
|
confidence: 0.95
|
|
79
|
-
action: block
|
|
80
73
|
pattern: "\\bmkfs\\b"
|
|
81
74
|
match_on: command
|
|
82
75
|
title: "Filesystem format command"
|
|
@@ -85,9 +78,8 @@
|
|
|
85
78
|
|
|
86
79
|
- id: "CLT-CMD-008"
|
|
87
80
|
category: tool
|
|
88
|
-
severity:
|
|
81
|
+
severity: warning
|
|
89
82
|
confidence: 0.85
|
|
90
|
-
action: block
|
|
91
83
|
pattern: "\\bdd\\s+if=.*of=/dev/"
|
|
92
84
|
match_on: command
|
|
93
85
|
title: "Direct disk write via dd"
|
|
@@ -98,7 +90,6 @@
|
|
|
98
90
|
category: tool
|
|
99
91
|
severity: critical
|
|
100
92
|
confidence: 0.90
|
|
101
|
-
action: block
|
|
102
93
|
pattern: "\\bshred\\b"
|
|
103
94
|
match_on: command
|
|
104
95
|
title: "Secure file destruction via shred"
|
|
@@ -110,7 +101,6 @@
|
|
|
110
101
|
category: tool
|
|
111
102
|
severity: critical
|
|
112
103
|
confidence: 0.90
|
|
113
|
-
action: block
|
|
114
104
|
pattern: "(curl|wget)\\s[\\s\\S]*?(&&|;)\\s*chmod\\s+\\+x"
|
|
115
105
|
match_on: command
|
|
116
106
|
title: "Download and execute chain"
|
|
@@ -120,9 +110,8 @@
|
|
|
120
110
|
# --- Privilege escalation ---
|
|
121
111
|
- id: "CLT-CMD-011"
|
|
122
112
|
category: tool
|
|
123
|
-
severity:
|
|
124
|
-
confidence: 0.
|
|
125
|
-
action: require_approval
|
|
113
|
+
severity: warning
|
|
114
|
+
confidence: 0.60
|
|
126
115
|
pattern: "\\bchmod\\s+777\\b"
|
|
127
116
|
match_on: command
|
|
128
117
|
title: "Overly permissive file permissions"
|
|
@@ -131,9 +120,8 @@
|
|
|
131
120
|
|
|
132
121
|
- id: "CLT-CMD-012"
|
|
133
122
|
category: tool
|
|
134
|
-
severity:
|
|
135
|
-
confidence: 0.
|
|
136
|
-
action: require_approval
|
|
123
|
+
severity: warning
|
|
124
|
+
confidence: 0.60
|
|
137
125
|
pattern: "NOPASSWD"
|
|
138
126
|
match_on: command
|
|
139
127
|
title: "Passwordless sudo configuration"
|
|
@@ -143,9 +131,8 @@
|
|
|
143
131
|
# --- Data exfiltration ---
|
|
144
132
|
- id: "CLT-CMD-013"
|
|
145
133
|
category: network_egress
|
|
146
|
-
severity:
|
|
147
|
-
confidence: 0.
|
|
148
|
-
action: require_approval
|
|
134
|
+
severity: warning
|
|
135
|
+
confidence: 0.60
|
|
149
136
|
pattern: "curl\\s[^|;]*(-d|--data|--data-binary)\\s\\S*(/etc/passwd|/etc/shadow|\\.ssh/|id_rsa|credentials|secrets)"
|
|
150
137
|
match_on: command
|
|
151
138
|
title: "Possible data exfiltration of sensitive files"
|
|
@@ -157,7 +144,6 @@
|
|
|
157
144
|
category: tool
|
|
158
145
|
severity: critical
|
|
159
146
|
confidence: 0.95
|
|
160
|
-
action: block
|
|
161
147
|
pattern: "\\bsudo\\s+(curl|wget)\\s[^|]*\\|\\s*(bash|sh|zsh|ksh|dash)"
|
|
162
148
|
match_on: command
|
|
163
149
|
title: "Privileged pipe-to-shell (sudo curl/wget piped to shell)"
|
|
@@ -171,9 +157,8 @@
|
|
|
171
157
|
# bounded non-greedy quantifier to avoid catastrophic backtracking.
|
|
172
158
|
- id: "CLT-CMD-015"
|
|
173
159
|
category: tool
|
|
174
|
-
severity:
|
|
175
|
-
confidence: 0.
|
|
176
|
-
action: require_approval
|
|
160
|
+
severity: warning
|
|
161
|
+
confidence: 0.60
|
|
177
162
|
pattern: "python[3]?\\s+-c\\s+[\"'][\\s\\S]{0,2048}?(?:os\\.(?:system|popen|exec[lv]?[ep]?e?)|subprocess\\.(?:run|call|Popen|check_output|check_call|getoutput|getstatusoutput)|__import__)\\s*\\("
|
|
178
163
|
match_on: command
|
|
179
164
|
title: "Python one-liner invoking shell/exec/subprocess call"
|
|
@@ -185,7 +170,6 @@
|
|
|
185
170
|
category: tool
|
|
186
171
|
severity: critical
|
|
187
172
|
confidence: 0.90
|
|
188
|
-
action: block
|
|
189
173
|
pattern: "\\bbash\\s+<\\(\\s*(curl|wget)\\b"
|
|
190
174
|
match_on: command
|
|
191
175
|
title: "Process substitution executing remote content"
|
|
@@ -194,9 +178,8 @@
|
|
|
194
178
|
|
|
195
179
|
- id: "CLT-CMD-017"
|
|
196
180
|
category: tool
|
|
197
|
-
severity:
|
|
181
|
+
severity: warning
|
|
198
182
|
confidence: 0.85
|
|
199
|
-
action: block
|
|
200
183
|
pattern: "\\beval\\b[^;|]*\\b(curl|wget)\\b"
|
|
201
184
|
match_on: command
|
|
202
185
|
title: "Eval executing remote download command"
|
|
@@ -205,13 +188,12 @@
|
|
|
205
188
|
|
|
206
189
|
- id: "CLT-CMD-018"
|
|
207
190
|
category: tool
|
|
208
|
-
severity:
|
|
191
|
+
severity: warning
|
|
209
192
|
confidence: 0.85
|
|
210
|
-
action: block
|
|
211
193
|
# The lookarounds prevent matching short-option flags like `du -sh` or
|
|
212
194
|
# identifiers like `shell`/`bashrc`; only standalone command invocations
|
|
213
195
|
# (preceded by whitespace, `/`, etc.) are flagged.
|
|
214
|
-
pattern: "\\bxargs\\b[
|
|
196
|
+
pattern: "\\bxargs\\b[^|;\\r\\n]{0,400}(?:(?<![-\\w])(bash|sh)(?![-\\w])(?:\\s+-[\\w]*c\\b\\s+(?:\"(?!\\s*(?:head|cat|wc)\\b)[^\"\\r\\n]{0,240}(?:\\{\\}|\\$[@*]|\\$\\d)[^\"\\r\\n]{0,240}\"|'(?!\\s*(?:head|cat|wc)\\b)[^'\\r\\n]{0,240}(?:\\{\\}|\\$[@*]|\\$\\d)[^'\\r\\n]{0,240}')|(?!\\s+-[\\w]*c\\b))|(?<![-\\w])(curl|wget)(?![-\\w])[^|;\\r\\n]{0,400}(?:-d|--data|--data-binary|--upload-file|-T|--post-file|--post-data|--body-file)\\b)"
|
|
215
197
|
match_on: command
|
|
216
198
|
title: "xargs dispatching download or shell execution"
|
|
217
199
|
expires_at: null
|
|
@@ -219,9 +201,8 @@
|
|
|
219
201
|
|
|
220
202
|
- id: "CLT-CMD-019"
|
|
221
203
|
category: tool
|
|
222
|
-
severity:
|
|
204
|
+
severity: warning
|
|
223
205
|
confidence: 0.85
|
|
224
|
-
action: block
|
|
225
206
|
pattern: "\\bfind\\b[^|;]*-exec\\s+(bash|sh|curl|wget)\\b"
|
|
226
207
|
match_on: command
|
|
227
208
|
title: "find -exec executing shell or download commands"
|
|
@@ -231,9 +212,8 @@
|
|
|
231
212
|
# --- DNS exfiltration ---
|
|
232
213
|
- id: "CLT-CMD-020"
|
|
233
214
|
category: network_egress
|
|
234
|
-
severity:
|
|
215
|
+
severity: warning
|
|
235
216
|
confidence: 0.80
|
|
236
|
-
action: block
|
|
237
217
|
pattern: "\\b(nslookup|dig|host)\\b[^|;]*\\$\\([^)]+\\)\\.[a-zA-Z]"
|
|
238
218
|
match_on: command
|
|
239
219
|
title: "DNS exfiltration via command substitution as subdomain label"
|
|
@@ -242,9 +222,8 @@
|
|
|
242
222
|
|
|
243
223
|
- id: "CLT-CMD-021"
|
|
244
224
|
category: network_egress
|
|
245
|
-
severity:
|
|
225
|
+
severity: warning
|
|
246
226
|
confidence: 0.80
|
|
247
|
-
action: block
|
|
248
227
|
pattern: "\\b(nslookup|dig|host)\\b[^|;]*`[^`]+`\\.[a-zA-Z]"
|
|
249
228
|
match_on: command
|
|
250
229
|
title: "DNS exfiltration via backtick substitution as subdomain label"
|
|
@@ -254,9 +233,8 @@
|
|
|
254
233
|
# --- Loop-based indirect execution ---
|
|
255
234
|
- id: "CLT-CMD-022"
|
|
256
235
|
category: tool
|
|
257
|
-
severity:
|
|
236
|
+
severity: warning
|
|
258
237
|
confidence: 0.80
|
|
259
|
-
action: block
|
|
260
238
|
pattern: "\\b(while|for)\\b[^;]*;\\s*do[^;]*(\\b(bash|sh)\\s+-c\\b|\\b(curl|wget)\\b[^;]*\\|\\s*(?:sudo\\s+)?(?:env\\s+)?(?:[^\\s\"']*[\\\\/])?(bash|sh|zsh|ksh|dash)\\b|\\b(curl|wget)\\b[^;]*(?:(-d|--data|--data-binary)\\s+['\\\"]?@\\S+|(--upload-file|-T)\\s+['\\\"]?\\S+))"
|
|
261
239
|
match_on: command
|
|
262
240
|
title: "Loop executing shell or download commands"
|
|
@@ -270,7 +248,6 @@
|
|
|
270
248
|
category: tool
|
|
271
249
|
severity: critical
|
|
272
250
|
confidence: 0.90
|
|
273
|
-
action: block
|
|
274
251
|
pattern: "python[23]?\\s+-c.*socket.*connect.*(\\/bin\\/zsh|\\/bin\\/sh|\\/bin\\/bash)"
|
|
275
252
|
match_on: command
|
|
276
253
|
title: "Python reverse shell via socket"
|
|
@@ -282,7 +259,6 @@
|
|
|
282
259
|
category: tool
|
|
283
260
|
severity: critical
|
|
284
261
|
confidence: 0.90
|
|
285
|
-
action: block
|
|
286
262
|
pattern: "ruby\\s+-e.*TCPSocket.*exec.*(\\/bin\\/zsh|\\/bin\\/sh)"
|
|
287
263
|
match_on: command
|
|
288
264
|
title: "Ruby reverse shell via TCPSocket"
|
|
@@ -294,7 +270,6 @@
|
|
|
294
270
|
category: tool
|
|
295
271
|
severity: critical
|
|
296
272
|
confidence: 0.90
|
|
297
|
-
action: block
|
|
298
273
|
pattern: "\\bzsh\\s+-c\\b.*\\b(exec|socket|/dev/tcp)\\b"
|
|
299
274
|
match_on: command
|
|
300
275
|
title: "Zsh reverse shell pattern"
|
|
@@ -306,7 +281,6 @@
|
|
|
306
281
|
category: tool
|
|
307
282
|
severity: critical
|
|
308
283
|
confidence: 0.95
|
|
309
|
-
action: block
|
|
310
284
|
pattern: "\\brm\\s+(-[a-zA-Z]+\\s+)*-[a-zA-Z]*[rR][a-zA-Z]*(\\s+-[a-zA-Z]+)*\\s+/(home|Users|etc|usr|var|boot|bin|sbin|lib|lib64|opt|root|System|Applications|Library|Volumes|private|mnt)\\b/?(\\s|$|[;&|])"
|
|
311
285
|
match_on: command
|
|
312
286
|
title: "Recursive deletion of critical system directory"
|
|
@@ -316,9 +290,8 @@
|
|
|
316
290
|
# --- Deletion of .env files ---
|
|
317
291
|
- id: "CLT-CMD-027"
|
|
318
292
|
category: tool
|
|
319
|
-
severity:
|
|
320
|
-
confidence: 0.
|
|
321
|
-
action: require_approval
|
|
293
|
+
severity: warning
|
|
294
|
+
confidence: 0.60
|
|
322
295
|
pattern: "\\brm\\s+(-{1,2}[\\w-]+(=\\S+)?\\s+)*(\\S+[\\\\/])?\\.env(?!\\S*\\.(example|sample|template|dist)\\b)(\\.(local|production|prod|staging|stage|development|dev|test))?\\b"
|
|
323
296
|
match_on: command
|
|
324
297
|
title: "Deletion of .env file"
|
|
@@ -328,9 +301,8 @@
|
|
|
328
301
|
# --- Deletion of database files ---
|
|
329
302
|
- id: "CLT-CMD-028"
|
|
330
303
|
category: tool
|
|
331
|
-
severity:
|
|
332
|
-
confidence: 0.
|
|
333
|
-
action: require_approval
|
|
304
|
+
severity: warning
|
|
305
|
+
confidence: 0.60
|
|
334
306
|
pattern: "\\brm\\s+(-{1,2}[\\w-]+(=\\S+)?\\s+)*\\S+\\.(db|sqlite|sqlite3)\\b"
|
|
335
307
|
match_on: command
|
|
336
308
|
title: "Deletion of database file"
|
|
@@ -340,9 +312,8 @@
|
|
|
340
312
|
# --- Deletion of .git directory ---
|
|
341
313
|
- id: "CLT-CMD-029"
|
|
342
314
|
category: tool
|
|
343
|
-
severity:
|
|
344
|
-
confidence: 0.
|
|
345
|
-
action: require_approval
|
|
315
|
+
severity: warning
|
|
316
|
+
confidence: 0.60
|
|
346
317
|
pattern: "\\b(rm|del|rmdir|rd|Remove-Item|unlink)\\b.*(\\s|[\\\\/])\\.git(\\s|[\\\\/]|$)"
|
|
347
318
|
case_insensitive: true
|
|
348
319
|
match_on: command
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
category: secrets
|
|
8
8
|
severity: critical
|
|
9
9
|
confidence: 0.80
|
|
10
|
-
action: block
|
|
11
10
|
pattern: "(sk-[a-zA-Z0-9_-]{20,}|sk-proj-[a-zA-Z0-9_-]{20,}|AKIA[0-9A-Z]{16}|AIza[0-9A-Za-z_-]{35}|ghp_[0-9a-zA-Z]{36}|gho_[0-9a-zA-Z]{36}|glpat-[0-9a-zA-Z_-]{20,}|xox[baprs]-[0-9a-zA-Z-]+)"
|
|
12
11
|
match_on: [command, content]
|
|
13
12
|
title: "Known API key prefix detected"
|
|
@@ -17,9 +16,8 @@
|
|
|
17
16
|
# --- Export of credential env vars ---
|
|
18
17
|
- id: "CLT-CRED-002"
|
|
19
18
|
category: secrets
|
|
20
|
-
severity:
|
|
21
|
-
confidence: 0.
|
|
22
|
-
action: require_approval
|
|
19
|
+
severity: warning
|
|
20
|
+
confidence: 0.60
|
|
23
21
|
pattern: "\\bexport\\s+[A-Z_]*(API_KEY|SECRET|TOKEN|PASSWORD|CREDENTIAL|AUTH)[A-Z_]*="
|
|
24
22
|
match_on: command
|
|
25
23
|
title: "Export of environment variable with credential keyword"
|
|
@@ -29,9 +27,8 @@
|
|
|
29
27
|
# --- .env file writes ---
|
|
30
28
|
- id: "CLT-CRED-003"
|
|
31
29
|
category: secrets
|
|
32
|
-
severity:
|
|
33
|
-
confidence: 0.
|
|
34
|
-
action: require_approval
|
|
30
|
+
severity: warning
|
|
31
|
+
confidence: 0.60
|
|
35
32
|
pattern: "(>>|>)\\s*\\.env(?!\\S*\\.(example|sample|template|dist)\\b)(\\.local|\\.production|\\.prod|\\.staging|\\.stage|\\.development|\\.dev|\\.test)?\\b"
|
|
36
33
|
match_on: command
|
|
37
34
|
title: "Write/append to .env file (potential credential exposure)"
|
|
@@ -41,9 +38,8 @@
|
|
|
41
38
|
# --- Reading credential files ---
|
|
42
39
|
- id: "CLT-CRED-004"
|
|
43
40
|
category: secrets
|
|
44
|
-
severity:
|
|
45
|
-
confidence: 0.
|
|
46
|
-
action: require_approval
|
|
41
|
+
severity: warning
|
|
42
|
+
confidence: 0.60
|
|
47
43
|
pattern: "\\b(cat|less|more|head|tail)\\s+.*(\\.(env(?!\\S*\\.(example|sample|template|dist)\\b)(\\.(local|production|prod|staging|stage|development|dev|test))?)|credentials|\\.aws/credentials|\\.ssh/id_rsa|\\.ssh/id_ed25519|\\.netrc|\\.pgpass)"
|
|
48
44
|
match_on: command
|
|
49
45
|
title: "Reading credential or secret file"
|
|
@@ -53,9 +49,8 @@
|
|
|
53
49
|
# --- Plaintext credential assignment ---
|
|
54
50
|
- id: "CLT-CRED-005"
|
|
55
51
|
category: secrets
|
|
56
|
-
severity:
|
|
57
|
-
confidence: 0.
|
|
58
|
-
action: require_approval
|
|
52
|
+
severity: warning
|
|
53
|
+
confidence: 0.60
|
|
59
54
|
pattern: "\\b(PASSWORD|API_SECRET|SECRET_KEY|PRIVATE_KEY|DB_PASSWORD|MYSQL_PASSWORD|POSTGRES_PASSWORD)=[\"']?[^\\s\"']{8,}"
|
|
60
55
|
match_on: [command, content]
|
|
61
56
|
title: "Plaintext credential assignment detected"
|
|
@@ -67,7 +62,6 @@
|
|
|
67
62
|
category: secrets
|
|
68
63
|
severity: critical
|
|
69
64
|
confidence: 0.92
|
|
70
|
-
action: block
|
|
71
65
|
pattern: "(github_pat_[0-9a-zA-Z_]{22,}|SG\\.[0-9a-zA-Z_-]{22,}\\.[0-9a-zA-Z_-]{22,}|pk_live_[0-9a-zA-Z]{24,}|sk_live_[0-9a-zA-Z]{24,}|rk_live_[0-9a-zA-Z]{24,})"
|
|
72
66
|
match_on: [command, content]
|
|
73
67
|
title: "Long-form API key pattern detected (GitHub PAT, SendGrid, Stripe)"
|
|
@@ -77,9 +71,8 @@
|
|
|
77
71
|
# --- Copy/move/link secret files ---
|
|
78
72
|
- id: "CLT-CRED-007"
|
|
79
73
|
category: secrets
|
|
80
|
-
severity:
|
|
81
|
-
confidence: 0.
|
|
82
|
-
action: require_approval
|
|
74
|
+
severity: warning
|
|
75
|
+
confidence: 0.60
|
|
83
76
|
# Protected files: .env*, .aws/credentials, .ssh/(id_rsa|id_ed25519|id_ecdsa|id_dsa),
|
|
84
77
|
# .netrc, .pgpass, .npmrc, .pypirc, key.properties, .docker/config.json,
|
|
85
78
|
# kubeconfig, .kube/config, master.key, credentials.yml
|
|
@@ -92,9 +85,8 @@
|
|
|
92
85
|
# --- Archive secret files ---
|
|
93
86
|
- id: "CLT-CRED-008"
|
|
94
87
|
category: secrets
|
|
95
|
-
severity:
|
|
96
|
-
confidence: 0.
|
|
97
|
-
action: require_approval
|
|
88
|
+
severity: warning
|
|
89
|
+
confidence: 0.60
|
|
98
90
|
# Protected files: .env*, .aws/credentials, .ssh/(id_rsa|id_ed25519|id_ecdsa|id_dsa),
|
|
99
91
|
# .netrc, .pgpass, .npmrc, .pypirc, key.properties, .docker/config.json,
|
|
100
92
|
# kubeconfig, .kube/config, master.key, credentials.yml
|
|
@@ -2,8 +2,13 @@
|
|
|
2
2
|
# Author: Test — NOT real threats
|
|
3
3
|
#
|
|
4
4
|
# Canary rules that match completely harmless, highly-specific marker strings.
|
|
5
|
-
# The
|
|
6
|
-
#
|
|
5
|
+
# The markers are deliberately OPAQUE (e.g. "diagmark_cmd_a75bf229", not
|
|
6
|
+
# "__sage_test_deny_cmd_..."): a self-describing name reads as a security probe, and
|
|
7
|
+
# a safety-trained model given security context (e.g. OpenCode, which injects Sage's
|
|
8
|
+
# scan findings into the prompt) will REFUSE to run it — so the artifact never
|
|
9
|
+
# reaches Sage and the E2E deny/ask test can't fire. Opaque markers run as rote yet
|
|
10
|
+
# stay unique random strings, so false positives are essentially impossible. The
|
|
11
|
+
# rule id/title carry the human-readable meaning; the hex suffix aids traceability.
|
|
7
12
|
#
|
|
8
13
|
# Coverage matrix:
|
|
9
14
|
# Tool match_on block(deny) require_approval(ask) log(allow)
|
|
@@ -24,8 +29,7 @@
|
|
|
24
29
|
category: testing
|
|
25
30
|
severity: critical
|
|
26
31
|
confidence: 0.95
|
|
27
|
-
|
|
28
|
-
pattern: "__sage_test_deny_cmd_a75bf229__"
|
|
32
|
+
pattern: "diagmark_cmd_a75bf229"
|
|
29
33
|
match_on: command
|
|
30
34
|
title: "[TEST] Canary deny command (alpha)"
|
|
31
35
|
expires_at: null
|
|
@@ -35,8 +39,7 @@
|
|
|
35
39
|
category: testing
|
|
36
40
|
severity: critical
|
|
37
41
|
confidence: 0.95
|
|
38
|
-
|
|
39
|
-
pattern: "__sage_test_deny_run_c3d91e4a__"
|
|
42
|
+
pattern: "diagmark_run_c3d91e4a"
|
|
40
43
|
match_on: command
|
|
41
44
|
title: "[TEST] Canary deny command (bravo)"
|
|
42
45
|
expires_at: null
|
|
@@ -44,10 +47,9 @@
|
|
|
44
47
|
|
|
45
48
|
- id: "DUMMY-CMD-ASK-001"
|
|
46
49
|
category: testing
|
|
47
|
-
severity:
|
|
48
|
-
confidence: 0.
|
|
49
|
-
|
|
50
|
-
pattern: "__sage_test_ask_cmd_8f2e6b71__"
|
|
50
|
+
severity: warning
|
|
51
|
+
confidence: 0.60
|
|
52
|
+
pattern: "diagmark_cmd_8f2e6b71"
|
|
51
53
|
match_on: command
|
|
52
54
|
title: "[TEST] Canary approval command (alpha)"
|
|
53
55
|
expires_at: null
|
|
@@ -55,10 +57,9 @@
|
|
|
55
57
|
|
|
56
58
|
- id: "DUMMY-CMD-ASK-002"
|
|
57
59
|
category: testing
|
|
58
|
-
severity:
|
|
59
|
-
confidence: 0.
|
|
60
|
-
|
|
61
|
-
pattern: "__sage_test_ask_run_d4a09c53__"
|
|
60
|
+
severity: warning
|
|
61
|
+
confidence: 0.60
|
|
62
|
+
pattern: "diagmark_run_d4a09c53"
|
|
62
63
|
match_on: command
|
|
63
64
|
title: "[TEST] Canary approval command (bravo)"
|
|
64
65
|
expires_at: null
|
|
@@ -66,14 +67,14 @@
|
|
|
66
67
|
|
|
67
68
|
- id: "DUMMY-CMD-LOG-001"
|
|
68
69
|
category: testing
|
|
69
|
-
severity:
|
|
70
|
-
confidence: 0.
|
|
71
|
-
|
|
72
|
-
pattern: "__sage_test_log_cmd_1b7e3f82__"
|
|
70
|
+
severity: info
|
|
71
|
+
confidence: 0.10
|
|
72
|
+
pattern: "diagmark_cmd_1b7e3f82"
|
|
73
73
|
match_on: command
|
|
74
74
|
title: "[TEST] Canary log-only command"
|
|
75
75
|
expires_at: null
|
|
76
76
|
revoked: false
|
|
77
|
+
flags: ["report"]
|
|
77
78
|
|
|
78
79
|
# ─── File-path patterns (Write / Edit / Read / Delete tools) ────────
|
|
79
80
|
|
|
@@ -81,8 +82,7 @@
|
|
|
81
82
|
category: testing
|
|
82
83
|
severity: critical
|
|
83
84
|
confidence: 0.95
|
|
84
|
-
|
|
85
|
-
pattern: "__sage_test_deny_file_e6c4a918__"
|
|
85
|
+
pattern: "diagmark_file_e6c4a918"
|
|
86
86
|
match_on: file_path
|
|
87
87
|
title: "[TEST] Canary deny file path"
|
|
88
88
|
expires_at: null
|
|
@@ -90,10 +90,9 @@
|
|
|
90
90
|
|
|
91
91
|
- id: "DUMMY-FILE-ASK-001"
|
|
92
92
|
category: testing
|
|
93
|
-
severity:
|
|
94
|
-
confidence: 0.
|
|
95
|
-
|
|
96
|
-
pattern: "__sage_test_ask_file_52fd7b36__"
|
|
93
|
+
severity: warning
|
|
94
|
+
confidence: 0.60
|
|
95
|
+
pattern: "diagmark_file_52fd7b36"
|
|
97
96
|
match_on: file_path
|
|
98
97
|
title: "[TEST] Canary approval file path"
|
|
99
98
|
expires_at: null
|
|
@@ -101,14 +100,14 @@
|
|
|
101
100
|
|
|
102
101
|
- id: "DUMMY-FILE-LOG-001"
|
|
103
102
|
category: testing
|
|
104
|
-
severity:
|
|
105
|
-
confidence: 0.
|
|
106
|
-
|
|
107
|
-
pattern: "__sage_test_log_file_9a13de74__"
|
|
103
|
+
severity: info
|
|
104
|
+
confidence: 0.10
|
|
105
|
+
pattern: "diagmark_file_9a13de74"
|
|
108
106
|
match_on: file_path
|
|
109
107
|
title: "[TEST] Canary log-only file path"
|
|
110
108
|
expires_at: null
|
|
111
109
|
revoked: false
|
|
110
|
+
flags: ["report"]
|
|
112
111
|
|
|
113
112
|
# ─── Content patterns (Write / Edit tools — file body) ──────────────
|
|
114
113
|
|
|
@@ -116,8 +115,7 @@
|
|
|
116
115
|
category: testing
|
|
117
116
|
severity: critical
|
|
118
117
|
confidence: 0.95
|
|
119
|
-
|
|
120
|
-
pattern: "__SAGE_TEST_DENY_CONTENT_3c8f15b7__"
|
|
118
|
+
pattern: "diagmark_content_3c8f15b7"
|
|
121
119
|
match_on: content
|
|
122
120
|
title: "[TEST] Canary deny content"
|
|
123
121
|
expires_at: null
|
|
@@ -125,10 +123,9 @@
|
|
|
125
123
|
|
|
126
124
|
- id: "DUMMY-CONTENT-ASK-001"
|
|
127
125
|
category: testing
|
|
128
|
-
severity:
|
|
129
|
-
confidence: 0.
|
|
130
|
-
|
|
131
|
-
pattern: "__SAGE_TEST_ASK_CONTENT_7d4ea2c9__"
|
|
126
|
+
severity: warning
|
|
127
|
+
confidence: 0.60
|
|
128
|
+
pattern: "diagmark_content_7d4ea2c9"
|
|
132
129
|
match_on: content
|
|
133
130
|
title: "[TEST] Canary approval content"
|
|
134
131
|
expires_at: null
|
|
@@ -136,14 +133,14 @@
|
|
|
136
133
|
|
|
137
134
|
- id: "DUMMY-CONTENT-LOG-001"
|
|
138
135
|
category: testing
|
|
139
|
-
severity:
|
|
140
|
-
confidence: 0.
|
|
141
|
-
|
|
142
|
-
pattern: "__SAGE_TEST_LOG_CONTENT_f0b683d1__"
|
|
136
|
+
severity: info
|
|
137
|
+
confidence: 0.10
|
|
138
|
+
pattern: "diagmark_content_f0b683d1"
|
|
143
139
|
match_on: content
|
|
144
140
|
title: "[TEST] Canary log-only content"
|
|
145
141
|
expires_at: null
|
|
146
142
|
revoked: false
|
|
143
|
+
flags: ["report"]
|
|
147
144
|
|
|
148
145
|
# ─── URL patterns (WebFetch / Bash / Write content) ─────────────────
|
|
149
146
|
# Uses .test TLD (RFC 2606 reserved, never resolves) for safety.
|
|
@@ -152,8 +149,7 @@
|
|
|
152
149
|
category: testing
|
|
153
150
|
severity: critical
|
|
154
151
|
confidence: 0.95
|
|
155
|
-
|
|
156
|
-
pattern: "sage-canary-deny-4e91ca37\\.test"
|
|
152
|
+
pattern: "diaghost-4e91ca37\\.test"
|
|
157
153
|
match_on: url
|
|
158
154
|
title: "[TEST] Canary deny URL"
|
|
159
155
|
expires_at: null
|
|
@@ -161,10 +157,9 @@
|
|
|
161
157
|
|
|
162
158
|
- id: "DUMMY-URL-ASK-001"
|
|
163
159
|
category: testing
|
|
164
|
-
severity:
|
|
165
|
-
confidence: 0.
|
|
166
|
-
|
|
167
|
-
pattern: "sage-canary-ask-b26d80f5\\.test"
|
|
160
|
+
severity: warning
|
|
161
|
+
confidence: 0.60
|
|
162
|
+
pattern: "diaghost-b26d80f5\\.test"
|
|
168
163
|
match_on: url
|
|
169
164
|
title: "[TEST] Canary approval URL"
|
|
170
165
|
expires_at: null
|
|
@@ -172,14 +167,14 @@
|
|
|
172
167
|
|
|
173
168
|
- id: "DUMMY-URL-LOG-001"
|
|
174
169
|
category: testing
|
|
175
|
-
severity:
|
|
176
|
-
confidence: 0.
|
|
177
|
-
|
|
178
|
-
pattern: "sage-canary-log-65f3d7a4\\.test"
|
|
170
|
+
severity: info
|
|
171
|
+
confidence: 0.10
|
|
172
|
+
pattern: "diaghost-65f3d7a4\\.test"
|
|
179
173
|
match_on: url
|
|
180
174
|
title: "[TEST] Canary log-only URL"
|
|
181
175
|
expires_at: null
|
|
182
176
|
revoked: false
|
|
177
|
+
flags: ["report"]
|
|
183
178
|
|
|
184
179
|
# ─── Domain pattern (verifies domain→url routing in heuristics) ─────
|
|
185
180
|
|
|
@@ -187,8 +182,7 @@
|
|
|
187
182
|
category: testing
|
|
188
183
|
severity: critical
|
|
189
184
|
confidence: 0.95
|
|
190
|
-
|
|
191
|
-
pattern: "sage-canary-domain-0c82eb16\\.test"
|
|
185
|
+
pattern: "diaghost-0c82eb16\\.test"
|
|
192
186
|
match_on: domain
|
|
193
187
|
title: "[TEST] Canary deny domain"
|
|
194
188
|
expires_at: null
|