@highflame/policy 2.2.11 → 2.2.23

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.
@@ -178,19 +178,6 @@
178
178
  "compliance:pci-dss",
179
179
  "compliance:hipaa"
180
180
  ]
181
- },
182
- {
183
- "id": "organization.permit-llm-default",
184
- "name": "Permit LLM proxy calls",
185
- "description": "Permit all LLM chat completion requests by default; deploy alongside threat-specific forbids for a permit-default posture.",
186
- "category": "organization",
187
- "file": "llm_default_allow.cedar",
188
- "severity": "low",
189
- "tags": [
190
- "category:organization",
191
- "surface:process-prompt",
192
- "posture:permit-default"
193
- ]
194
181
  }
195
182
  ]
196
183
  }
@@ -283,6 +283,42 @@
283
283
  "required": false,
284
284
  "description": "Risk score for cross-origin escalation (0-100). Higher scores indicate more suspicious cross-boundary activity"
285
285
  },
286
+ {
287
+ "key": "package_install_detected",
288
+ "type": "boolean",
289
+ "required": false,
290
+ "description": "Whether the event contains a recognized package install/download command (pip, npm, yarn, pnpm, bun, uv, gem, cargo, go, composer)"
291
+ },
292
+ {
293
+ "key": "packages_checked",
294
+ "type": "number",
295
+ "required": false,
296
+ "description": "Number of unique packages checked against the osv.dev database for this event"
297
+ },
298
+ {
299
+ "key": "malicious_package_detected",
300
+ "type": "boolean",
301
+ "required": false,
302
+ "description": "Whether any referenced package has a known-malicious OSV advisory (OpenSSF MAL- ID). Use to block supply-chain attacks at install time"
303
+ },
304
+ {
305
+ "key": "malicious_package_score",
306
+ "type": "number",
307
+ "required": false,
308
+ "description": "100 when a malicious package was detected, 0 otherwise"
309
+ },
310
+ {
311
+ "key": "malicious_packages",
312
+ "type": "array",
313
+ "required": false,
314
+ "description": "Malicious packages as ecosystem/name[@version] strings (e.g. 'PyPI/evil-pkg@1.0.0')"
315
+ },
316
+ {
317
+ "key": "package_check_status",
318
+ "type": "string",
319
+ "required": false,
320
+ "description": "Set to 'degraded' when the osv.dev lookup failed and packages could not be verified (fail-open). Combine with package_install_detected to fail closed"
321
+ },
286
322
  {
287
323
  "key": "encoded_content_detected",
288
324
  "type": "boolean",
@@ -949,6 +985,42 @@
949
985
  "required": false,
950
986
  "description": "Risk score for cross-origin escalation in tool calls (0-100)"
951
987
  },
988
+ {
989
+ "key": "package_install_detected",
990
+ "type": "boolean",
991
+ "required": false,
992
+ "description": "Whether the event contains a recognized package install/download command (pip, npm, yarn, pnpm, bun, uv, gem, cargo, go, composer)"
993
+ },
994
+ {
995
+ "key": "packages_checked",
996
+ "type": "number",
997
+ "required": false,
998
+ "description": "Number of unique packages checked against the osv.dev database for this event"
999
+ },
1000
+ {
1001
+ "key": "malicious_package_detected",
1002
+ "type": "boolean",
1003
+ "required": false,
1004
+ "description": "Whether any referenced package has a known-malicious OSV advisory (OpenSSF MAL- ID). Use to block supply-chain attacks at install time"
1005
+ },
1006
+ {
1007
+ "key": "malicious_package_score",
1008
+ "type": "number",
1009
+ "required": false,
1010
+ "description": "100 when a malicious package was detected, 0 otherwise"
1011
+ },
1012
+ {
1013
+ "key": "malicious_packages",
1014
+ "type": "array",
1015
+ "required": false,
1016
+ "description": "Malicious packages as ecosystem/name[@version] strings (e.g. 'PyPI/evil-pkg@1.0.0')"
1017
+ },
1018
+ {
1019
+ "key": "package_check_status",
1020
+ "type": "string",
1021
+ "required": false,
1022
+ "description": "Set to 'degraded' when the osv.dev lookup failed and packages could not be verified (fail-open). Combine with package_install_detected to fail closed"
1023
+ },
952
1024
  {
953
1025
  "key": "encoded_content_detected",
954
1026
  "type": "boolean",
@@ -0,0 +1,59 @@
1
+ // =============================================================================
2
+ // Malicious Package (Default)
3
+ // =============================================================================
4
+ // Blocks tool calls that install or download packages flagged as malicious
5
+ // by the osv.dev database (OpenSSF MAL- advisories). The malicious_package
6
+ // detector (Shield, Tier Slow) parses package-manager invocations (pip, npm,
7
+ // yarn, pnpm, bun, uv, gem, cargo, go, composer) out of tool-call arguments
8
+ // and checks each referenced package against the OSV batch API.
9
+ //
10
+ // Context keys consumed:
11
+ // - malicious_package_detected: Bool
12
+ // - package_install_detected: Bool
13
+ // - package_check_status: String ("" | "degraded")
14
+ //
15
+ // Compliance:
16
+ // - OWASP LLM03 (Supply Chain), OWASP ASI02
17
+ //
18
+ // Category: agent-security
19
+ // Namespace: Guardrails
20
+ // =============================================================================
21
+
22
+ @id("agent-security.block-malicious-package")
23
+ @name("Block malicious package installs")
24
+ @description("Blocks call_tool when a referenced package carries a known-malicious osv.dev (MAL-) advisory.")
25
+ @severity("critical")
26
+ @tags("category:agent-security,threat:supply-chain,detection:aggregate,surface:call-tool,owasp:llm03,owasp:asi02")
27
+ @reject_message("Package install blocked: the requested package is flagged as malicious in the osv.dev database.")
28
+ forbid (
29
+ principal,
30
+ action == Guardrails::Action::"call_tool",
31
+ resource
32
+ )
33
+ when {
34
+ context has malicious_package_detected &&
35
+ context.malicious_package_detected == true
36
+ };
37
+
38
+ // Alternative (fail-closed): the detector fails OPEN by design — when the
39
+ // OSV lookup is unavailable, installs proceed with package_check_status set
40
+ // to "degraded". Uncomment to block package installs whenever they cannot be
41
+ // verified, trading install availability for supply-chain certainty.
42
+ //
43
+ // @id("agent-security.block-unverified-package")
44
+ // @name("Block unverified package installs")
45
+ // @description("Blocks call_tool package installs when the malicious-package lookup is degraded.")
46
+ // @severity("medium")
47
+ // @tags("category:agent-security,threat:supply-chain,detection:aggregate,surface:call-tool,owasp:llm03")
48
+ // @reject_message("Package install blocked: the package could not be verified against the malicious-package database.")
49
+ // forbid (
50
+ // principal,
51
+ // action == Guardrails::Action::"call_tool",
52
+ // resource
53
+ // )
54
+ // when {
55
+ // context has package_install_detected &&
56
+ // context.package_install_detected == true &&
57
+ // context has package_check_status &&
58
+ // context.package_check_status == "degraded"
59
+ // };
@@ -2,14 +2,16 @@
2
2
  // Code Agent — Supply Chain Security
3
3
  // =============================================================================
4
4
  // Detects and blocks MCP server poisoning, indirect prompt injection from
5
- // tool outputs, credential theft chains, and destructive operation sequences.
5
+ // tool outputs, credential theft chains, destructive operation sequences,
6
+ // and installs of packages with known-malicious (MAL-) osv.dev advisories.
6
7
  //
7
8
  // Context keys consumed:
8
- // - tool_poisoning_score: Long (0-100)
9
- // - indirect_injection_score: Long (0-100)
10
- // - tool_is_sensitive: Bool
11
- // - suspicious_pattern: Bool
12
- // - pattern_type: String
9
+ // - tool_poisoning_score: Long (0-100)
10
+ // - indirect_injection_score: Long (0-100)
11
+ // - tool_is_sensitive: Bool
12
+ // - suspicious_pattern: Bool
13
+ // - pattern_type: String
14
+ // - malicious_package_detected: Bool
13
15
  //
14
16
  // Compliance:
15
17
  // - OWASP ASI01, ASI02, ASI04, LLM01 (indirect), MCP01–05
@@ -96,3 +98,19 @@ when {
96
98
  context has suspicious_pattern && context.suspicious_pattern == true &&
97
99
  context has pattern_type && context.pattern_type == "destructive_sequence"
98
100
  };
101
+
102
+ @id("agent-security.code-block-malicious-package")
103
+ @name("Block malicious package installs (code profile)")
104
+ @description("Blocks call_tool when a referenced package carries a known-malicious osv.dev (MAL-) advisory.")
105
+ @severity("critical")
106
+ @tags("category:agent-security,threat:supply-chain,detection:aggregate,surface:call-tool,owasp:llm03,owasp:asi02")
107
+ @reject_message("Package install blocked: the requested package is flagged as malicious in the osv.dev database.")
108
+ forbid (
109
+ principal,
110
+ action == Guardrails::Action::"call_tool",
111
+ resource
112
+ )
113
+ when {
114
+ context has malicious_package_detected &&
115
+ context.malicious_package_detected == true
116
+ };
@@ -151,6 +151,20 @@
151
151
  "owasp:asi02"
152
152
  ]
153
153
  },
154
+ {
155
+ "id": "agent-security.malicious-package",
156
+ "name": "Malicious Package",
157
+ "description": "Block package installs (pip, npm, yarn, pnpm, bun, uv, gem, cargo, go, composer) flagged as malicious.",
158
+ "category": "agent-security",
159
+ "file": "defaults/malicious_package.cedar",
160
+ "severity": "critical",
161
+ "tags": [
162
+ "category:agent-security",
163
+ "threat:supply-chain",
164
+ "owasp:llm03",
165
+ "owasp:asi02"
166
+ ]
167
+ },
154
168
  {
155
169
  "id": "agent-security.defaults",
156
170
  "name": "Agentic Safety",
@@ -292,7 +306,7 @@
292
306
  {
293
307
  "id": "agent-security.code-agent-supply-chain",
294
308
  "name": "Code Agent — Supply Chain",
295
- "description": "Block MCP server poisoning, indirect prompt injection, credential theft chains, and destructive sequences for coding agents.",
309
+ "description": "Block MCP server poisoning, indirect prompt injection, credential theft chains, destructive sequences, and malicious package installs for coding agents.",
296
310
  "category": "agent-security",
297
311
  "file": "profiles/code_agent/supply_chain.cedar",
298
312
  "severity": "critical",
@@ -1299,28 +1299,6 @@ when {
1299
1299
  )
1300
1300
  };
1301
1301
  `;
1302
- const AI_GATEWAY_ORGANIZATION_PERMIT_LLM_DEFAULT_CEDAR = `// =============================================================================
1303
- // LLM Default Allow
1304
- // =============================================================================
1305
- // Permits all LLM prompt processing by default. Deploy alongside threat-specific
1306
- // forbid policies to create a "default allow, block on threat" posture for LLM
1307
- // chat completions.
1308
- //
1309
- // Category: organization
1310
- // Namespace: AIGateway
1311
- // =============================================================================
1312
-
1313
- @id("organization.permit-llm-default")
1314
- @name("Permit LLM proxy calls")
1315
- @description("Permits all process_prompt actions for the LLM proxy.")
1316
- @severity("low")
1317
- @tags("category:organization,surface:process-prompt,posture:permit-default")
1318
- permit (
1319
- principal,
1320
- action == AIGateway::Action::"process_prompt",
1321
- resource
1322
- );
1323
- `;
1324
1302
  // =============================================================================
1325
1303
  // CATEGORIES
1326
1304
  // =============================================================================
@@ -1442,15 +1420,6 @@ export const AI_GATEWAY_TEMPLATES = [
1442
1420
  severity: 'critical',
1443
1421
  tags: ['category:privacy', 'threat:pii', 'detection:pattern', 'compliance:pci-dss', 'compliance:hipaa'],
1444
1422
  },
1445
- {
1446
- id: 'organization.permit-llm-default',
1447
- name: 'Permit LLM proxy calls',
1448
- description: 'Permit all LLM chat completion requests by default; deploy alongside threat-specific forbids for a permit-default posture.',
1449
- category: 'organization',
1450
- cedarText: AI_GATEWAY_ORGANIZATION_PERMIT_LLM_DEFAULT_CEDAR,
1451
- severity: 'low',
1452
- tags: ['category:organization', 'surface:process-prompt', 'posture:permit-default'],
1453
- },
1454
1423
  ];
1455
1424
  // =============================================================================
1456
1425
  // TEMPLATES METADATA
@@ -1636,19 +1605,6 @@ export const AI_GATEWAY_TEMPLATES_JSON = `{
1636
1605
  "compliance:pci-dss",
1637
1606
  "compliance:hipaa"
1638
1607
  ]
1639
- },
1640
- {
1641
- "id": "organization.permit-llm-default",
1642
- "name": "Permit LLM proxy calls",
1643
- "description": "Permit all LLM chat completion requests by default; deploy alongside threat-specific forbids for a permit-default posture.",
1644
- "category": "organization",
1645
- "file": "llm_default_allow.cedar",
1646
- "severity": "low",
1647
- "tags": [
1648
- "category:organization",
1649
- "surface:process-prompt",
1650
- "posture:permit-default"
1651
- ]
1652
1608
  }
1653
1609
  ]
1654
1610
  }
@@ -61,6 +61,9 @@ export declare const GuardrailsContextKey: {
61
61
  readonly LoopCount: "loop_count";
62
62
  readonly LoopDetected: "loop_detected";
63
63
  readonly LoopTool: "loop_tool";
64
+ readonly MaliciousPackageDetected: "malicious_package_detected";
65
+ readonly MaliciousPackageScore: "malicious_package_score";
66
+ readonly MaliciousPackages: "malicious_packages";
64
67
  readonly McpConfigRisk: "mcp_config_risk";
65
68
  readonly McpRiskScore: "mcp_risk_score";
66
69
  readonly McpRiskType: "mcp_risk_type";
@@ -68,6 +71,9 @@ export declare const GuardrailsContextKey: {
68
71
  readonly McpServerVerified: "mcp_server_verified";
69
72
  readonly McpTool: "mcp_tool";
70
73
  readonly MultiTurnDetection: "multi_turn_detection";
74
+ readonly PackageCheckStatus: "package_check_status";
75
+ readonly PackageInstallDetected: "package_install_detected";
76
+ readonly PackagesChecked: "packages_checked";
71
77
  readonly ParamTypeViolation: "param_type_violation";
72
78
  readonly ParamTypeViolations: "param_type_violations";
73
79
  readonly Path: "path";
@@ -137,4 +143,4 @@ export type GuardrailsContextKey = (typeof GuardrailsContextKey)[keyof typeof Gu
137
143
  * The full set of authorable context attribute keys for Guardrails.
138
144
  * Iterate this to enumerate the authorable surface (cockpit, conformance).
139
145
  */
140
- export declare const GuardrailsContextKeys: readonly ["agent_framework", "agent_id", "agent_publisher", "agent_trust_level", "agent_type", "budget_exceeded", "budget_remaining_pct", "code_languages", "code_ratio", "command_injection_detected", "command_injection_score", "command_injection_type", "contains_code", "contains_non_ascii", "content_safety_blocked", "content_safety_score", "content_topics", "content_type", "conversation_turn", "crime_score", "cross_origin_detected", "cross_origin_score", "cross_origin_type", "detected_language", "detected_script", "detector_count", "direction", "encoded_content_detected", "encoded_count", "encoded_score", "encoded_types", "factuality_score", "hallucination_score", "hate_speech_score", "highest_severity", "identity_type", "indirect_injection_score", "indirect_injection_type", "injection_deep_context_score", "injection_pulse_score", "injection_score", "injection_type", "invisible_chars_detected", "invisible_chars_score", "is_english", "is_latin_script", "jailbreak_deep_context_score", "jailbreak_pulse_score", "jailbreak_score", "keyword_categories", "keyword_count", "keyword_matched", "language_confidence", "loop_count", "loop_detected", "loop_tool", "mcp_config_risk", "mcp_risk_score", "mcp_risk_type", "mcp_server", "mcp_server_verified", "mcp_tool", "multi_turn_detection", "param_type_violation", "param_type_violations", "path", "path_traversal_detected", "path_traversal_severity", "path_traversal_type", "pattern_type", "phishing_detected", "pii_count", "pii_detected", "pii_score", "pii_types", "principal", "privilege_scope", "profanity_score", "request_id", "role", "rpm_exceeded", "rpm_remaining_pct", "rug_pull_detected", "rug_pull_score", "rug_pull_type", "script_confidence", "secret_count", "secret_types", "secrets_detected", "sentiment_score", "sequence_risk", "session_command_injection", "session_cumulative_risk_score", "session_injection_detected", "session_max_command_injection_score", "session_max_injection_score", "session_max_jailbreak_score", "session_max_pii_score", "session_max_secret_score", "session_max_sensitivity", "session_original_request", "session_pii_detected", "session_pii_types", "session_secret_types", "session_secrets_detected", "session_threat_turns", "sexual_score", "sql_injection_detected", "sql_injection_score", "sql_injection_type", "suspicious_pattern", "timestamp", "tool_category", "tool_is_builtin", "tool_is_sensitive", "tool_name", "tool_operation_classes", "tool_poisoning_detected", "tool_poisoning_score", "tool_poisoning_type", "tool_risk_score", "topic_confidence", "tpm_exceeded", "tpm_remaining_pct", "violence_score", "weapons_score"];
146
+ export declare const GuardrailsContextKeys: readonly ["agent_framework", "agent_id", "agent_publisher", "agent_trust_level", "agent_type", "budget_exceeded", "budget_remaining_pct", "code_languages", "code_ratio", "command_injection_detected", "command_injection_score", "command_injection_type", "contains_code", "contains_non_ascii", "content_safety_blocked", "content_safety_score", "content_topics", "content_type", "conversation_turn", "crime_score", "cross_origin_detected", "cross_origin_score", "cross_origin_type", "detected_language", "detected_script", "detector_count", "direction", "encoded_content_detected", "encoded_count", "encoded_score", "encoded_types", "factuality_score", "hallucination_score", "hate_speech_score", "highest_severity", "identity_type", "indirect_injection_score", "indirect_injection_type", "injection_deep_context_score", "injection_pulse_score", "injection_score", "injection_type", "invisible_chars_detected", "invisible_chars_score", "is_english", "is_latin_script", "jailbreak_deep_context_score", "jailbreak_pulse_score", "jailbreak_score", "keyword_categories", "keyword_count", "keyword_matched", "language_confidence", "loop_count", "loop_detected", "loop_tool", "malicious_package_detected", "malicious_package_score", "malicious_packages", "mcp_config_risk", "mcp_risk_score", "mcp_risk_type", "mcp_server", "mcp_server_verified", "mcp_tool", "multi_turn_detection", "package_check_status", "package_install_detected", "packages_checked", "param_type_violation", "param_type_violations", "path", "path_traversal_detected", "path_traversal_severity", "path_traversal_type", "pattern_type", "phishing_detected", "pii_count", "pii_detected", "pii_score", "pii_types", "principal", "privilege_scope", "profanity_score", "request_id", "role", "rpm_exceeded", "rpm_remaining_pct", "rug_pull_detected", "rug_pull_score", "rug_pull_type", "script_confidence", "secret_count", "secret_types", "secrets_detected", "sentiment_score", "sequence_risk", "session_command_injection", "session_cumulative_risk_score", "session_injection_detected", "session_max_command_injection_score", "session_max_injection_score", "session_max_jailbreak_score", "session_max_pii_score", "session_max_secret_score", "session_max_sensitivity", "session_original_request", "session_pii_detected", "session_pii_types", "session_secret_types", "session_secrets_detected", "session_threat_turns", "sexual_score", "sql_injection_detected", "sql_injection_score", "sql_injection_type", "suspicious_pattern", "timestamp", "tool_category", "tool_is_builtin", "tool_is_sensitive", "tool_name", "tool_operation_classes", "tool_poisoning_detected", "tool_poisoning_score", "tool_poisoning_type", "tool_risk_score", "topic_confidence", "tpm_exceeded", "tpm_remaining_pct", "violence_score", "weapons_score"];
@@ -63,6 +63,9 @@ export const GuardrailsContextKey = {
63
63
  LoopCount: 'loop_count',
64
64
  LoopDetected: 'loop_detected',
65
65
  LoopTool: 'loop_tool',
66
+ MaliciousPackageDetected: 'malicious_package_detected',
67
+ MaliciousPackageScore: 'malicious_package_score',
68
+ MaliciousPackages: 'malicious_packages',
66
69
  McpConfigRisk: 'mcp_config_risk',
67
70
  McpRiskScore: 'mcp_risk_score',
68
71
  McpRiskType: 'mcp_risk_type',
@@ -70,6 +73,9 @@ export const GuardrailsContextKey = {
70
73
  McpServerVerified: 'mcp_server_verified',
71
74
  McpTool: 'mcp_tool',
72
75
  MultiTurnDetection: 'multi_turn_detection',
76
+ PackageCheckStatus: 'package_check_status',
77
+ PackageInstallDetected: 'package_install_detected',
78
+ PackagesChecked: 'packages_checked',
73
79
  ParamTypeViolation: 'param_type_violation',
74
80
  ParamTypeViolations: 'param_type_violations',
75
81
  Path: 'path',
@@ -195,6 +201,9 @@ export const GuardrailsContextKeys = [
195
201
  GuardrailsContextKey.LoopCount,
196
202
  GuardrailsContextKey.LoopDetected,
197
203
  GuardrailsContextKey.LoopTool,
204
+ GuardrailsContextKey.MaliciousPackageDetected,
205
+ GuardrailsContextKey.MaliciousPackageScore,
206
+ GuardrailsContextKey.MaliciousPackages,
198
207
  GuardrailsContextKey.McpConfigRisk,
199
208
  GuardrailsContextKey.McpRiskScore,
200
209
  GuardrailsContextKey.McpRiskType,
@@ -202,6 +211,9 @@ export const GuardrailsContextKeys = [
202
211
  GuardrailsContextKey.McpServerVerified,
203
212
  GuardrailsContextKey.McpTool,
204
213
  GuardrailsContextKey.MultiTurnDetection,
214
+ GuardrailsContextKey.PackageCheckStatus,
215
+ GuardrailsContextKey.PackageInstallDetected,
216
+ GuardrailsContextKey.PackagesChecked,
205
217
  GuardrailsContextKey.ParamTypeViolation,
206
218
  GuardrailsContextKey.ParamTypeViolations,
207
219
  GuardrailsContextKey.Path,
@@ -580,6 +580,66 @@ when {
580
580
  context has tool_risk_score && context.tool_risk_score >= 71
581
581
  };
582
582
  `;
583
+ const GUARDRAILS_AGENT_SECURITY_MALICIOUS_PACKAGE_CEDAR = `// =============================================================================
584
+ // Malicious Package (Default)
585
+ // =============================================================================
586
+ // Blocks tool calls that install or download packages flagged as malicious
587
+ // by the osv.dev database (OpenSSF MAL- advisories). The malicious_package
588
+ // detector (Shield, Tier Slow) parses package-manager invocations (pip, npm,
589
+ // yarn, pnpm, bun, uv, gem, cargo, go, composer) out of tool-call arguments
590
+ // and checks each referenced package against the OSV batch API.
591
+ //
592
+ // Context keys consumed:
593
+ // - malicious_package_detected: Bool
594
+ // - package_install_detected: Bool
595
+ // - package_check_status: String ("" | "degraded")
596
+ //
597
+ // Compliance:
598
+ // - OWASP LLM03 (Supply Chain), OWASP ASI02
599
+ //
600
+ // Category: agent-security
601
+ // Namespace: Guardrails
602
+ // =============================================================================
603
+
604
+ @id("agent-security.block-malicious-package")
605
+ @name("Block malicious package installs")
606
+ @description("Blocks call_tool when a referenced package carries a known-malicious osv.dev (MAL-) advisory.")
607
+ @severity("critical")
608
+ @tags("category:agent-security,threat:supply-chain,detection:aggregate,surface:call-tool,owasp:llm03,owasp:asi02")
609
+ @reject_message("Package install blocked: the requested package is flagged as malicious in the osv.dev database.")
610
+ forbid (
611
+ principal,
612
+ action == Guardrails::Action::"call_tool",
613
+ resource
614
+ )
615
+ when {
616
+ context has malicious_package_detected &&
617
+ context.malicious_package_detected == true
618
+ };
619
+
620
+ // Alternative (fail-closed): the detector fails OPEN by design — when the
621
+ // OSV lookup is unavailable, installs proceed with package_check_status set
622
+ // to "degraded". Uncomment to block package installs whenever they cannot be
623
+ // verified, trading install availability for supply-chain certainty.
624
+ //
625
+ // @id("agent-security.block-unverified-package")
626
+ // @name("Block unverified package installs")
627
+ // @description("Blocks call_tool package installs when the malicious-package lookup is degraded.")
628
+ // @severity("medium")
629
+ // @tags("category:agent-security,threat:supply-chain,detection:aggregate,surface:call-tool,owasp:llm03")
630
+ // @reject_message("Package install blocked: the package could not be verified against the malicious-package database.")
631
+ // forbid (
632
+ // principal,
633
+ // action == Guardrails::Action::"call_tool",
634
+ // resource
635
+ // )
636
+ // when {
637
+ // context has package_install_detected &&
638
+ // context.package_install_detected == true &&
639
+ // context has package_check_status &&
640
+ // context.package_check_status == "degraded"
641
+ // };
642
+ `;
583
643
  const GUARDRAILS_AGENT_SECURITY_DEFAULTS_CEDAR = `// =============================================================================
584
644
  // Agentic Safety (Default)
585
645
  // =============================================================================
@@ -1595,14 +1655,16 @@ const GUARDRAILS_AGENT_SECURITY_CODE_AGENT_SUPPLY_CHAIN_CEDAR = `// ============
1595
1655
  // Code Agent — Supply Chain Security
1596
1656
  // =============================================================================
1597
1657
  // Detects and blocks MCP server poisoning, indirect prompt injection from
1598
- // tool outputs, credential theft chains, and destructive operation sequences.
1658
+ // tool outputs, credential theft chains, destructive operation sequences,
1659
+ // and installs of packages with known-malicious (MAL-) osv.dev advisories.
1599
1660
  //
1600
1661
  // Context keys consumed:
1601
- // - tool_poisoning_score: Long (0-100)
1602
- // - indirect_injection_score: Long (0-100)
1603
- // - tool_is_sensitive: Bool
1604
- // - suspicious_pattern: Bool
1605
- // - pattern_type: String
1662
+ // - tool_poisoning_score: Long (0-100)
1663
+ // - indirect_injection_score: Long (0-100)
1664
+ // - tool_is_sensitive: Bool
1665
+ // - suspicious_pattern: Bool
1666
+ // - pattern_type: String
1667
+ // - malicious_package_detected: Bool
1606
1668
  //
1607
1669
  // Compliance:
1608
1670
  // - OWASP ASI01, ASI02, ASI04, LLM01 (indirect), MCP01–05
@@ -1689,6 +1751,22 @@ when {
1689
1751
  context has suspicious_pattern && context.suspicious_pattern == true &&
1690
1752
  context has pattern_type && context.pattern_type == "destructive_sequence"
1691
1753
  };
1754
+
1755
+ @id("agent-security.code-block-malicious-package")
1756
+ @name("Block malicious package installs (code profile)")
1757
+ @description("Blocks call_tool when a referenced package carries a known-malicious osv.dev (MAL-) advisory.")
1758
+ @severity("critical")
1759
+ @tags("category:agent-security,threat:supply-chain,detection:aggregate,surface:call-tool,owasp:llm03,owasp:asi02")
1760
+ @reject_message("Package install blocked: the requested package is flagged as malicious in the osv.dev database.")
1761
+ forbid (
1762
+ principal,
1763
+ action == Guardrails::Action::"call_tool",
1764
+ resource
1765
+ )
1766
+ when {
1767
+ context has malicious_package_detected &&
1768
+ context.malicious_package_detected == true
1769
+ };
1692
1770
  `;
1693
1771
  const GUARDRAILS_DATA_PROTECTION_DATA_PIPELINE_CEDAR = `// =============================================================================
1694
1772
  // Data Pipeline — Data Protection (Secrets)
@@ -3436,6 +3514,15 @@ export const GUARDRAILS_TEMPLATES = [
3436
3514
  severity: 'critical',
3437
3515
  tags: ['category:agent-security', 'threat:command-injection', 'owasp:llm06', 'owasp:asi02'],
3438
3516
  },
3517
+ {
3518
+ id: 'agent-security.malicious-package',
3519
+ name: 'Malicious Package',
3520
+ description: 'Block package installs (pip, npm, yarn, pnpm, bun, uv, gem, cargo, go, composer) flagged as malicious.',
3521
+ category: 'agent-security',
3522
+ cedarText: GUARDRAILS_AGENT_SECURITY_MALICIOUS_PACKAGE_CEDAR,
3523
+ severity: 'critical',
3524
+ tags: ['category:agent-security', 'threat:supply-chain', 'owasp:llm03', 'owasp:asi02'],
3525
+ },
3439
3526
  {
3440
3527
  id: 'agent-security.defaults',
3441
3528
  name: 'Agentic Safety',
@@ -3538,7 +3625,7 @@ export const GUARDRAILS_TEMPLATES = [
3538
3625
  {
3539
3626
  id: 'agent-security.code-agent-supply-chain',
3540
3627
  name: 'Code Agent — Supply Chain',
3541
- description: 'Block MCP server poisoning, indirect prompt injection, credential theft chains, and destructive sequences for coding agents.',
3628
+ description: 'Block MCP server poisoning, indirect prompt injection, credential theft chains, destructive sequences, and malicious package installs for coding agents.',
3542
3629
  category: 'agent-security',
3543
3630
  cedarText: GUARDRAILS_AGENT_SECURITY_CODE_AGENT_SUPPLY_CHAIN_CEDAR,
3544
3631
  severity: 'critical',
@@ -3828,6 +3915,20 @@ export const GUARDRAILS_TEMPLATES_JSON = `{
3828
3915
  "owasp:asi02"
3829
3916
  ]
3830
3917
  },
3918
+ {
3919
+ "id": "agent-security.malicious-package",
3920
+ "name": "Malicious Package",
3921
+ "description": "Block package installs (pip, npm, yarn, pnpm, bun, uv, gem, cargo, go, composer) flagged as malicious.",
3922
+ "category": "agent-security",
3923
+ "file": "defaults/malicious_package.cedar",
3924
+ "severity": "critical",
3925
+ "tags": [
3926
+ "category:agent-security",
3927
+ "threat:supply-chain",
3928
+ "owasp:llm03",
3929
+ "owasp:asi02"
3930
+ ]
3931
+ },
3831
3932
  {
3832
3933
  "id": "agent-security.defaults",
3833
3934
  "name": "Agentic Safety",
@@ -3969,7 +4070,7 @@ export const GUARDRAILS_TEMPLATES_JSON = `{
3969
4070
  {
3970
4071
  "id": "agent-security.code-agent-supply-chain",
3971
4072
  "name": "Code Agent — Supply Chain",
3972
- "description": "Block MCP server poisoning, indirect prompt injection, credential theft chains, and destructive sequences for coding agents.",
4073
+ "description": "Block MCP server poisoning, indirect prompt injection, credential theft chains, destructive sequences, and malicious package installs for coding agents.",
3973
4074
  "category": "agent-security",
3974
4075
  "file": "profiles/code_agent/supply_chain.cedar",
3975
4076
  "severity": "critical",
@@ -378,6 +378,20 @@ export const GUARDRAILS_DETECTORS = [
378
378
  defendsAgainst: ["phishing"],
379
379
  exampleAttacks: [{ title: "Lookalike login URL", vulnerabilityId: "financial_fraud_facilitation", snippet: "Verify your account at http://paypa1-secure-login.example.", expectedSignal: {} }],
380
380
  },
381
+ {
382
+ id: "malicious_package",
383
+ displayName: "Malicious Package (OSV)",
384
+ category: "tool_safety",
385
+ stability: "preview",
386
+ tier: "slow",
387
+ inhouse: false,
388
+ model: null,
389
+ latencyP50Ms: 250,
390
+ emits: [{ name: "package_install_detected", type: "Bool", modifiable: false, semantic: "boolean_flag", description: "True iff a package install/download command was recognized in the event." }, { name: "packages_checked", type: "Long", modifiable: false, semantic: "count", description: "Number of unique packages checked against osv.dev." }, { name: "malicious_package_detected", type: "Bool", modifiable: false, semantic: "boolean_flag", description: "True iff any referenced package has a known-malicious (MAL-) OSV advisory." }, { name: "malicious_package_score", type: "Long", modifiable: false, semantic: "severity_0_100", description: "100 when a malicious package was detected, 0 otherwise." }, { name: "malicious_packages", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Malicious packages as ecosystem/name[@version] strings." }, { name: "package_check_status", type: "String", modifiable: false, semantic: "category_label", description: "Set to 'degraded' when the osv.dev lookup failed (fail-open); empty otherwise." }],
391
+ supportedModes: ["enforce", "monitor", "alert"],
392
+ defendsAgainst: ["supply_chain"],
393
+ exampleAttacks: [{ title: "Typosquatted PyPI package install", vulnerabilityId: "supply_chain", snippet: "pip install reqeusts", expectedSignal: {} }],
394
+ },
381
395
  {
382
396
  id: "sentiment",
383
397
  displayName: "Sentiment Analysis",
@@ -482,6 +496,9 @@ export const GUARDRAILS_FIELD_TO_DETECTORS = {
482
496
  "loop_count": ["loop_detector"],
483
497
  "loop_detected": ["loop_detector"],
484
498
  "loop_tool": ["loop_detector"],
499
+ "malicious_package_detected": ["malicious_package"],
500
+ "malicious_package_score": ["malicious_package"],
501
+ "malicious_packages": ["malicious_package"],
485
502
  "mcp_config_risk": ["mcp_risk"],
486
503
  "mcp_risk_score": ["mcp_risk"],
487
504
  "mcp_risk_type": ["mcp_risk"],
@@ -492,6 +509,9 @@ export const GUARDRAILS_FIELD_TO_DETECTORS = {
492
509
  "mip_label_name": ["file_metadata"],
493
510
  "multi_turn_detection": ["deepcontext"],
494
511
  "non_ascii_score": ["security"],
512
+ "package_check_status": ["malicious_package"],
513
+ "package_install_detected": ["malicious_package"],
514
+ "packages_checked": ["malicious_package"],
495
515
  "path_traversal_detected": ["path_traversal"],
496
516
  "path_traversal_severity": ["path_traversal"],
497
517
  "path_traversal_type": ["path_traversal"],
@@ -3584,6 +3584,12 @@ export const GUARDRAILS_CONTEXT = {
3584
3584
  { "key": "cross_origin_detected", "type": "boolean", "required": false, "description": "Whether cross-origin escalation patterns were detected (tool calls or references crossing trust boundaries)" },
3585
3585
  { "key": "cross_origin_type", "type": "string", "required": false, "description": "Type of cross-origin escalation: \'cross_origin_tool\', \'cross_origin_server\', or \'none\'" },
3586
3586
  { "key": "cross_origin_score", "type": "number", "required": false, "description": "Risk score for cross-origin escalation (0-100). Higher scores indicate more suspicious cross-boundary activity" },
3587
+ { "key": "package_install_detected", "type": "boolean", "required": false, "description": "Whether the event contains a recognized package install/download command (pip, npm, yarn, pnpm, bun, uv, gem, cargo, go, composer)" },
3588
+ { "key": "packages_checked", "type": "number", "required": false, "description": "Number of unique packages checked against the osv.dev database for this event" },
3589
+ { "key": "malicious_package_detected", "type": "boolean", "required": false, "description": "Whether any referenced package has a known-malicious OSV advisory (OpenSSF MAL- ID). Use to block supply-chain attacks at install time" },
3590
+ { "key": "malicious_package_score", "type": "number", "required": false, "description": "100 when a malicious package was detected, 0 otherwise" },
3591
+ { "key": "malicious_packages", "type": "array", "required": false, "description": "Malicious packages as ecosystem/name[@version] strings (e.g. \'PyPI/evil-pkg@1.0.0\')" },
3592
+ { "key": "package_check_status", "type": "string", "required": false, "description": "Set to \'degraded\' when the osv.dev lookup failed and packages could not be verified (fail-open). Combine with package_install_detected to fail closed" },
3587
3593
  { "key": "encoded_content_detected", "type": "boolean", "required": false, "description": "Whether encoded content was detected (base64, hex, unicode, URL encoding) that may hide malicious payloads" },
3588
3594
  { "key": "encoded_types", "type": "array", "required": false, "description": "Array of encoding types detected (e.g., [\'base64\', \'hex\', \'unicode\', \'url\']). Use .contains() to check for specific encoding types" },
3589
3595
  { "key": "encoded_count", "type": "number", "required": false, "description": "Number of encoded segments found in the content" },
@@ -3700,6 +3706,12 @@ export const GUARDRAILS_CONTEXT = {
3700
3706
  { "key": "cross_origin_detected", "type": "boolean", "required": false, "description": "Whether cross-origin escalation patterns were detected in tool calls crossing trust boundaries" },
3701
3707
  { "key": "cross_origin_type", "type": "string", "required": false, "description": "Type of cross-origin escalation detected in tool call" },
3702
3708
  { "key": "cross_origin_score", "type": "number", "required": false, "description": "Risk score for cross-origin escalation in tool calls (0-100)" },
3709
+ { "key": "package_install_detected", "type": "boolean", "required": false, "description": "Whether the event contains a recognized package install/download command (pip, npm, yarn, pnpm, bun, uv, gem, cargo, go, composer)" },
3710
+ { "key": "packages_checked", "type": "number", "required": false, "description": "Number of unique packages checked against the osv.dev database for this event" },
3711
+ { "key": "malicious_package_detected", "type": "boolean", "required": false, "description": "Whether any referenced package has a known-malicious OSV advisory (OpenSSF MAL- ID). Use to block supply-chain attacks at install time" },
3712
+ { "key": "malicious_package_score", "type": "number", "required": false, "description": "100 when a malicious package was detected, 0 otherwise" },
3713
+ { "key": "malicious_packages", "type": "array", "required": false, "description": "Malicious packages as ecosystem/name[@version] strings (e.g. \'PyPI/evil-pkg@1.0.0\')" },
3714
+ { "key": "package_check_status", "type": "string", "required": false, "description": "Set to \'degraded\' when the osv.dev lookup failed and packages could not be verified (fail-open). Combine with package_install_detected to fail closed" },
3703
3715
  { "key": "encoded_content_detected", "type": "boolean", "required": false, "description": "Whether encoded content was detected in tool arguments (base64, hex, unicode encoding hiding payloads)" },
3704
3716
  { "key": "encoded_types", "type": "array", "required": false, "description": "Array of encoding types detected in tool arguments (e.g., [\'base64\', \'hex\'])" },
3705
3717
  { "key": "encoded_count", "type": "number", "required": false, "description": "Number of encoded segments found in tool arguments" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@highflame/policy",
3
- "version": "2.2.11",
3
+ "version": "2.2.23",
4
4
  "engines": {
5
5
  "node": ">=18"
6
6
  },
@@ -1,21 +0,0 @@
1
- // =============================================================================
2
- // LLM Default Allow
3
- // =============================================================================
4
- // Permits all LLM prompt processing by default. Deploy alongside threat-specific
5
- // forbid policies to create a "default allow, block on threat" posture for LLM
6
- // chat completions.
7
- //
8
- // Category: organization
9
- // Namespace: AIGateway
10
- // =============================================================================
11
-
12
- @id("organization.permit-llm-default")
13
- @name("Permit LLM proxy calls")
14
- @description("Permits all process_prompt actions for the LLM proxy.")
15
- @severity("low")
16
- @tags("category:organization,surface:process-prompt,posture:permit-default")
17
- permit (
18
- principal,
19
- action == AIGateway::Action::"process_prompt",
20
- resource
21
- );