@highflame/policy 2.2.34 → 2.2.36

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 (39) hide show
  1. package/_schemas/agent_ops/context.json +30 -0
  2. package/_schemas/agent_ops/schema.cedarschema +7 -0
  3. package/_schemas/agent_ops/templates/ported/agent-security/agent_identity_multi_agent_safety.cedar +3 -17
  4. package/_schemas/agent_ops/templates/ported/threat-detection/security_patterns.cedar +7 -19
  5. package/_schemas/agent_ops/templates/ported/threat-detection/semantic_defaults.cedar +7 -33
  6. package/_schemas/agent_ops/templates/templates.json +4 -6
  7. package/_schemas/ai_gateway/context.json +30 -0
  8. package/_schemas/ai_gateway/schema.cedarschema +7 -0
  9. package/_schemas/ai_gateway/templates/defaults/tools.cedar +3 -17
  10. package/_schemas/ai_gateway/templates/templates.json +1 -2
  11. package/_schemas/guardrails/context.json +30 -0
  12. package/_schemas/guardrails/schema.cedarschema +7 -0
  13. package/_schemas/guardrails/templates/defaults/security_patterns.cedar +7 -19
  14. package/_schemas/guardrails/templates/profiles/multi_agent/agent_safety.cedar +3 -17
  15. package/_schemas/guardrails/templates/templates.json +4 -6
  16. package/_schemas/overwatch/context.json +30 -0
  17. package/_schemas/overwatch/schema.cedarschema +7 -0
  18. package/_schemas/sentry/templates/templates.json +0 -14
  19. package/dist/agent_ops-context.gen.d.ts +6 -1
  20. package/dist/agent_ops-context.gen.js +10 -0
  21. package/dist/agent_ops-defaults.gen.js +25 -79
  22. package/dist/ai_gateway-context.gen.d.ts +6 -1
  23. package/dist/ai_gateway-context.gen.js +10 -0
  24. package/dist/ai_gateway-defaults.gen.js +6 -21
  25. package/dist/ai_gateway-detectors.gen.js +6 -1
  26. package/dist/guardrails-context.gen.d.ts +6 -1
  27. package/dist/guardrails-context.gen.js +10 -0
  28. package/dist/guardrails-defaults.gen.js +18 -46
  29. package/dist/guardrails-detectors.gen.js +6 -1
  30. package/dist/overwatch-context.gen.d.ts +6 -1
  31. package/dist/overwatch-context.gen.js +10 -0
  32. package/dist/overwatch-defaults.gen.js +11 -37
  33. package/dist/overwatch-detectors.gen.js +6 -1
  34. package/dist/sentry-defaults.gen.d.ts +1 -1
  35. package/dist/sentry-defaults.gen.js +0 -56
  36. package/dist/service-schemas.gen.d.ts +4 -4
  37. package/dist/service-schemas.gen.js +48 -0
  38. package/package.json +1 -1
  39. package/_schemas/sentry/templates/defaults/file_safety.cedar +0 -31
@@ -1229,6 +1229,36 @@
1229
1229
  "required": false,
1230
1230
  "description": "All operation classes observed in the tool call, emitted by the AST command classifiers. Subset of: 'readonly', 'write_enabling', 'execute_enabling', 'network_access', 'unknown'. A single command can carry several classes; combine with contains() to match shapes — e.g. tool_operation_classes.contains(\"network_access\") && tool_operation_classes.contains(\"execute_enabling\") catches download-and-run (curl | sh). 'unknown' appears when any unrecognized or variable-expanded command was seen and should be treated as deny-worthy."
1231
1231
  },
1232
+ {
1233
+ "key": "resolved_target_paths",
1234
+ "type": "string",
1235
+ "required": false,
1236
+ "description": "Newline-delimited (leading+trailing \\n) union of the statically-resolved absolute target paths a shell command touches, any capability, emitted by the bash AST detector. Cedar like is full-string anchored and every value starts with the \\n delimiter, so patterns must begin with '*': anchored sub-tree \"*\\n/etc/*\" (matches only paths under /etc, unlike the loose \"*/etc/*\" which also hits a project etc/ dir at any depth), bare directory \"*\\n/etc\\n*\" (e.g. rm -rf /etc, no trailing slash), exact file \"*\\n/etc/passwd\\n*\". Resolution is purely lexical (cwd-join + path.Clean; quoting, escapes, wrappers, cd/VAR/bash -c normalized); remote endpoints and dynamic operands are never fabricated."
1237
+ },
1238
+ {
1239
+ "key": "read_target_paths",
1240
+ "type": "string",
1241
+ "required": false,
1242
+ "description": "Newline-delimited resolved absolute paths a shell command reads or enumerates, emitted by the bash AST detector. \\n-anchored: match with like patterns that begin with '*' (see resolved_target_paths)."
1243
+ },
1244
+ {
1245
+ "key": "write_target_paths",
1246
+ "type": "string",
1247
+ "required": false,
1248
+ "description": "Newline-delimited resolved absolute paths a shell command writes, creates, or destroys (redirects, cp/mv/dd, curl/wget -o, scp/rsync local dest, tar/unzip/cpio extraction, yq -i), emitted by the bash AST detector. \\n-anchored: e.g. write_target_paths like \"*\\n/etc/cron.d/*\"."
1249
+ },
1250
+ {
1251
+ "key": "exec_target_paths",
1252
+ "type": "string",
1253
+ "required": false,
1254
+ "description": "Newline-delimited resolved absolute paths a shell command executes as a script, emitted by the bash AST detector. \\n-anchored: match with like patterns that begin with '*' (see resolved_target_paths)."
1255
+ },
1256
+ {
1257
+ "key": "unresolved_target",
1258
+ "type": "boolean",
1259
+ "required": false,
1260
+ "description": "True when a shell command's target hid behind a variable, glob, command substitution, or inline shell code that static analysis could not resolve, or when the 64-path / 4096-byte path-list cap truncated the results. Benign dev traffic sets this frequently (variables, globs, and command substitution are everywhere, and the truncation cap trips it too), so it is NOT a deny signal on its own — combine it with a path or operation match, and reserve a blanket deny-on-unresolved rule for high-assurance or allowlisted environments."
1261
+ },
1232
1262
  {
1233
1263
  "key": "path",
1234
1264
  "type": "string",
@@ -421,6 +421,13 @@ namespace AgentOps {
421
421
  // Tool Operation Classifier (optional)
422
422
  "tool_operation_classes"?: Set<String>,
423
423
 
424
+ // --- Bash AST resolved target paths (#411 / CAP-DET-007) — newline-delimited (leading+trailing \n); Cedar `like` is anchored so patterns start with "*": sub-tree "*\n/etc/*", bare dir "*\n/etc\n*", exact "*\n/etc/passwd\n*" ---
425
+ "resolved_target_paths"?: String, // union of resolved absolute target paths, any capability
426
+ "read_target_paths"?: String, // paths the command reads or enumerates
427
+ "write_target_paths"?: String, // paths the command writes, creates, or destroys
428
+ "exec_target_paths"?: String, // paths executed as a script
429
+ "unresolved_target"?: Bool, // a target hid behind a variable/glob/$()/inline code, or the path-list cap truncated
430
+
424
431
  // Agentic - Multi-Turn Context (optional)
425
432
  "conversation_turn"?: Long,
426
433
  "multi_turn_detection"?: Boolean,
@@ -10,7 +10,6 @@
10
10
  // - agent_trust_level, agent_type, tool_name, tool_is_sensitive
11
11
  // - session_pii_detected, session_pii_types
12
12
  // - session_secrets_detected, session_injection_detected
13
- // - session_command_injection
14
13
  // - session_threat_turns: Long
15
14
  // - session_cumulative_risk_score: Long
16
15
  // - suspicious_pattern: Bool
@@ -106,22 +105,9 @@ when {
106
105
  context has session_injection_detected && context.session_injection_detected == true
107
106
  };
108
107
 
109
- @id("agent-identity.multi-agent-post-command-injection-shell")
110
- @name("Block shell after command injection in session")
111
- @description("Blocks call_tool when session_command_injection is true and tool_name is a shell tool.")
112
- @severity("critical")
113
- @tags("category:agent-identity,threat:command-injection,scope:per-agent,detection:aggregate,surface:call-tool,mitre:t1059")
114
- @reject_message("Tool execution blocked: command injection was detected earlier in this session — no agent may execute shell commands afterwards.")
115
- forbid (
116
- principal is AgentOps::Agent,
117
- action == AgentOps::Action::"call_tool",
118
- resource
119
- )
120
- when {
121
- context has session_command_injection && context.session_command_injection == true &&
122
- context has tool_name &&
123
- (context.tool_name == "shell" || context.tool_name == "execute_command" || context.tool_name == "bash")
124
- };
108
+ // The post-command-injection shell rule was removed while that detector is
109
+ // disabled, so this template cannot instantiate a rule that can never fire.
110
+ // See highflame-shield#386; restore it when the detector is re-enabled.
125
111
 
126
112
  // ---------------------------------------------------------------------------
127
113
  // Section 4: Cumulative risk circuit breakers
@@ -1,38 +1,26 @@
1
1
  // =============================================================================
2
2
  // Security Pattern Detection (Default)
3
3
  // =============================================================================
4
- // Blocks command injection, path traversal, and SQL injection using
5
- // regex-based pattern detection from Shield's security detectors.
4
+ // Blocks path traversal and SQL injection using regex-based pattern detection
5
+ // from Shield's security detectors.
6
+ //
7
+ // The command-injection rule was removed while that detector is disabled, so
8
+ // this template cannot instantiate a rule that can never fire. See
9
+ // highflame-shield#386; restore the rule when the detector is re-enabled.
6
10
  //
7
11
  // Context keys consumed:
8
- // - command_injection_detected: Bool
9
12
  // - path_traversal_detected: Bool
10
13
  // - path_traversal_severity: String
11
14
  // - sql_injection_detected: Bool
12
15
  // - sql_injection_score: Long (0-100)
13
16
  //
14
17
  // Compliance:
15
- // - MITRE T1059 (Command Injection), T1005 (Data from Local System)
18
+ // - MITRE T1005 (Data from Local System)
16
19
  //
17
20
  // Category: security
18
21
  // Namespace: AgentOps
19
22
  // =============================================================================
20
23
 
21
- @id("security.block-command-injection")
22
- @name("Block command injection")
23
- @description("Blocks process_prompt and call_tool when command_injection_detected is true.")
24
- @severity("critical")
25
- @tags("category:security,threat:command-injection,detection:pattern,mitre:t1059")
26
- @reject_message("Request blocked: command injection pattern detected — reverse shell, destructive command, or privilege escalation.")
27
- forbid (
28
- principal,
29
- action in [AgentOps::Action::"process_prompt", AgentOps::Action::"call_tool"],
30
- resource
31
- )
32
- when {
33
- context has command_injection_detected && context.command_injection_detected == true
34
- };
35
-
36
24
  @id("security.block-path-traversal")
37
25
  @name("Block path traversal")
38
26
  @description("Blocks process_prompt, call_tool, read_file, and write_file when path_traversal_detected is true and severity is high or critical.")
@@ -1,11 +1,15 @@
1
1
  // =============================================================================
2
2
  // Semantic Threat Detection (Default)
3
3
  // =============================================================================
4
- // Blocks injection attacks (command, SQL, path traversal), prompt injection,
5
- // jailbreak attempts, and encoded payloads using two detection tiers:
4
+ // Blocks injection attacks (SQL, path traversal), prompt injection, jailbreak
5
+ // attempts, and encoded payloads using two detection tiers:
6
6
  //
7
7
  // Tier 1 — Pattern-based (always available, no external dependency)
8
- // command_injection, sql_injection, path_traversal, detect_encoded
8
+ // sql_injection, path_traversal, detect_encoded
9
+ //
10
+ // The command-injection rules were removed while that detector is disabled, so
11
+ // this template cannot instantiate rules that can never fire. See
12
+ // highflame-shield#386; restore them when the detector is re-enabled.
9
13
  //
10
14
  // Tier 2 — ML classifiers (require Highflame API token)
11
15
  // injection_score, jailbreak_score
@@ -30,36 +34,6 @@
30
34
  // Tier 1: Pattern-based injection detection
31
35
  // ---------------------------------------------------------------------------
32
36
 
33
- @id("semantic.block-command-injection-tool")
34
- @name("Block command injection in tool calls")
35
- @description("Blocks call_tool when detected_threats contains \"command_injection\".")
36
- @severity("critical")
37
- @tags("category:semantic,threat:command-injection,detection:pattern,surface:call-tool,mitre:t1059,owasp:asi02")
38
- @reject_message("Tool execution blocked: command injection pattern detected — reverse shell, destructive command, or privilege escalation.")
39
- forbid (
40
- principal,
41
- action == AgentOps::Action::"call_tool",
42
- resource
43
- )
44
- when {
45
- context has detected_threats && context.detected_threats.contains("command_injection")
46
- };
47
-
48
- @id("semantic.block-command-injection-prompt")
49
- @name("Block command injection in prompts")
50
- @description("Blocks process_prompt when detected_threats contains \"command_injection\".")
51
- @severity("critical")
52
- @tags("category:semantic,threat:command-injection,detection:pattern,surface:process-prompt,mitre:t1059")
53
- @reject_message("Prompt blocked: command injection pattern detected.")
54
- forbid (
55
- principal,
56
- action == AgentOps::Action::"process_prompt",
57
- resource
58
- )
59
- when {
60
- context has detected_threats && context.detected_threats.contains("command_injection")
61
- };
62
-
63
37
  @id("semantic.block-sql-injection-tool")
64
38
  @name("Block SQL injection in tool calls")
65
39
  @description("Blocks call_tool when detected_threats contains \"sql_injection\".")
@@ -251,17 +251,15 @@
251
251
  {
252
252
  "id": "security.patterns",
253
253
  "name": "Security Pattern Detection",
254
- "description": "Block command injection, path traversal, and SQL injection using regex-based pattern detection.",
254
+ "description": "Block path traversal and SQL injection using regex-based pattern detection.",
255
255
  "category": "threat-detection",
256
256
  "file": "ported/threat-detection/security_patterns.cedar",
257
- "severity": "critical",
257
+ "severity": "high",
258
258
  "tags": [
259
259
  "category:security",
260
- "threat:command-injection",
261
260
  "threat:sql-injection",
262
261
  "threat:path-traversal",
263
- "detection:pattern",
264
- "mitre:t1059"
262
+ "detection:pattern"
265
263
  ]
266
264
  },
267
265
  {
@@ -610,7 +608,7 @@
610
608
  {
611
609
  "id": "semantic.defaults",
612
610
  "name": "Semantic Threat Detection",
613
- "description": "Block injection attacks (command, SQL, path, encoded) plus ML-detected prompt injection and jailbreak attempts.",
611
+ "description": "Block injection attacks (SQL, path, encoded) plus ML-detected prompt injection and jailbreak attempts.",
614
612
  "category": "threat-detection",
615
613
  "file": "ported/threat-detection/semantic_defaults.cedar",
616
614
  "severity": "critical",
@@ -187,6 +187,36 @@
187
187
  "required": false,
188
188
  "description": "All operation classes observed in the tool call, emitted by the AST command classifiers. Subset of: 'readonly', 'write_enabling', 'execute_enabling', 'network_access', 'unknown'. A single command can carry several classes; combine with contains() to match shapes — e.g. tool_operation_classes.contains(\"network_access\") && tool_operation_classes.contains(\"execute_enabling\") catches download-and-run (curl | sh). 'unknown' appears when any unrecognized or variable-expanded command was seen and should be treated as deny-worthy."
189
189
  },
190
+ {
191
+ "key": "resolved_target_paths",
192
+ "type": "string",
193
+ "required": false,
194
+ "description": "Newline-delimited (leading+trailing \\n) union of the statically-resolved absolute target paths a shell command touches, any capability, emitted by the bash AST detector. Cedar like is full-string anchored and every value starts with the \\n delimiter, so patterns must begin with '*': anchored sub-tree \"*\\n/etc/*\" (matches only paths under /etc, unlike the loose \"*/etc/*\" which also hits a project etc/ dir at any depth), bare directory \"*\\n/etc\\n*\" (e.g. rm -rf /etc, no trailing slash), exact file \"*\\n/etc/passwd\\n*\". Resolution is purely lexical (cwd-join + path.Clean; quoting, escapes, wrappers, cd/VAR/bash -c normalized); remote endpoints and dynamic operands are never fabricated. NOTE (AI Gateway): declared ahead of runtime emission — the gateway does not populate this until the bash classifier is wired (#173); policies validate now but will not match in the interim."
195
+ },
196
+ {
197
+ "key": "read_target_paths",
198
+ "type": "string",
199
+ "required": false,
200
+ "description": "Newline-delimited resolved absolute paths a shell command reads or enumerates, emitted by the bash AST detector. \\n-anchored: match with like patterns that begin with '*' (see resolved_target_paths). NOTE (AI Gateway): declared ahead of runtime emission — the gateway does not populate this until the bash classifier is wired (#173); policies validate now but will not match in the interim."
201
+ },
202
+ {
203
+ "key": "write_target_paths",
204
+ "type": "string",
205
+ "required": false,
206
+ "description": "Newline-delimited resolved absolute paths a shell command writes, creates, or destroys (redirects, cp/mv/dd, curl/wget -o, scp/rsync local dest, tar/unzip/cpio extraction, yq -i), emitted by the bash AST detector. \\n-anchored: e.g. write_target_paths like \"*\\n/etc/cron.d/*\". NOTE (AI Gateway): declared ahead of runtime emission — the gateway does not populate this until the bash classifier is wired (#173); policies validate now but will not match in the interim."
207
+ },
208
+ {
209
+ "key": "exec_target_paths",
210
+ "type": "string",
211
+ "required": false,
212
+ "description": "Newline-delimited resolved absolute paths a shell command executes as a script, emitted by the bash AST detector. \\n-anchored: match with like patterns that begin with '*' (see resolved_target_paths). NOTE (AI Gateway): declared ahead of runtime emission — the gateway does not populate this until the bash classifier is wired (#173); policies validate now but will not match in the interim."
213
+ },
214
+ {
215
+ "key": "unresolved_target",
216
+ "type": "boolean",
217
+ "required": false,
218
+ "description": "True when a shell command's target hid behind a variable, glob, command substitution, or inline shell code that static analysis could not resolve, or when the 64-path / 4096-byte path-list cap truncated the results. Benign dev traffic sets this frequently (variables, globs, and command substitution are everywhere, and the truncation cap trips it too), so it is NOT a deny signal on its own — combine it with a path or operation match, and reserve a blanket deny-on-unresolved rule for high-assurance or allowlisted environments. NOTE (AI Gateway): declared ahead of runtime emission — the gateway does not populate this until the bash classifier is wired (#173); policies validate now but will not match in the interim."
219
+ },
190
220
  {
191
221
  "key": "mcp_server_verified",
192
222
  "type": "boolean",
@@ -122,6 +122,13 @@ action call_tool appliesTo {
122
122
  // --- Tool Operation Classifier ---
123
123
  tool_operation_classes?: Set<String>, // subset of {"readonly", "write_enabling", "execute_enabling", "network_access", "unknown"}
124
124
 
125
+ // --- Bash AST resolved target paths (#411 / CAP-DET-007) — newline-delimited (leading+trailing \n); Cedar `like` is anchored so patterns start with "*": sub-tree "*\n/etc/*", bare dir "*\n/etc\n*", exact "*\n/etc/passwd\n*" ---
126
+ resolved_target_paths?: String, // union of resolved absolute target paths, any capability
127
+ read_target_paths?: String, // paths the command reads or enumerates
128
+ write_target_paths?: String, // paths the command writes, creates, or destroys
129
+ exec_target_paths?: String, // paths executed as a script
130
+ unresolved_target?: Bool, // a target hid behind a variable/glob/$()/inline code, or the path-list cap truncated
131
+
125
132
  // --- MCP Trust ---
126
133
  mcp_server_verified?: Bool, // Whether server is from verified registry
127
134
 
@@ -8,7 +8,6 @@
8
8
  // - Computed risk score (tool_risk_score)
9
9
  // - Detector category labels (tool_category, tool_is_sensitive)
10
10
  // - Threat aggregation (threat_count, max_threat_severity)
11
- // - Detection rule triggers (detected_threats)
12
11
  //
13
12
  // Context keys consumed:
14
13
  // - tool_risk_score: Long (0-100)
@@ -16,11 +15,9 @@
16
15
  // - tool_is_sensitive: Bool
17
16
  // - threat_count: Long
18
17
  // - max_threat_severity: Long (0-4)
19
- // - detected_threats: Set<String>
20
18
  //
21
19
  // Compliance:
22
20
  // - OWASP LLM06, OWASP ASI02
23
- // - MITRE T1059
24
21
  //
25
22
  // Category: tools
26
23
  // Namespace: AIGateway
@@ -88,17 +85,6 @@ when {
88
85
  context.threat_count >= 1 && context.max_threat_severity >= 3
89
86
  };
90
87
 
91
- @id("tools.block-command-injection")
92
- @name("Block command injection")
93
- @description("Blocks call_tool when detected_threats contains \"command_injection\".")
94
- @severity("critical")
95
- @tags("category:tools,threat:command-injection,detection:rule,surface:call-tool,mitre:t1059,owasp:asi02")
96
- @reject_message("Tool execution blocked: command injection pattern detected in tool arguments.")
97
- forbid (
98
- principal,
99
- action == AIGateway::Action::"call_tool",
100
- resource
101
- )
102
- when {
103
- context has detected_threats && context.detected_threats.contains("command_injection")
104
- };
88
+ // The command-injection rule was removed while that detector is disabled, so
89
+ // this template cannot instantiate a rule that can never fire. See
90
+ // highflame-shield#386; restore it when the detector is re-enabled.
@@ -75,13 +75,12 @@
75
75
  {
76
76
  "id": "tools.defaults",
77
77
  "name": "Tool Permissioning",
78
- "description": "Enforce tool risk scoring, block dangerous tools, and detect command injection in MCP tool arguments.",
78
+ "description": "Enforce tool risk scoring and block dangerous tools in MCP tool arguments.",
79
79
  "category": "tools",
80
80
  "file": "defaults/tools.cedar",
81
81
  "severity": "critical",
82
82
  "tags": [
83
83
  "category:tools",
84
- "threat:command-injection",
85
84
  "owasp:llm06",
86
85
  "owasp:asi02"
87
86
  ]
@@ -1066,6 +1066,36 @@
1066
1066
  "required": false,
1067
1067
  "description": "All operation classes observed in the tool call, emitted by the AST command classifiers. Subset of: 'readonly', 'write_enabling', 'execute_enabling', 'network_access', 'unknown'. A single command can carry several classes; combine with contains() to match shapes — e.g. tool_operation_classes.contains(\"network_access\") && tool_operation_classes.contains(\"execute_enabling\") catches download-and-run (curl | sh). 'unknown' appears when any unrecognized or variable-expanded command was seen and should be treated as deny-worthy."
1068
1068
  },
1069
+ {
1070
+ "key": "resolved_target_paths",
1071
+ "type": "string",
1072
+ "required": false,
1073
+ "description": "Newline-delimited (leading+trailing \\n) union of the statically-resolved absolute target paths a shell command touches, any capability, emitted by the bash AST detector. Cedar like is full-string anchored and every value starts with the \\n delimiter, so patterns must begin with '*': anchored sub-tree \"*\\n/etc/*\" (matches only paths under /etc, unlike the loose \"*/etc/*\" which also hits a project etc/ dir at any depth), bare directory \"*\\n/etc\\n*\" (e.g. rm -rf /etc, no trailing slash), exact file \"*\\n/etc/passwd\\n*\". Resolution is purely lexical (cwd-join + path.Clean; quoting, escapes, wrappers, cd/VAR/bash -c normalized); remote endpoints and dynamic operands are never fabricated."
1074
+ },
1075
+ {
1076
+ "key": "read_target_paths",
1077
+ "type": "string",
1078
+ "required": false,
1079
+ "description": "Newline-delimited resolved absolute paths a shell command reads or enumerates, emitted by the bash AST detector. \\n-anchored: match with like patterns that begin with '*' (see resolved_target_paths)."
1080
+ },
1081
+ {
1082
+ "key": "write_target_paths",
1083
+ "type": "string",
1084
+ "required": false,
1085
+ "description": "Newline-delimited resolved absolute paths a shell command writes, creates, or destroys (redirects, cp/mv/dd, curl/wget -o, scp/rsync local dest, tar/unzip/cpio extraction, yq -i), emitted by the bash AST detector. \\n-anchored: e.g. write_target_paths like \"*\\n/etc/cron.d/*\"."
1086
+ },
1087
+ {
1088
+ "key": "exec_target_paths",
1089
+ "type": "string",
1090
+ "required": false,
1091
+ "description": "Newline-delimited resolved absolute paths a shell command executes as a script, emitted by the bash AST detector. \\n-anchored: match with like patterns that begin with '*' (see resolved_target_paths)."
1092
+ },
1093
+ {
1094
+ "key": "unresolved_target",
1095
+ "type": "boolean",
1096
+ "required": false,
1097
+ "description": "True when a shell command's target hid behind a variable, glob, command substitution, or inline shell code that static analysis could not resolve, or when the 64-path / 4096-byte path-list cap truncated the results. Benign dev traffic sets this frequently (variables, globs, and command substitution are everywhere, and the truncation cap trips it too), so it is NOT a deny signal on its own — combine it with a path or operation match, and reserve a blanket deny-on-unresolved rule for high-assurance or allowlisted environments."
1098
+ },
1069
1099
  {
1070
1100
  "key": "cross_origin_detected",
1071
1101
  "type": "boolean",
@@ -405,6 +405,13 @@ namespace Guardrails {
405
405
  // Tool Operation Classifier (optional) — populated by AST-based classifiers (bash, python, etc.)
406
406
  "tool_operation_classes"?: Set<String>, // subset of {"readonly", "write_enabling", "execute_enabling", "network_access", "unknown"}
407
407
 
408
+ // --- Bash AST resolved target paths (#411 / CAP-DET-007) — newline-delimited (leading+trailing \n); Cedar `like` is anchored so patterns start with "*": sub-tree "*\n/etc/*", bare dir "*\n/etc\n*", exact "*\n/etc/passwd\n*" ---
409
+ "resolved_target_paths"?: String, // union of resolved absolute target paths, any capability
410
+ "read_target_paths"?: String, // paths the command reads or enumerates
411
+ "write_target_paths"?: String, // paths the command writes, creates, or destroys
412
+ "exec_target_paths"?: String, // paths executed as a script
413
+ "unresolved_target"?: Bool, // a target hid behind a variable/glob/$()/inline code, or the path-list cap truncated
414
+
408
415
  // Agentic - Multi-Turn Context (optional)
409
416
  "conversation_turn"?: Long,
410
417
  "multi_turn_detection"?: Bool,
@@ -1,38 +1,26 @@
1
1
  // =============================================================================
2
2
  // Security Pattern Detection (Default)
3
3
  // =============================================================================
4
- // Blocks command injection, path traversal, and SQL injection using
5
- // regex-based pattern detection from Shield's security detectors.
4
+ // Blocks path traversal and SQL injection using regex-based pattern detection
5
+ // from Shield's security detectors.
6
+ //
7
+ // The command-injection rule was removed while that detector is disabled, so
8
+ // this template cannot instantiate a rule that can never fire. See
9
+ // highflame-shield#386; restore the rule when the detector is re-enabled.
6
10
  //
7
11
  // Context keys consumed:
8
- // - command_injection_detected: Bool
9
12
  // - path_traversal_detected: Bool
10
13
  // - path_traversal_severity: String
11
14
  // - sql_injection_detected: Bool
12
15
  // - sql_injection_score: Long (0-100)
13
16
  //
14
17
  // Compliance:
15
- // - MITRE T1059 (Command Injection), T1005 (Data from Local System)
18
+ // - MITRE T1005 (Data from Local System)
16
19
  //
17
20
  // Category: security
18
21
  // Namespace: Guardrails
19
22
  // =============================================================================
20
23
 
21
- @id("security.block-command-injection")
22
- @name("Block command injection")
23
- @description("Blocks process_prompt and call_tool when command_injection_detected is true.")
24
- @severity("critical")
25
- @tags("category:security,threat:command-injection,detection:pattern,mitre:t1059")
26
- @reject_message("Request blocked: command injection pattern detected — reverse shell, destructive command, or privilege escalation.")
27
- forbid (
28
- principal,
29
- action in [Guardrails::Action::"process_prompt", Guardrails::Action::"call_tool"],
30
- resource
31
- )
32
- when {
33
- context has command_injection_detected && context.command_injection_detected == true
34
- };
35
-
36
24
  @id("security.block-path-traversal")
37
25
  @name("Block path traversal")
38
26
  @description("Blocks process_prompt, call_tool, read_file, and write_file when path_traversal_detected is true and severity is high or critical.")
@@ -10,7 +10,6 @@
10
10
  // - agent_trust_level, agent_type, tool_name, tool_is_sensitive
11
11
  // - session_pii_detected, session_pii_types
12
12
  // - session_secrets_detected, session_injection_detected
13
- // - session_command_injection
14
13
  // - session_threat_turns: Long
15
14
  // - session_cumulative_risk_score: Long
16
15
  // - suspicious_pattern: Bool
@@ -106,22 +105,9 @@ when {
106
105
  context has session_injection_detected && context.session_injection_detected == true
107
106
  };
108
107
 
109
- @id("agent-identity.multi-agent-post-command-injection-shell")
110
- @name("Block shell after command injection in session")
111
- @description("Blocks call_tool when session_command_injection is true and tool_name is a shell tool.")
112
- @severity("critical")
113
- @tags("category:agent-identity,threat:command-injection,scope:per-agent,detection:aggregate,surface:call-tool,mitre:t1059")
114
- @reject_message("Tool execution blocked: command injection was detected earlier in this session — no agent may execute shell commands afterwards.")
115
- forbid (
116
- principal is Guardrails::Agent,
117
- action == Guardrails::Action::"call_tool",
118
- resource
119
- )
120
- when {
121
- context has session_command_injection && context.session_command_injection == true &&
122
- context has tool_name &&
123
- (context.tool_name == "shell" || context.tool_name == "execute_command" || context.tool_name == "bash")
124
- };
108
+ // The post-command-injection shell rule was removed while that detector is
109
+ // disabled, so this template cannot instantiate a rule that can never fire.
110
+ // See highflame-shield#386; restore it when the detector is re-enabled.
125
111
 
126
112
  // ---------------------------------------------------------------------------
127
113
  // Section 4: Cumulative risk circuit breakers
@@ -6,7 +6,7 @@
6
6
  {
7
7
  "id": "security",
8
8
  "name": "Security",
9
- "description": "Block prompt injection, jailbreak attempts, command injection, path traversal, and SQL injection."
9
+ "description": "Block prompt injection, jailbreak attempts, path traversal, and SQL injection."
10
10
  },
11
11
  {
12
12
  "id": "privacy",
@@ -185,17 +185,15 @@
185
185
  {
186
186
  "id": "security.patterns",
187
187
  "name": "Security Pattern Detection",
188
- "description": "Block command injection, path traversal, and SQL injection using regex-based pattern detection.",
188
+ "description": "Block path traversal and SQL injection using regex-based pattern detection.",
189
189
  "category": "security",
190
190
  "file": "defaults/security_patterns.cedar",
191
- "severity": "critical",
191
+ "severity": "high",
192
192
  "tags": [
193
193
  "category:security",
194
- "threat:command-injection",
195
194
  "threat:sql-injection",
196
195
  "threat:path-traversal",
197
- "detection:pattern",
198
- "mitre:t1059"
196
+ "detection:pattern"
199
197
  ]
200
198
  },
201
199
  {
@@ -680,6 +680,36 @@
680
680
  "required": false,
681
681
  "description": "All operation classes observed in the tool call, emitted by the AST command classifiers. Subset of: 'readonly', 'write_enabling', 'execute_enabling', 'network_access', 'unknown'. A single command can carry several classes; combine with contains() to match shapes — e.g. tool_operation_classes.contains(\"network_access\") && tool_operation_classes.contains(\"execute_enabling\") catches download-and-run (curl | sh). Used by the Bash Operation Classes template. 'unknown' appears when any unrecognized or variable-expanded command was seen and should be treated as deny-worthy."
682
682
  },
683
+ {
684
+ "key": "resolved_target_paths",
685
+ "type": "string",
686
+ "required": false,
687
+ "description": "Newline-delimited (leading+trailing \\n) union of the statically-resolved absolute target paths a shell command touches, any capability, emitted by the bash AST detector. Cedar like is full-string anchored and every value starts with the \\n delimiter, so patterns must begin with '*': anchored sub-tree \"*\\n/etc/*\" (matches only paths under /etc, unlike the loose \"*/etc/*\" which also hits a project etc/ dir at any depth), bare directory \"*\\n/etc\\n*\" (e.g. rm -rf /etc, no trailing slash), exact file \"*\\n/etc/passwd\\n*\". Resolution is purely lexical (cwd-join + path.Clean; quoting, escapes, wrappers, cd/VAR/bash -c normalized); remote endpoints and dynamic operands are never fabricated."
688
+ },
689
+ {
690
+ "key": "read_target_paths",
691
+ "type": "string",
692
+ "required": false,
693
+ "description": "Newline-delimited resolved absolute paths a shell command reads or enumerates, emitted by the bash AST detector. \\n-anchored: match with like patterns that begin with '*' (see resolved_target_paths)."
694
+ },
695
+ {
696
+ "key": "write_target_paths",
697
+ "type": "string",
698
+ "required": false,
699
+ "description": "Newline-delimited resolved absolute paths a shell command writes, creates, or destroys (redirects, cp/mv/dd, curl/wget -o, scp/rsync local dest, tar/unzip/cpio extraction, yq -i), emitted by the bash AST detector. \\n-anchored: e.g. write_target_paths like \"*\\n/etc/cron.d/*\"."
700
+ },
701
+ {
702
+ "key": "exec_target_paths",
703
+ "type": "string",
704
+ "required": false,
705
+ "description": "Newline-delimited resolved absolute paths a shell command executes as a script, emitted by the bash AST detector. \\n-anchored: match with like patterns that begin with '*' (see resolved_target_paths)."
706
+ },
707
+ {
708
+ "key": "unresolved_target",
709
+ "type": "boolean",
710
+ "required": false,
711
+ "description": "True when a shell command's target hid behind a variable, glob, command substitution, or inline shell code that static analysis could not resolve, or when the 64-path / 4096-byte path-list cap truncated the results. Benign dev traffic sets this frequently (variables, globs, and command substitution are everywhere, and the truncation cap trips it too), so it is NOT a deny signal on its own — combine it with a path or operation match, and reserve a blanket deny-on-unresolved rule for high-assurance or allowlisted environments."
712
+ },
683
713
  {
684
714
  "key": "package_install_detected",
685
715
  "type": "boolean",
@@ -246,6 +246,13 @@ action call_tool appliesTo {
246
246
  // --- Tool Operation Classifier ---
247
247
  tool_operation_classes?: Set<String>, // subset of {"readonly", "write_enabling", "execute_enabling", "network_access", "unknown"}
248
248
 
249
+ // --- Bash AST resolved target paths (#411 / CAP-DET-007) — newline-delimited (leading+trailing \n); Cedar `like` is anchored so patterns start with "*": sub-tree "*\n/etc/*", bare dir "*\n/etc\n*", exact "*\n/etc/passwd\n*" ---
250
+ resolved_target_paths?: String, // union of resolved absolute target paths, any capability
251
+ read_target_paths?: String, // paths the command reads or enumerates
252
+ write_target_paths?: String, // paths the command writes, creates, or destroys
253
+ exec_target_paths?: String, // paths executed as a script
254
+ unresolved_target?: Bool, // a target hid behind a variable/glob/$()/inline code
255
+
249
256
  // --- Session Detection History (cross-turn sticky flags) ---
250
257
  session_pii_detected?: Bool,
251
258
  session_pii_types?: Set<String>,
@@ -23,11 +23,6 @@
23
23
  "name": "Content Safety",
24
24
  "description": "Block violent, harmful, hateful, sexual, or profane content."
25
25
  },
26
- {
27
- "id": "file-safety",
28
- "name": "File & Attachment Safety",
29
- "description": "Block file uploads containing secrets or PII."
30
- },
31
26
  {
32
27
  "id": "clipboard",
33
28
  "name": "Clipboard Policy",
@@ -146,15 +141,6 @@
146
141
  "compliance:hipaa"
147
142
  ]
148
143
  },
149
- {
150
- "id": "file-safety.block-upload-secrets",
151
- "name": "File & Attachment Safety",
152
- "description": "Block file uploads containing secrets in document content.",
153
- "category": "file-safety",
154
- "file": "defaults/file_safety.cedar",
155
- "severity": "critical",
156
- "tags": ["category:file-safety", "threat:secrets"]
157
- },
158
144
  {
159
145
  "id": "clipboard.defaults",
160
146
  "name": "Clipboard Policy",