@gendigital/sage-opencode 0.9.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 +102 -0
- package/dist/bundled-dirs.d.ts +12 -0
- package/dist/bundled-dirs.d.ts.map +1 -0
- package/dist/bundled-dirs.js +29 -0
- package/dist/bundled-dirs.js.map +1 -0
- package/dist/error.d.ts +7 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +12 -0
- package/dist/error.js.map +1 -0
- package/dist/extractors.d.ts +6 -0
- package/dist/extractors.d.ts.map +1 -0
- package/dist/extractors.js +111 -0
- package/dist/extractors.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +128 -0
- package/dist/index.js.map +1 -0
- package/dist/logger-adaptor.d.ts +15 -0
- package/dist/logger-adaptor.d.ts.map +1 -0
- package/dist/logger-adaptor.js +32 -0
- package/dist/logger-adaptor.js.map +1 -0
- package/dist/plugin-discovery.d.ts +12 -0
- package/dist/plugin-discovery.d.ts.map +1 -0
- package/dist/plugin-discovery.js +138 -0
- package/dist/plugin-discovery.js.map +1 -0
- package/dist/startup-scan.d.ts +7 -0
- package/dist/startup-scan.d.ts.map +1 -0
- package/dist/startup-scan.js +41 -0
- package/dist/startup-scan.js.map +1 -0
- package/dist/tool-handler.d.ts +14 -0
- package/dist/tool-handler.d.ts.map +1 -0
- package/dist/tool-handler.js +93 -0
- package/dist/tool-handler.js.map +1 -0
- package/package.json +60 -0
- package/resources/allowlists/trusted-installer-domains.yaml +55 -0
- package/resources/threats/LICENSE +45 -0
- package/resources/threats/commands.yaml +351 -0
- package/resources/threats/credentials.yaml +105 -0
- package/resources/threats/dummy.yaml +195 -0
- package/resources/threats/files.yaml +239 -0
- package/resources/threats/mac-commands.yaml +355 -0
- package/resources/threats/mac-credentials.yaml +99 -0
- package/resources/threats/mac-files.yaml +124 -0
- package/resources/threats/mac-obfuscation.yaml +92 -0
- package/resources/threats/mac-persistence.yaml +117 -0
- package/resources/threats/mac-supply-chain.yaml +40 -0
- package/resources/threats/mitre.yaml +810 -0
- package/resources/threats/obfuscation.yaml +98 -0
- package/resources/threats/persistence.yaml +87 -0
- package/resources/threats/prompt-injection.yaml +334 -0
- package/resources/threats/self-defense.yaml +55 -0
- package/resources/threats/supply_chain.yaml +15 -0
- package/resources/threats/urls.yaml +66 -0
- package/resources/threats/win-commands.yaml +785 -0
- package/resources/threats/win-credentials.yaml +128 -0
- package/resources/threats/win-files.yaml +124 -0
- package/resources/threats/win-obfuscation.yaml +205 -0
- package/resources/threats/win-persistence.yaml +100 -0
- package/resources/threats/win-supply-chain.yaml +15 -0
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
# Command threat patterns for Sage
|
|
2
|
+
# Author: Gen Digital Inc.
|
|
3
|
+
# License: DRL-1.1 (see threats/LICENSE)
|
|
4
|
+
# Schema: id, category, severity, confidence, action, pattern, match_on, title, expires_at, revoked
|
|
5
|
+
|
|
6
|
+
# --- Pipe to shell (Remote Code Execution) ---
|
|
7
|
+
- id: "CLT-CMD-001"
|
|
8
|
+
category: tool
|
|
9
|
+
severity: critical
|
|
10
|
+
confidence: 0.95
|
|
11
|
+
action: block
|
|
12
|
+
pattern: "curl\\s[^|]*\\|\\s*(bash|sh|zsh|ksh|dash)"
|
|
13
|
+
match_on: command
|
|
14
|
+
title: "Remote code execution via curl pipe to shell"
|
|
15
|
+
expires_at: null
|
|
16
|
+
revoked: false
|
|
17
|
+
|
|
18
|
+
- id: "CLT-CMD-002"
|
|
19
|
+
category: tool
|
|
20
|
+
severity: critical
|
|
21
|
+
confidence: 0.95
|
|
22
|
+
action: block
|
|
23
|
+
pattern: "wget\\s[^|]*\\|\\s*(bash|sh|zsh|ksh|dash)"
|
|
24
|
+
match_on: command
|
|
25
|
+
title: "Remote code execution via wget pipe to shell"
|
|
26
|
+
expires_at: null
|
|
27
|
+
revoked: false
|
|
28
|
+
|
|
29
|
+
# --- Reverse shells ---
|
|
30
|
+
- id: "CLT-CMD-003"
|
|
31
|
+
category: tool
|
|
32
|
+
severity: critical
|
|
33
|
+
confidence: 0.90
|
|
34
|
+
action: block
|
|
35
|
+
pattern: "/dev/tcp/"
|
|
36
|
+
match_on: command
|
|
37
|
+
title: "Reverse shell via /dev/tcp"
|
|
38
|
+
expires_at: null
|
|
39
|
+
revoked: false
|
|
40
|
+
|
|
41
|
+
- id: "CLT-CMD-004"
|
|
42
|
+
category: tool
|
|
43
|
+
severity: critical
|
|
44
|
+
confidence: 0.90
|
|
45
|
+
action: block
|
|
46
|
+
pattern: "\\bnc\\b.*\\s-e\\s"
|
|
47
|
+
match_on: command
|
|
48
|
+
title: "Reverse shell via netcat -e"
|
|
49
|
+
expires_at: null
|
|
50
|
+
revoked: false
|
|
51
|
+
|
|
52
|
+
- id: "CLT-CMD-005"
|
|
53
|
+
category: tool
|
|
54
|
+
severity: critical
|
|
55
|
+
confidence: 0.85
|
|
56
|
+
action: block
|
|
57
|
+
pattern: "bash\\s+-i\\s+>\\s*&\\s*/dev/"
|
|
58
|
+
match_on: command
|
|
59
|
+
title: "Interactive reverse shell via bash"
|
|
60
|
+
expires_at: null
|
|
61
|
+
revoked: false
|
|
62
|
+
|
|
63
|
+
# --- Destructive operations ---
|
|
64
|
+
- id: "CLT-CMD-006"
|
|
65
|
+
category: tool
|
|
66
|
+
severity: critical
|
|
67
|
+
confidence: 0.95
|
|
68
|
+
action: block
|
|
69
|
+
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
|
+
match_on: command
|
|
71
|
+
title: "Recursive forced deletion from root"
|
|
72
|
+
expires_at: null
|
|
73
|
+
revoked: false
|
|
74
|
+
|
|
75
|
+
- id: "CLT-CMD-007"
|
|
76
|
+
category: tool
|
|
77
|
+
severity: critical
|
|
78
|
+
confidence: 0.95
|
|
79
|
+
action: block
|
|
80
|
+
pattern: "\\bmkfs\\b"
|
|
81
|
+
match_on: command
|
|
82
|
+
title: "Filesystem format command"
|
|
83
|
+
expires_at: null
|
|
84
|
+
revoked: false
|
|
85
|
+
|
|
86
|
+
- id: "CLT-CMD-008"
|
|
87
|
+
category: tool
|
|
88
|
+
severity: high
|
|
89
|
+
confidence: 0.85
|
|
90
|
+
action: block
|
|
91
|
+
pattern: "\\bdd\\s+if=.*of=/dev/"
|
|
92
|
+
match_on: command
|
|
93
|
+
title: "Direct disk write via dd"
|
|
94
|
+
expires_at: null
|
|
95
|
+
revoked: false
|
|
96
|
+
|
|
97
|
+
- id: "CLT-CMD-009"
|
|
98
|
+
category: tool
|
|
99
|
+
severity: critical
|
|
100
|
+
confidence: 0.90
|
|
101
|
+
action: block
|
|
102
|
+
pattern: "\\bshred\\b"
|
|
103
|
+
match_on: command
|
|
104
|
+
title: "Secure file destruction via shred"
|
|
105
|
+
expires_at: null
|
|
106
|
+
revoked: false
|
|
107
|
+
|
|
108
|
+
# --- Download + execute chains ---
|
|
109
|
+
- id: "CLT-CMD-010"
|
|
110
|
+
category: tool
|
|
111
|
+
severity: critical
|
|
112
|
+
confidence: 0.90
|
|
113
|
+
action: block
|
|
114
|
+
pattern: "(curl|wget)\\s[\\s\\S]*?(&&|;)\\s*chmod\\s+\\+x"
|
|
115
|
+
match_on: command
|
|
116
|
+
title: "Download and execute chain"
|
|
117
|
+
expires_at: null
|
|
118
|
+
revoked: false
|
|
119
|
+
|
|
120
|
+
# --- Privilege escalation ---
|
|
121
|
+
- id: "CLT-CMD-011"
|
|
122
|
+
category: tool
|
|
123
|
+
severity: high
|
|
124
|
+
confidence: 0.80
|
|
125
|
+
action: require_approval
|
|
126
|
+
pattern: "\\bchmod\\s+777\\b"
|
|
127
|
+
match_on: command
|
|
128
|
+
title: "Overly permissive file permissions"
|
|
129
|
+
expires_at: null
|
|
130
|
+
revoked: false
|
|
131
|
+
|
|
132
|
+
- id: "CLT-CMD-012"
|
|
133
|
+
category: tool
|
|
134
|
+
severity: high
|
|
135
|
+
confidence: 0.80
|
|
136
|
+
action: require_approval
|
|
137
|
+
pattern: "NOPASSWD"
|
|
138
|
+
match_on: command
|
|
139
|
+
title: "Passwordless sudo configuration"
|
|
140
|
+
expires_at: null
|
|
141
|
+
revoked: false
|
|
142
|
+
|
|
143
|
+
# --- Data exfiltration ---
|
|
144
|
+
- id: "CLT-CMD-013"
|
|
145
|
+
category: network_egress
|
|
146
|
+
severity: high
|
|
147
|
+
confidence: 0.80
|
|
148
|
+
action: require_approval
|
|
149
|
+
pattern: "curl\\s[^|;]*(-d|--data|--data-binary)\\s\\S*(/etc/passwd|/etc/shadow|\\.ssh/|id_rsa|credentials|secrets)"
|
|
150
|
+
match_on: command
|
|
151
|
+
title: "Possible data exfiltration of sensitive files"
|
|
152
|
+
expires_at: null
|
|
153
|
+
revoked: false
|
|
154
|
+
|
|
155
|
+
# --- Privileged pipe to shell ---
|
|
156
|
+
- id: "CLT-CMD-014"
|
|
157
|
+
category: tool
|
|
158
|
+
severity: critical
|
|
159
|
+
confidence: 0.95
|
|
160
|
+
action: block
|
|
161
|
+
pattern: "\\bsudo\\s+(curl|wget)\\s[^|]*\\|\\s*(bash|sh|zsh|ksh|dash)"
|
|
162
|
+
match_on: command
|
|
163
|
+
title: "Privileged pipe-to-shell (sudo curl/wget piped to shell)"
|
|
164
|
+
expires_at: null
|
|
165
|
+
revoked: false
|
|
166
|
+
|
|
167
|
+
# --- Python one-liner with dangerous calls ---
|
|
168
|
+
# Matches actual call sites (`name(`) rather than bare imports — `import
|
|
169
|
+
# subprocess` alone is harmless; `subprocess.run(...)` is what we care about.
|
|
170
|
+
# Uses `[\s\S]` to span newlines (loader does not set the `s` flag) and a
|
|
171
|
+
# bounded non-greedy quantifier to avoid catastrophic backtracking.
|
|
172
|
+
- id: "CLT-CMD-015"
|
|
173
|
+
category: tool
|
|
174
|
+
severity: high
|
|
175
|
+
confidence: 0.80
|
|
176
|
+
action: require_approval
|
|
177
|
+
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
|
+
match_on: command
|
|
179
|
+
title: "Python one-liner invoking shell/exec/subprocess call"
|
|
180
|
+
expires_at: null
|
|
181
|
+
revoked: false
|
|
182
|
+
|
|
183
|
+
# --- Indirect execution patterns ---
|
|
184
|
+
- id: "CLT-CMD-016"
|
|
185
|
+
category: tool
|
|
186
|
+
severity: critical
|
|
187
|
+
confidence: 0.90
|
|
188
|
+
action: block
|
|
189
|
+
pattern: "\\bbash\\s+<\\(\\s*(curl|wget)\\b"
|
|
190
|
+
match_on: command
|
|
191
|
+
title: "Process substitution executing remote content"
|
|
192
|
+
expires_at: null
|
|
193
|
+
revoked: false
|
|
194
|
+
|
|
195
|
+
- id: "CLT-CMD-017"
|
|
196
|
+
category: tool
|
|
197
|
+
severity: high
|
|
198
|
+
confidence: 0.85
|
|
199
|
+
action: block
|
|
200
|
+
pattern: "\\beval\\b[^;|]*\\b(curl|wget)\\b"
|
|
201
|
+
match_on: command
|
|
202
|
+
title: "Eval executing remote download command"
|
|
203
|
+
expires_at: null
|
|
204
|
+
revoked: false
|
|
205
|
+
|
|
206
|
+
- id: "CLT-CMD-018"
|
|
207
|
+
category: tool
|
|
208
|
+
severity: high
|
|
209
|
+
confidence: 0.85
|
|
210
|
+
action: block
|
|
211
|
+
# The lookarounds prevent matching short-option flags like `du -sh` or
|
|
212
|
+
# identifiers like `shell`/`bashrc`; only standalone command invocations
|
|
213
|
+
# (preceded by whitespace, `/`, etc.) are flagged.
|
|
214
|
+
pattern: "\\bxargs\\b[^|;]*(?<![-\\w])(curl|wget|bash|sh)(?![-\\w])"
|
|
215
|
+
match_on: command
|
|
216
|
+
title: "xargs dispatching download or shell execution"
|
|
217
|
+
expires_at: null
|
|
218
|
+
revoked: false
|
|
219
|
+
|
|
220
|
+
- id: "CLT-CMD-019"
|
|
221
|
+
category: tool
|
|
222
|
+
severity: high
|
|
223
|
+
confidence: 0.85
|
|
224
|
+
action: block
|
|
225
|
+
pattern: "\\bfind\\b[^|;]*-exec\\s+(bash|sh|curl|wget)\\b"
|
|
226
|
+
match_on: command
|
|
227
|
+
title: "find -exec executing shell or download commands"
|
|
228
|
+
expires_at: null
|
|
229
|
+
revoked: false
|
|
230
|
+
|
|
231
|
+
# --- DNS exfiltration ---
|
|
232
|
+
- id: "CLT-CMD-020"
|
|
233
|
+
category: network_egress
|
|
234
|
+
severity: high
|
|
235
|
+
confidence: 0.80
|
|
236
|
+
action: block
|
|
237
|
+
pattern: "\\b(nslookup|dig|host)\\b[^|;]*\\$\\([^)]+\\)\\.[a-zA-Z]"
|
|
238
|
+
match_on: command
|
|
239
|
+
title: "DNS exfiltration via command substitution as subdomain label"
|
|
240
|
+
expires_at: null
|
|
241
|
+
revoked: false
|
|
242
|
+
|
|
243
|
+
- id: "CLT-CMD-021"
|
|
244
|
+
category: network_egress
|
|
245
|
+
severity: high
|
|
246
|
+
confidence: 0.80
|
|
247
|
+
action: block
|
|
248
|
+
pattern: "\\b(nslookup|dig|host)\\b[^|;]*`[^`]+`\\.[a-zA-Z]"
|
|
249
|
+
match_on: command
|
|
250
|
+
title: "DNS exfiltration via backtick substitution as subdomain label"
|
|
251
|
+
expires_at: null
|
|
252
|
+
revoked: false
|
|
253
|
+
|
|
254
|
+
# --- Loop-based indirect execution ---
|
|
255
|
+
- id: "CLT-CMD-022"
|
|
256
|
+
category: tool
|
|
257
|
+
severity: high
|
|
258
|
+
confidence: 0.80
|
|
259
|
+
action: block
|
|
260
|
+
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
|
+
match_on: command
|
|
262
|
+
title: "Loop executing shell or download commands"
|
|
263
|
+
expires_at: null
|
|
264
|
+
revoked: false
|
|
265
|
+
|
|
266
|
+
# --- Cross-platform reverse shells (scripting languages) ---
|
|
267
|
+
|
|
268
|
+
# Python socket reverse shell
|
|
269
|
+
- id: "CLT-CMD-023"
|
|
270
|
+
category: tool
|
|
271
|
+
severity: critical
|
|
272
|
+
confidence: 0.90
|
|
273
|
+
action: block
|
|
274
|
+
pattern: "python[23]?\\s+-c.*socket.*connect.*(\\/bin\\/zsh|\\/bin\\/sh|\\/bin\\/bash)"
|
|
275
|
+
match_on: command
|
|
276
|
+
title: "Python reverse shell via socket"
|
|
277
|
+
expires_at: null
|
|
278
|
+
revoked: false
|
|
279
|
+
|
|
280
|
+
# Ruby TCPSocket reverse shell
|
|
281
|
+
- id: "CLT-CMD-024"
|
|
282
|
+
category: tool
|
|
283
|
+
severity: critical
|
|
284
|
+
confidence: 0.90
|
|
285
|
+
action: block
|
|
286
|
+
pattern: "ruby\\s+-e.*TCPSocket.*exec.*(\\/bin\\/zsh|\\/bin\\/sh)"
|
|
287
|
+
match_on: command
|
|
288
|
+
title: "Ruby reverse shell via TCPSocket"
|
|
289
|
+
expires_at: null
|
|
290
|
+
revoked: false
|
|
291
|
+
|
|
292
|
+
# zsh -c reverse shell pattern
|
|
293
|
+
- id: "CLT-CMD-025"
|
|
294
|
+
category: tool
|
|
295
|
+
severity: critical
|
|
296
|
+
confidence: 0.90
|
|
297
|
+
action: block
|
|
298
|
+
pattern: "\\bzsh\\s+-c\\b.*\\b(exec|socket|/dev/tcp)\\b"
|
|
299
|
+
match_on: command
|
|
300
|
+
title: "Zsh reverse shell pattern"
|
|
301
|
+
expires_at: null
|
|
302
|
+
revoked: false
|
|
303
|
+
|
|
304
|
+
# --- Recursive deletion of critical system directories ---
|
|
305
|
+
- id: "CLT-CMD-026"
|
|
306
|
+
category: tool
|
|
307
|
+
severity: critical
|
|
308
|
+
confidence: 0.95
|
|
309
|
+
action: block
|
|
310
|
+
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
|
+
match_on: command
|
|
312
|
+
title: "Recursive deletion of critical system directory"
|
|
313
|
+
expires_at: null
|
|
314
|
+
revoked: false
|
|
315
|
+
|
|
316
|
+
# --- Deletion of .env files ---
|
|
317
|
+
- id: "CLT-CMD-027"
|
|
318
|
+
category: tool
|
|
319
|
+
severity: high
|
|
320
|
+
confidence: 0.85
|
|
321
|
+
action: require_approval
|
|
322
|
+
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
|
+
match_on: command
|
|
324
|
+
title: "Deletion of .env file"
|
|
325
|
+
expires_at: null
|
|
326
|
+
revoked: false
|
|
327
|
+
|
|
328
|
+
# --- Deletion of database files ---
|
|
329
|
+
- id: "CLT-CMD-028"
|
|
330
|
+
category: tool
|
|
331
|
+
severity: high
|
|
332
|
+
confidence: 0.85
|
|
333
|
+
action: require_approval
|
|
334
|
+
pattern: "\\brm\\s+(-{1,2}[\\w-]+(=\\S+)?\\s+)*\\S+\\.(db|sqlite|sqlite3)\\b"
|
|
335
|
+
match_on: command
|
|
336
|
+
title: "Deletion of database file"
|
|
337
|
+
expires_at: null
|
|
338
|
+
revoked: false
|
|
339
|
+
|
|
340
|
+
# --- Deletion of .git directory ---
|
|
341
|
+
- id: "CLT-CMD-029"
|
|
342
|
+
category: tool
|
|
343
|
+
severity: high
|
|
344
|
+
confidence: 0.90
|
|
345
|
+
action: require_approval
|
|
346
|
+
pattern: "\\b(rm|del|rmdir|rd|Remove-Item|unlink)\\b.*(\\s|[\\\\/])\\.git(\\s|[\\\\/]|$)"
|
|
347
|
+
case_insensitive: true
|
|
348
|
+
match_on: command
|
|
349
|
+
title: "Deletion of .git directory"
|
|
350
|
+
expires_at: null
|
|
351
|
+
revoked: false
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Credential exposure threat patterns for Sage
|
|
2
|
+
# Author: Gen Digital Inc.
|
|
3
|
+
# License: DRL-1.1 (see threats/LICENSE)
|
|
4
|
+
|
|
5
|
+
# --- Known API key prefixes ---
|
|
6
|
+
- id: "CLT-CRED-001"
|
|
7
|
+
category: secrets
|
|
8
|
+
severity: critical
|
|
9
|
+
confidence: 0.80
|
|
10
|
+
action: block
|
|
11
|
+
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
|
+
match_on: [command, content]
|
|
13
|
+
title: "Known API key prefix detected"
|
|
14
|
+
expires_at: null
|
|
15
|
+
revoked: false
|
|
16
|
+
|
|
17
|
+
# --- Export of credential env vars ---
|
|
18
|
+
- id: "CLT-CRED-002"
|
|
19
|
+
category: secrets
|
|
20
|
+
severity: high
|
|
21
|
+
confidence: 0.80
|
|
22
|
+
action: require_approval
|
|
23
|
+
pattern: "\\bexport\\s+[A-Z_]*(API_KEY|SECRET|TOKEN|PASSWORD|CREDENTIAL|AUTH)[A-Z_]*="
|
|
24
|
+
match_on: command
|
|
25
|
+
title: "Export of environment variable with credential keyword"
|
|
26
|
+
expires_at: null
|
|
27
|
+
revoked: false
|
|
28
|
+
|
|
29
|
+
# --- .env file writes ---
|
|
30
|
+
- id: "CLT-CRED-003"
|
|
31
|
+
category: secrets
|
|
32
|
+
severity: high
|
|
33
|
+
confidence: 0.80
|
|
34
|
+
action: require_approval
|
|
35
|
+
pattern: "(>>|>)\\s*\\.env(?!\\S*\\.(example|sample|template|dist)\\b)(\\.local|\\.production|\\.prod|\\.staging|\\.stage|\\.development|\\.dev|\\.test)?\\b"
|
|
36
|
+
match_on: command
|
|
37
|
+
title: "Write/append to .env file (potential credential exposure)"
|
|
38
|
+
expires_at: null
|
|
39
|
+
revoked: false
|
|
40
|
+
|
|
41
|
+
# --- Reading credential files ---
|
|
42
|
+
- id: "CLT-CRED-004"
|
|
43
|
+
category: secrets
|
|
44
|
+
severity: high
|
|
45
|
+
confidence: 0.80
|
|
46
|
+
action: require_approval
|
|
47
|
+
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
|
+
match_on: command
|
|
49
|
+
title: "Reading credential or secret file"
|
|
50
|
+
expires_at: null
|
|
51
|
+
revoked: false
|
|
52
|
+
|
|
53
|
+
# --- Plaintext credential assignment ---
|
|
54
|
+
- id: "CLT-CRED-005"
|
|
55
|
+
category: secrets
|
|
56
|
+
severity: high
|
|
57
|
+
confidence: 0.85
|
|
58
|
+
action: require_approval
|
|
59
|
+
pattern: "\\b(PASSWORD|API_SECRET|SECRET_KEY|PRIVATE_KEY|DB_PASSWORD|MYSQL_PASSWORD|POSTGRES_PASSWORD)=[\"']?[^\\s\"']{8,}"
|
|
60
|
+
match_on: [command, content]
|
|
61
|
+
title: "Plaintext credential assignment detected"
|
|
62
|
+
expires_at: null
|
|
63
|
+
revoked: false
|
|
64
|
+
|
|
65
|
+
# --- Long-form API key patterns ---
|
|
66
|
+
- id: "CLT-CRED-006"
|
|
67
|
+
category: secrets
|
|
68
|
+
severity: critical
|
|
69
|
+
confidence: 0.92
|
|
70
|
+
action: block
|
|
71
|
+
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
|
+
match_on: [command, content]
|
|
73
|
+
title: "Long-form API key pattern detected (GitHub PAT, SendGrid, Stripe)"
|
|
74
|
+
expires_at: null
|
|
75
|
+
revoked: false
|
|
76
|
+
|
|
77
|
+
# --- Copy/move/link secret files ---
|
|
78
|
+
- id: "CLT-CRED-007"
|
|
79
|
+
category: secrets
|
|
80
|
+
severity: high
|
|
81
|
+
confidence: 0.80
|
|
82
|
+
action: require_approval
|
|
83
|
+
# Protected files: .env*, .aws/credentials, .ssh/(id_rsa|id_ed25519|id_ecdsa|id_dsa),
|
|
84
|
+
# .netrc, .pgpass, .npmrc, .pypirc, key.properties, .docker/config.json,
|
|
85
|
+
# kubeconfig, .kube/config, master.key, credentials.yml
|
|
86
|
+
pattern: "\\b(cp|mv|ln|rsync|install|ditto)\\s+.*(?<=[\\\\/\\s])(\\.env(?!\\S*\\.(example|sample|template|dist)\\b)(\\.\\w+)?(?=[\\s\\\\/]|$)|\\.aws/credentials|\\.ssh/(id_rsa|id_ed25519|id_ecdsa|id_dsa)|\\.netrc|\\.pgpass|\\.npmrc|\\.pypirc|key\\.properties|\\.docker/config\\.json|kubeconfig|\\.kube/config|master\\.key|credentials\\.yml)"
|
|
87
|
+
match_on: command
|
|
88
|
+
title: "Copy/move/link of credential or secret file"
|
|
89
|
+
expires_at: null
|
|
90
|
+
revoked: false
|
|
91
|
+
|
|
92
|
+
# --- Archive secret files ---
|
|
93
|
+
- id: "CLT-CRED-008"
|
|
94
|
+
category: secrets
|
|
95
|
+
severity: high
|
|
96
|
+
confidence: 0.80
|
|
97
|
+
action: require_approval
|
|
98
|
+
# Protected files: .env*, .aws/credentials, .ssh/(id_rsa|id_ed25519|id_ecdsa|id_dsa),
|
|
99
|
+
# .netrc, .pgpass, .npmrc, .pypirc, key.properties, .docker/config.json,
|
|
100
|
+
# kubeconfig, .kube/config, master.key, credentials.yml
|
|
101
|
+
pattern: "\\b(tar|zip|7z|rar|gzip)\\s+.*(?<=[\\\\/\\s])(\\.env(?!\\S*\\.(example|sample|template|dist)\\b)(\\.\\w+)?(?=[\\s\\\\/]|$)|\\.aws/credentials|\\.ssh/(id_rsa|id_ed25519|id_ecdsa|id_dsa)|\\.netrc|\\.pgpass|\\.npmrc|\\.pypirc|key\\.properties|\\.docker/config\\.json|kubeconfig|\\.kube/config|master\\.key|credentials\\.yml)"
|
|
102
|
+
match_on: command
|
|
103
|
+
title: "Archiving credential or secret file"
|
|
104
|
+
expires_at: null
|
|
105
|
+
revoked: false
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Dummy threat patterns for Sage smoke-testing
|
|
2
|
+
# Author: Test — NOT real threats
|
|
3
|
+
#
|
|
4
|
+
# Canary rules that match completely harmless, highly-specific marker strings.
|
|
5
|
+
# The "__sage_test_" prefix would never appear in real-world code,
|
|
6
|
+
# making false positives essentially impossible.
|
|
7
|
+
#
|
|
8
|
+
# Coverage matrix:
|
|
9
|
+
# Tool match_on block(deny) require_approval(ask) log(allow)
|
|
10
|
+
# ─────────── ──────── ─────────── ───────────────────── ──────────
|
|
11
|
+
# Bash command ✓ ✓ ✓ ✓ ✓
|
|
12
|
+
# Write/Edit file_path ✓ ✓ ✓
|
|
13
|
+
# Write/Edit content ✓ ✓ ✓
|
|
14
|
+
# WebFetch/Bash url ✓ ✓ ✓
|
|
15
|
+
# WebFetch/Bash domain ✓ — —
|
|
16
|
+
#
|
|
17
|
+
# The file_path rules also cover Read, Delete, Glob, and LS tools
|
|
18
|
+
# (they produce the same artifact type).
|
|
19
|
+
# The url rules also cover URLs embedded in Bash commands and file content.
|
|
20
|
+
|
|
21
|
+
# ─── Command patterns (Bash tool) ───────────────────────────────────
|
|
22
|
+
|
|
23
|
+
- id: "DUMMY-CMD-DENY-001"
|
|
24
|
+
category: testing
|
|
25
|
+
severity: critical
|
|
26
|
+
confidence: 0.95
|
|
27
|
+
action: block
|
|
28
|
+
pattern: "__sage_test_deny_cmd_a75bf229__"
|
|
29
|
+
match_on: command
|
|
30
|
+
title: "[TEST] Canary deny command (alpha)"
|
|
31
|
+
expires_at: null
|
|
32
|
+
revoked: false
|
|
33
|
+
|
|
34
|
+
- id: "DUMMY-CMD-DENY-002"
|
|
35
|
+
category: testing
|
|
36
|
+
severity: critical
|
|
37
|
+
confidence: 0.95
|
|
38
|
+
action: block
|
|
39
|
+
pattern: "__sage_test_deny_run_c3d91e4a__"
|
|
40
|
+
match_on: command
|
|
41
|
+
title: "[TEST] Canary deny command (bravo)"
|
|
42
|
+
expires_at: null
|
|
43
|
+
revoked: false
|
|
44
|
+
|
|
45
|
+
- id: "DUMMY-CMD-ASK-001"
|
|
46
|
+
category: testing
|
|
47
|
+
severity: high
|
|
48
|
+
confidence: 0.90
|
|
49
|
+
action: require_approval
|
|
50
|
+
pattern: "__sage_test_ask_cmd_8f2e6b71__"
|
|
51
|
+
match_on: command
|
|
52
|
+
title: "[TEST] Canary approval command (alpha)"
|
|
53
|
+
expires_at: null
|
|
54
|
+
revoked: false
|
|
55
|
+
|
|
56
|
+
- id: "DUMMY-CMD-ASK-002"
|
|
57
|
+
category: testing
|
|
58
|
+
severity: high
|
|
59
|
+
confidence: 0.90
|
|
60
|
+
action: require_approval
|
|
61
|
+
pattern: "__sage_test_ask_run_d4a09c53__"
|
|
62
|
+
match_on: command
|
|
63
|
+
title: "[TEST] Canary approval command (bravo)"
|
|
64
|
+
expires_at: null
|
|
65
|
+
revoked: false
|
|
66
|
+
|
|
67
|
+
- id: "DUMMY-CMD-LOG-001"
|
|
68
|
+
category: testing
|
|
69
|
+
severity: low
|
|
70
|
+
confidence: 0.90
|
|
71
|
+
action: log
|
|
72
|
+
pattern: "__sage_test_log_cmd_1b7e3f82__"
|
|
73
|
+
match_on: command
|
|
74
|
+
title: "[TEST] Canary log-only command"
|
|
75
|
+
expires_at: null
|
|
76
|
+
revoked: false
|
|
77
|
+
|
|
78
|
+
# ─── File-path patterns (Write / Edit / Read / Delete tools) ────────
|
|
79
|
+
|
|
80
|
+
- id: "DUMMY-FILE-DENY-001"
|
|
81
|
+
category: testing
|
|
82
|
+
severity: critical
|
|
83
|
+
confidence: 0.95
|
|
84
|
+
action: block
|
|
85
|
+
pattern: "__sage_test_deny_file_e6c4a918__"
|
|
86
|
+
match_on: file_path
|
|
87
|
+
title: "[TEST] Canary deny file path"
|
|
88
|
+
expires_at: null
|
|
89
|
+
revoked: false
|
|
90
|
+
|
|
91
|
+
- id: "DUMMY-FILE-ASK-001"
|
|
92
|
+
category: testing
|
|
93
|
+
severity: high
|
|
94
|
+
confidence: 0.90
|
|
95
|
+
action: require_approval
|
|
96
|
+
pattern: "__sage_test_ask_file_52fd7b36__"
|
|
97
|
+
match_on: file_path
|
|
98
|
+
title: "[TEST] Canary approval file path"
|
|
99
|
+
expires_at: null
|
|
100
|
+
revoked: false
|
|
101
|
+
|
|
102
|
+
- id: "DUMMY-FILE-LOG-001"
|
|
103
|
+
category: testing
|
|
104
|
+
severity: low
|
|
105
|
+
confidence: 0.90
|
|
106
|
+
action: log
|
|
107
|
+
pattern: "__sage_test_log_file_9a13de74__"
|
|
108
|
+
match_on: file_path
|
|
109
|
+
title: "[TEST] Canary log-only file path"
|
|
110
|
+
expires_at: null
|
|
111
|
+
revoked: false
|
|
112
|
+
|
|
113
|
+
# ─── Content patterns (Write / Edit tools — file body) ──────────────
|
|
114
|
+
|
|
115
|
+
- id: "DUMMY-CONTENT-DENY-001"
|
|
116
|
+
category: testing
|
|
117
|
+
severity: critical
|
|
118
|
+
confidence: 0.95
|
|
119
|
+
action: block
|
|
120
|
+
pattern: "__SAGE_TEST_DENY_CONTENT_3c8f15b7__"
|
|
121
|
+
match_on: content
|
|
122
|
+
title: "[TEST] Canary deny content"
|
|
123
|
+
expires_at: null
|
|
124
|
+
revoked: false
|
|
125
|
+
|
|
126
|
+
- id: "DUMMY-CONTENT-ASK-001"
|
|
127
|
+
category: testing
|
|
128
|
+
severity: high
|
|
129
|
+
confidence: 0.90
|
|
130
|
+
action: require_approval
|
|
131
|
+
pattern: "__SAGE_TEST_ASK_CONTENT_7d4ea2c9__"
|
|
132
|
+
match_on: content
|
|
133
|
+
title: "[TEST] Canary approval content"
|
|
134
|
+
expires_at: null
|
|
135
|
+
revoked: false
|
|
136
|
+
|
|
137
|
+
- id: "DUMMY-CONTENT-LOG-001"
|
|
138
|
+
category: testing
|
|
139
|
+
severity: low
|
|
140
|
+
confidence: 0.90
|
|
141
|
+
action: log
|
|
142
|
+
pattern: "__SAGE_TEST_LOG_CONTENT_f0b683d1__"
|
|
143
|
+
match_on: content
|
|
144
|
+
title: "[TEST] Canary log-only content"
|
|
145
|
+
expires_at: null
|
|
146
|
+
revoked: false
|
|
147
|
+
|
|
148
|
+
# ─── URL patterns (WebFetch / Bash / Write content) ─────────────────
|
|
149
|
+
# Uses .test TLD (RFC 2606 reserved, never resolves) for safety.
|
|
150
|
+
|
|
151
|
+
- id: "DUMMY-URL-DENY-001"
|
|
152
|
+
category: testing
|
|
153
|
+
severity: critical
|
|
154
|
+
confidence: 0.95
|
|
155
|
+
action: block
|
|
156
|
+
pattern: "sage-canary-deny-4e91ca37\\.test"
|
|
157
|
+
match_on: url
|
|
158
|
+
title: "[TEST] Canary deny URL"
|
|
159
|
+
expires_at: null
|
|
160
|
+
revoked: false
|
|
161
|
+
|
|
162
|
+
- id: "DUMMY-URL-ASK-001"
|
|
163
|
+
category: testing
|
|
164
|
+
severity: high
|
|
165
|
+
confidence: 0.90
|
|
166
|
+
action: require_approval
|
|
167
|
+
pattern: "sage-canary-ask-b26d80f5\\.test"
|
|
168
|
+
match_on: url
|
|
169
|
+
title: "[TEST] Canary approval URL"
|
|
170
|
+
expires_at: null
|
|
171
|
+
revoked: false
|
|
172
|
+
|
|
173
|
+
- id: "DUMMY-URL-LOG-001"
|
|
174
|
+
category: testing
|
|
175
|
+
severity: low
|
|
176
|
+
confidence: 0.90
|
|
177
|
+
action: log
|
|
178
|
+
pattern: "sage-canary-log-65f3d7a4\\.test"
|
|
179
|
+
match_on: url
|
|
180
|
+
title: "[TEST] Canary log-only URL"
|
|
181
|
+
expires_at: null
|
|
182
|
+
revoked: false
|
|
183
|
+
|
|
184
|
+
# ─── Domain pattern (verifies domain→url routing in heuristics) ─────
|
|
185
|
+
|
|
186
|
+
- id: "DUMMY-DOMAIN-DENY-001"
|
|
187
|
+
category: testing
|
|
188
|
+
severity: critical
|
|
189
|
+
confidence: 0.95
|
|
190
|
+
action: block
|
|
191
|
+
pattern: "sage-canary-domain-0c82eb16\\.test"
|
|
192
|
+
match_on: domain
|
|
193
|
+
title: "[TEST] Canary deny domain"
|
|
194
|
+
expires_at: null
|
|
195
|
+
revoked: false
|