@gendigital/sage-openclaw 0.8.0 → 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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "sage-openclaw",
3
3
  "name": "Sage",
4
- "version": "0.8.0",
4
+ "version": "0.9.0",
5
5
  "description": "Safety for Agents — ADR layer that guards commands, files, and web requests",
6
6
  "skills": [
7
7
  "resources/skills/security-awareness"
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gendigital/sage-openclaw",
3
3
  "license": "Apache-2.0",
4
- "version": "0.8.0",
4
+ "version": "0.9.0",
5
5
  "type": "module",
6
6
  "description": "Safety for Agents — ADR layer for OpenClaw",
7
7
  "main": "./dist/index.cjs",
@@ -21,7 +21,7 @@
21
21
  "esbuild": "^0.25.0",
22
22
  "typescript": "^5.9.0",
23
23
  "vitest": "^4.0.0",
24
- "@gendigital/sage-core": "0.8.0"
24
+ "@gendigital/sage-core": "0.9.0"
25
25
  },
26
26
  "openclaw": {
27
27
  "extensions": [
@@ -29,6 +29,9 @@
29
29
  ],
30
30
  "compat": {
31
31
  "pluginApi": ">=2026.3.28"
32
+ },
33
+ "build": {
34
+ "openclawVersion": "2026.3.28"
32
35
  }
33
36
  },
34
37
  "engines": {
@@ -164,15 +164,19 @@
164
164
  expires_at: null
165
165
  revoked: false
166
166
 
167
- # --- Python one-liner with dangerous imports ---
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.
168
172
  - id: "CLT-CMD-015"
169
173
  category: tool
170
174
  severity: high
171
175
  confidence: 0.80
172
176
  action: require_approval
173
- pattern: "python[3]?\\s+-c\\s+[\"'][^\"']*\\b(os\\.system|subprocess|os\\.exec|os\\.popen|__import__)\\b"
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*\\("
174
178
  match_on: command
175
- title: "Python one-liner with dangerous imports"
179
+ title: "Python one-liner invoking shell/exec/subprocess call"
176
180
  expires_at: null
177
181
  revoked: false
178
182
 
@@ -204,7 +208,10 @@
204
208
  severity: high
205
209
  confidence: 0.85
206
210
  action: block
207
- pattern: "\\bxargs\\b[^|;]*\\b(curl|wget|bash|sh)\\b"
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])"
208
215
  match_on: command
209
216
  title: "xargs dispatching download or shell execution"
210
217
  expires_at: null
@@ -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
@@ -165,7 +165,7 @@
165
165
  severity: high
166
166
  confidence: 0.80
167
167
  action: require_approval
168
- pattern: "(telnet(\\.exe)?|nmap(\\.exe)?|Invoke-ARPScan\\.ps1|Invoke-PortScan\\.ps1|Invoke-SMBScanner\\.ps1|Port-Scan\\.ps1)"
168
+ pattern: "(\\btelnet(\\.exe)?\\b|\\bnmap(\\.exe)?\\b|Invoke-ARPScan\\.ps1|Invoke-PortScan\\.ps1|Invoke-SMBScanner\\.ps1|Port-Scan\\.ps1)"
169
169
  case_insensitive: true
170
170
  match_on: command
171
171
  title: "MITRE ATT&CK T1046 - Network Service Scanning"
@@ -191,7 +191,7 @@
191
191
  severity: high
192
192
  confidence: 0.80
193
193
  action: require_approval
194
- pattern: "(schtasks(\\.exe)?\\s+/create|schtasks(\\.exe)?\\s+/%windir:~0,1%reate|at\\.exe)"
194
+ pattern: "(schtasks(\\.exe)?\\s+/create|schtasks(\\.exe)?\\s+/%windir:~0,1%reate|\\bat\\.exe\\b)"
195
195
  case_insensitive: true
196
196
  match_on: command
197
197
  title: "MITRE ATT&CK T1053.005 - Scheduled Task"
@@ -0,0 +1,334 @@
1
+ # Prompt injection detection heuristic rules (tier 1)
2
+ # Catches common PI patterns with zero model dependency, ~1ms.
3
+ # Designed for low false-positive rate on coding content.
4
+ #
5
+ # Sources: original Sage PI prototype, PR #90 (promptware), @stackone/defender patterns.
6
+ # These complement the ML model (tier 2) which handles subtler attacks.
7
+
8
+ # ── Instruction Override ────────────────────────────────────────────
9
+ # The most common PI pattern family. Well-established attack surface.
10
+
11
+ - id: "CLT-PI-001"
12
+ category: prompt_injection
13
+ severity: critical
14
+ confidence: 0.90
15
+ action: block
16
+ case_insensitive: true
17
+ pattern: "ignore\\s+(all\\s+)?(previous|prior|above|earlier)\\s+(instructions?|directives?|rules?|guidelines?|prompts?|directions?)"
18
+ match_on: content
19
+ title: "Instruction override: ignore previous"
20
+ expires_at: null
21
+ revoked: false
22
+
23
+ - id: "CLT-PI-002"
24
+ category: prompt_injection
25
+ severity: critical
26
+ confidence: 0.90
27
+ action: block
28
+ case_insensitive: true
29
+ pattern: "disregard\\s+(all\\s+)?(previous|prior|above|your)\\s+(instructions?|directives?|rules?|guidelines?|safety)"
30
+ match_on: content
31
+ title: "Instruction override: disregard directives"
32
+ expires_at: null
33
+ revoked: false
34
+
35
+ - id: "CLT-PI-003"
36
+ category: prompt_injection
37
+ severity: critical
38
+ confidence: 0.90
39
+ action: block
40
+ case_insensitive: true
41
+ pattern: "forget\\s+(all\\s+)?(your\\s+)?(previous\\s+)?(instructions?|rules?|guidelines?|restrictions?|constraints?|context)"
42
+ match_on: content
43
+ title: "Instruction override: forget instructions"
44
+ expires_at: null
45
+ revoked: false
46
+
47
+ - id: "CLT-PI-004"
48
+ category: prompt_injection
49
+ severity: critical
50
+ confidence: 0.90
51
+ action: block
52
+ case_insensitive: true
53
+ pattern: "override\\s+(the\\s+)?(system\\s+)?(prompt|instructions?|rules?|guidelines?)"
54
+ match_on: content
55
+ title: "Instruction override: direct override"
56
+ expires_at: null
57
+ revoked: false
58
+
59
+ - id: "CLT-PI-005"
60
+ category: prompt_injection
61
+ severity: high
62
+ confidence: 0.85
63
+ action: block
64
+ case_insensitive: true
65
+ pattern: "(new|updated?|revised?|changed?)\\s+instructions?:\\s*"
66
+ match_on: content
67
+ title: "Instruction override: inject new instructions"
68
+ expires_at: null
69
+ revoked: false
70
+
71
+ # ── Role / Persona Override ─────────────────────────────────────────
72
+ # Attempts to reassign the AI's identity or role.
73
+
74
+ - id: "CLT-PI-010"
75
+ category: prompt_injection
76
+ severity: critical
77
+ confidence: 0.90
78
+ action: block
79
+ case_insensitive: true
80
+ pattern: "you\\s+are\\s+now\\s+(a\\s+)?(different|new|the|my|an?\\s+unrestricted|an?\\s+unfiltered)"
81
+ match_on: content
82
+ title: "Role override: identity reassignment"
83
+ expires_at: null
84
+ revoked: false
85
+
86
+ - id: "CLT-PI-011"
87
+ category: prompt_injection
88
+ severity: high
89
+ confidence: 0.85
90
+ action: block
91
+ case_insensitive: true
92
+ pattern: "\\bDAN\\b.*?(do\\s+anything|jailbreak|no\\s+restrictions)"
93
+ match_on: content
94
+ title: "Role override: DAN jailbreak"
95
+ expires_at: null
96
+ revoked: false
97
+
98
+ - id: "CLT-PI-012"
99
+ category: prompt_injection
100
+ severity: high
101
+ confidence: 0.85
102
+ action: block
103
+ case_insensitive: true
104
+ pattern: "developer\\s+mode\\s+(is\\s+)?(now\\s+)?(enabled?|activated?|on).{0,50}(comply|content\\s+polic|no\\s+restrict|without\\s+restrict|any\\s+request)"
105
+ match_on: content
106
+ title: "Role override: developer mode jailbreak"
107
+ expires_at: null
108
+ revoked: false
109
+
110
+ - id: "CLT-PI-013"
111
+ category: prompt_injection
112
+ severity: high
113
+ confidence: 0.85
114
+ action: block
115
+ case_insensitive: true
116
+ pattern: "act\\s+(as|like)\\s+(a\\s+)?(system|admin|root|superuser)"
117
+ match_on: content
118
+ title: "Role override: privileged role assumption"
119
+ expires_at: null
120
+ revoked: false
121
+
122
+ # ── Security Bypass ─────────────────────────────────────────────────
123
+ # Attempts to disable safety mechanisms.
124
+
125
+ - id: "CLT-PI-020"
126
+ category: prompt_injection
127
+ severity: critical
128
+ confidence: 0.85
129
+ action: block
130
+ case_insensitive: true
131
+ pattern: "(bypass|disable)\\s+(the\\s+)?(security|safety|guardrails?|filters?|restrictions?)"
132
+ match_on: content
133
+ title: "Security bypass: disable safety features"
134
+ expires_at: null
135
+ revoked: false
136
+
137
+ - id: "CLT-PI-021"
138
+ category: prompt_injection
139
+ severity: high
140
+ confidence: 0.85
141
+ action: block
142
+ case_insensitive: true
143
+ pattern: "ignore\\s+(the\\s+)?(safety|security|ethical)\\s+(guidelines?|rules?|restrictions?)"
144
+ match_on: content
145
+ title: "Security bypass: ignore safety guidelines"
146
+ expires_at: null
147
+ revoked: false
148
+
149
+ - id: "CLT-PI-022"
150
+ category: prompt_injection
151
+ severity: high
152
+ confidence: 0.80
153
+ action: block
154
+ case_insensitive: true
155
+ pattern: "skip\\s+(all\\s+)?security\\s+checks"
156
+ match_on: content
157
+ title: "Security bypass: skip security checks"
158
+ expires_at: null
159
+ revoked: false
160
+
161
+ - id: "CLT-PI-023"
162
+ category: prompt_injection
163
+ severity: critical
164
+ confidence: 0.90
165
+ action: block
166
+ case_insensitive: true
167
+ pattern: "system\\s+override.{0,50}(execut|disabl|bypass|security|safet|comply|filter)"
168
+ match_on: content
169
+ title: "Security bypass: system override with action"
170
+ expires_at: null
171
+ revoked: false
172
+
173
+ # ── Anti-Transparency ──────────────────────────────────────────────
174
+ # Instructions to hide activity from the user.
175
+
176
+ - id: "CLT-PI-030"
177
+ category: prompt_injection
178
+ severity: critical
179
+ confidence: 0.90
180
+ action: block
181
+ case_insensitive: true
182
+ pattern: "do\\s+not\\s+(tell|inform|mention|reveal|show|disclose)\\s+(the\\s+)?(user|human|operator|developer)"
183
+ match_on: content
184
+ title: "Anti-transparency: hide from user"
185
+ expires_at: null
186
+ revoked: false
187
+
188
+ # ── Prompt Exfiltration ────────────────────────────────────────────
189
+ # Attempts to extract the system prompt or instructions.
190
+
191
+ - id: "CLT-PI-040"
192
+ category: prompt_injection
193
+ severity: high
194
+ confidence: 0.85
195
+ action: block
196
+ case_insensitive: true
197
+ pattern: "reveal\\s+(your\\s+)?(system\\s+)?prompt"
198
+ match_on: content
199
+ title: "Prompt exfiltration: reveal system prompt"
200
+ expires_at: null
201
+ revoked: false
202
+
203
+ - id: "CLT-PI-041"
204
+ category: prompt_injection
205
+ severity: high
206
+ confidence: 0.85
207
+ action: block
208
+ case_insensitive: true
209
+ pattern: "show\\s+(me\\s+)?(your\\s+)?(initial|original|system|hidden)\\s+instructions?"
210
+ match_on: content
211
+ title: "Prompt exfiltration: show hidden instructions"
212
+ expires_at: null
213
+ revoked: false
214
+
215
+ - id: "CLT-PI-042"
216
+ category: prompt_injection
217
+ severity: high
218
+ confidence: 0.85
219
+ action: block
220
+ case_insensitive: true
221
+ pattern: "repeat\\s+(back\\s+)?(everything|all|your\\s+instructions?)"
222
+ match_on: content
223
+ title: "Prompt exfiltration: repeat instructions"
224
+ expires_at: null
225
+ revoked: false
226
+
227
+ - id: "CLT-PI-043"
228
+ category: prompt_injection
229
+ severity: high
230
+ confidence: 0.85
231
+ action: block
232
+ case_insensitive: true
233
+ pattern: "output\\s+(your\\s+)?(initialization|system\\s+prompt|initial\\s+instructions?)"
234
+ match_on: content
235
+ title: "Prompt exfiltration: output initialization"
236
+ expires_at: null
237
+ revoked: false
238
+
239
+ # ── Structural Injection ───────────────────────────────────────────
240
+ # Injection hiding in HTML, markdown, or JSON structures.
241
+
242
+ - id: "CLT-PI-050"
243
+ category: prompt_injection
244
+ severity: high
245
+ confidence: 0.85
246
+ action: block
247
+ case_insensitive: true
248
+ pattern: "<!--\\s*(?:system|ignore|instruction|prompt|important|override|execute).*?-->"
249
+ match_on: content
250
+ title: "Structural injection: HTML comment with injection keywords"
251
+ expires_at: null
252
+ revoked: false
253
+
254
+ - id: "CLT-PI-051"
255
+ category: prompt_injection
256
+ severity: high
257
+ confidence: 0.85
258
+ action: block
259
+ case_insensitive: true
260
+ pattern: "\\[.*?\\]\\(.*?(?:ignore|forget|system|instruction|override).*?\\)"
261
+ match_on: content
262
+ title: "Structural injection: markdown link with hidden injection"
263
+ expires_at: null
264
+ revoked: false
265
+
266
+ # ── Role Marker Injection ──────────────────────────────────────────
267
+ # Fake conversation turn markers to confuse the model.
268
+
269
+ - id: "CLT-PI-060"
270
+ category: prompt_injection
271
+ severity: high
272
+ confidence: 0.85
273
+ action: block
274
+ case_insensitive: true
275
+ pattern: "\\n\\s*\\n\\s*(Human|User|Assistant|System)\\s*:"
276
+ match_on: content
277
+ title: "Role marker injection: fake conversation turn"
278
+ expires_at: null
279
+ revoked: false
280
+
281
+ - id: "CLT-PI-061"
282
+ category: prompt_injection
283
+ severity: high
284
+ confidence: 0.85
285
+ action: block
286
+ case_insensitive: true
287
+ pattern: "\\[INST\\]|\\[/INST\\]"
288
+ match_on: content
289
+ title: "Role marker injection: Llama instruction format"
290
+ expires_at: null
291
+ revoked: false
292
+
293
+ # ── Encoding / Obfuscation ─────────────────────────────────────────
294
+ # Obfuscated injection attempts.
295
+
296
+ - id: "CLT-PI-070"
297
+ category: prompt_injection
298
+ severity: high
299
+ confidence: 0.80
300
+ action: require_approval
301
+ case_insensitive: true
302
+ pattern: "1gn0r3|f0rg3t|byp4ss|syst3m|4dm1n"
303
+ match_on: content
304
+ title: "Encoding: leetspeak obfuscation of injection keywords"
305
+ expires_at: null
306
+ revoked: false
307
+
308
+ # ── Credential Exfiltration via Injection ──────────────────────────
309
+ # PI-driven data exfiltration patterns. Note: bare curl/wget commands
310
+ # are NOT PI — these only match when combined with credential targets.
311
+
312
+ - id: "CLT-PI-080"
313
+ category: prompt_injection
314
+ severity: high
315
+ confidence: 0.80
316
+ action: block
317
+ case_insensitive: true
318
+ pattern: "cat\\s+~/\\.(env|ssh|aws|gnupg).*\\|.*curl"
319
+ match_on: content
320
+ title: "Credential exfiltration: pipe dotfile to curl"
321
+ expires_at: null
322
+ revoked: false
323
+
324
+ - id: "CLT-PI-081"
325
+ category: prompt_injection
326
+ severity: high
327
+ confidence: 0.80
328
+ action: block
329
+ case_insensitive: true
330
+ pattern: "output\\s+(all\\s+)?(the\\s+)?environment\\s+variables.{0,50}(send|post|upload|exfiltrat|curl|fetch)"
331
+ match_on: content
332
+ title: "Credential exfiltration: dump env vars and send"
333
+ expires_at: null
334
+ revoked: false
@@ -39,14 +39,17 @@
39
39
  revoked: false
40
40
 
41
41
  # --- IP-based URLs (often C2 or staging) ---
42
+ # Excludes loopback (127/8), unspecified (0/8), RFC1918 private
43
+ # (10/8, 172.16/12, 192.168/16), and link-local (169.254/16) ranges,
44
+ # which are common in local development and rarely indicate C2 traffic.
42
45
  - id: "CLT-URL-004"
43
46
  category: network_egress
44
47
  severity: medium
45
48
  confidence: 0.65
46
49
  action: require_approval
47
- pattern: "https?://\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}[:/]"
50
+ pattern: "https?://(?!(?:127|10|0)\\.|192\\.168\\.|169\\.254\\.|172\\.(?:1[6-9]|2\\d|3[01])\\.)\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}[:/]"
48
51
  match_on: url
49
- title: "Direct IP address URL (potential C2 or staging server)"
52
+ title: "Direct public IP address URL (potential C2 or staging server)"
50
53
  expires_at: null
51
54
  revoked: false
52
55