@highflame/policy 2.2.22 → 2.2.24

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.
@@ -372,6 +372,66 @@
372
372
  "type": "boolean",
373
373
  "required": false,
374
374
  "description": "Whether the TPM limit has been exceeded. Use this to enforce token rate limits via Cedar policy"
375
+ },
376
+ {
377
+ "key": "package_install_detected",
378
+ "type": "boolean",
379
+ "required": false,
380
+ "description": "Whether the tool-call arguments contain a recognized package install command (pip, npm, cargo, go get, etc.)"
381
+ },
382
+ {
383
+ "key": "packages_checked",
384
+ "type": "number",
385
+ "required": false,
386
+ "description": "Number of unique packages checked against osv.dev for this tool call"
387
+ },
388
+ {
389
+ "key": "malicious_package_detected",
390
+ "type": "boolean",
391
+ "required": false,
392
+ "description": "Whether any referenced package has a known-malicious (MAL-) OSV advisory. Use to block supply-chain attacks at install time"
393
+ },
394
+ {
395
+ "key": "malicious_package_score",
396
+ "type": "number",
397
+ "required": false,
398
+ "description": "100 when a malicious package was detected, 0 otherwise"
399
+ },
400
+ {
401
+ "key": "malicious_packages",
402
+ "type": "array",
403
+ "required": false,
404
+ "description": "Malicious packages as ecosystem/name[@version] strings (e.g. 'PyPI/evil-pkg@1.0.0')"
405
+ },
406
+ {
407
+ "key": "package_names",
408
+ "type": "array",
409
+ "required": false,
410
+ "description": "Names of all packages parsed from the install command (without ecosystem prefix). Available even when the osv.dev lookup fails."
411
+ },
412
+ {
413
+ "key": "package_ecosystems",
414
+ "type": "array",
415
+ "required": false,
416
+ "description": "Unique package ecosystems seen in this tool call, e.g. ['PyPI', 'npm']. Useful for policies that restrict which ecosystems are permitted."
417
+ },
418
+ {
419
+ "key": "package_advisory_count",
420
+ "type": "number",
421
+ "required": false,
422
+ "description": "Total non-malicious OSV advisories (GHSA- / CVE-) found across all checked packages. Excludes MAL- entries counted in malicious_package_detected."
423
+ },
424
+ {
425
+ "key": "package_risk_score",
426
+ "type": "number",
427
+ "required": false,
428
+ "description": "Graduated supply-chain risk score (0-100). 100 when any malicious package is found; proportional to advisory count for advisory-only packages; 0 when all packages are clean."
429
+ },
430
+ {
431
+ "key": "package_check_status",
432
+ "type": "string",
433
+ "required": false,
434
+ "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."
375
435
  }
376
436
  ]
377
437
  },
@@ -618,6 +678,66 @@
618
678
  "type": "boolean",
619
679
  "required": false,
620
680
  "description": "Whether the TPM limit has been exceeded. Use this to enforce token rate limits via Cedar policy"
681
+ },
682
+ {
683
+ "key": "package_install_detected",
684
+ "type": "boolean",
685
+ "required": false,
686
+ "description": "Whether the server-connect arguments contain a recognized package install command"
687
+ },
688
+ {
689
+ "key": "packages_checked",
690
+ "type": "number",
691
+ "required": false,
692
+ "description": "Number of unique packages checked against osv.dev for this connection event"
693
+ },
694
+ {
695
+ "key": "malicious_package_detected",
696
+ "type": "boolean",
697
+ "required": false,
698
+ "description": "Whether any referenced package has a known-malicious (MAL-) OSV advisory"
699
+ },
700
+ {
701
+ "key": "malicious_package_score",
702
+ "type": "number",
703
+ "required": false,
704
+ "description": "100 when a malicious package was detected, 0 otherwise"
705
+ },
706
+ {
707
+ "key": "malicious_packages",
708
+ "type": "array",
709
+ "required": false,
710
+ "description": "Malicious packages as ecosystem/name[@version] strings"
711
+ },
712
+ {
713
+ "key": "package_names",
714
+ "type": "array",
715
+ "required": false,
716
+ "description": "Names of all packages parsed from install commands (without ecosystem prefix)"
717
+ },
718
+ {
719
+ "key": "package_ecosystems",
720
+ "type": "array",
721
+ "required": false,
722
+ "description": "Unique package ecosystems seen in this connection event"
723
+ },
724
+ {
725
+ "key": "package_advisory_count",
726
+ "type": "number",
727
+ "required": false,
728
+ "description": "Total non-malicious OSV advisories found across all checked packages"
729
+ },
730
+ {
731
+ "key": "package_risk_score",
732
+ "type": "number",
733
+ "required": false,
734
+ "description": "Graduated supply-chain risk score (0-100)"
735
+ },
736
+ {
737
+ "key": "package_check_status",
738
+ "type": "string",
739
+ "required": false,
740
+ "description": "Set to 'degraded' when the osv.dev lookup failed (fail-open)"
621
741
  }
622
742
  ]
623
743
  },
@@ -283,6 +283,66 @@
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_names",
318
+ "type": "array",
319
+ "required": false,
320
+ "description": "Names of all packages parsed from the install command (without ecosystem prefix), e.g. ['requests', 'left-pad']. Available even when the osv.dev lookup fails."
321
+ },
322
+ {
323
+ "key": "package_ecosystems",
324
+ "type": "array",
325
+ "required": false,
326
+ "description": "Unique package ecosystems seen in this event, e.g. ['PyPI', 'npm']. Useful for policy rules that restrict which ecosystems are permitted."
327
+ },
328
+ {
329
+ "key": "package_advisory_count",
330
+ "type": "number",
331
+ "required": false,
332
+ "description": "Total number of non-malicious OSV advisories (GHSA- / CVE- IDs) found across all checked packages. Excludes MAL- entries counted in malicious_package_detected."
333
+ },
334
+ {
335
+ "key": "package_risk_score",
336
+ "type": "number",
337
+ "required": false,
338
+ "description": "Graduated supply-chain risk score (0-100). 100 when any malicious package is found; proportional to advisory_count for advisory-only packages; 0 when all packages are clean."
339
+ },
340
+ {
341
+ "key": "package_check_status",
342
+ "type": "string",
343
+ "required": false,
344
+ "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"
345
+ },
286
346
  {
287
347
  "key": "encoded_content_detected",
288
348
  "type": "boolean",
@@ -949,6 +1009,66 @@
949
1009
  "required": false,
950
1010
  "description": "Risk score for cross-origin escalation in tool calls (0-100)"
951
1011
  },
1012
+ {
1013
+ "key": "package_install_detected",
1014
+ "type": "boolean",
1015
+ "required": false,
1016
+ "description": "Whether the event contains a recognized package install/download command (pip, npm, yarn, pnpm, bun, uv, gem, cargo, go, composer)"
1017
+ },
1018
+ {
1019
+ "key": "packages_checked",
1020
+ "type": "number",
1021
+ "required": false,
1022
+ "description": "Number of unique packages checked against the osv.dev database for this event"
1023
+ },
1024
+ {
1025
+ "key": "malicious_package_detected",
1026
+ "type": "boolean",
1027
+ "required": false,
1028
+ "description": "Whether any referenced package has a known-malicious OSV advisory (OpenSSF MAL- ID). Use to block supply-chain attacks at install time"
1029
+ },
1030
+ {
1031
+ "key": "malicious_package_score",
1032
+ "type": "number",
1033
+ "required": false,
1034
+ "description": "100 when a malicious package was detected, 0 otherwise"
1035
+ },
1036
+ {
1037
+ "key": "malicious_packages",
1038
+ "type": "array",
1039
+ "required": false,
1040
+ "description": "Malicious packages as ecosystem/name[@version] strings (e.g. 'PyPI/evil-pkg@1.0.0')"
1041
+ },
1042
+ {
1043
+ "key": "package_names",
1044
+ "type": "array",
1045
+ "required": false,
1046
+ "description": "Names of all packages parsed from the install command (without ecosystem prefix), e.g. ['requests', 'left-pad']. Available even when the osv.dev lookup fails."
1047
+ },
1048
+ {
1049
+ "key": "package_ecosystems",
1050
+ "type": "array",
1051
+ "required": false,
1052
+ "description": "Unique package ecosystems seen in this event, e.g. ['PyPI', 'npm']. Useful for policy rules that restrict which ecosystems are permitted."
1053
+ },
1054
+ {
1055
+ "key": "package_advisory_count",
1056
+ "type": "number",
1057
+ "required": false,
1058
+ "description": "Total number of non-malicious OSV advisories (GHSA- / CVE- IDs) found across all checked packages. Excludes MAL- entries counted in malicious_package_detected."
1059
+ },
1060
+ {
1061
+ "key": "package_risk_score",
1062
+ "type": "number",
1063
+ "required": false,
1064
+ "description": "Graduated supply-chain risk score (0-100). 100 when any malicious package is found; proportional to advisory_count for advisory-only packages; 0 when all packages are clean."
1065
+ },
1066
+ {
1067
+ "key": "package_check_status",
1068
+ "type": "string",
1069
+ "required": false,
1070
+ "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"
1071
+ },
952
1072
  {
953
1073
  "key": "encoded_content_detected",
954
1074
  "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",
@@ -17,6 +17,9 @@ export declare const AiGatewayContextKey: {
17
17
  readonly JailbreakScore: "jailbreak_score";
18
18
  readonly LoopCount: "loop_count";
19
19
  readonly LoopDetected: "loop_detected";
20
+ readonly MaliciousPackageDetected: "malicious_package_detected";
21
+ readonly MaliciousPackageScore: "malicious_package_score";
22
+ readonly MaliciousPackages: "malicious_packages";
20
23
  readonly MaxThreatSeverity: "max_threat_severity";
21
24
  readonly McpConfigRisk: "mcp_config_risk";
22
25
  readonly McpRiskScore: "mcp_risk_score";
@@ -25,6 +28,13 @@ export declare const AiGatewayContextKey: {
25
28
  readonly McpTool: "mcp_tool";
26
29
  readonly ModelName: "model_name";
27
30
  readonly ModelProvider: "model_provider";
31
+ readonly PackageAdvisoryCount: "package_advisory_count";
32
+ readonly PackageCheckStatus: "package_check_status";
33
+ readonly PackageEcosystems: "package_ecosystems";
34
+ readonly PackageInstallDetected: "package_install_detected";
35
+ readonly PackageNames: "package_names";
36
+ readonly PackageRiskScore: "package_risk_score";
37
+ readonly PackagesChecked: "packages_checked";
28
38
  readonly PatternType: "pattern_type";
29
39
  readonly PiiCount: "pii_count";
30
40
  readonly PiiDetected: "pii_detected";
@@ -76,4 +86,4 @@ export type AiGatewayContextKey = (typeof AiGatewayContextKey)[keyof typeof AiGa
76
86
  * The full set of authorable context attribute keys for AiGateway.
77
87
  * Iterate this to enumerate the authorable surface (cockpit, conformance).
78
88
  */
79
- export declare const AiGatewayContextKeys: readonly ["content", "crime_score", "detected_threats", "hate_speech_score", "highest_severity", "indirect_injection_score", "injection_score", "invisible_chars_detected", "invisible_chars_score", "jailbreak_score", "loop_count", "loop_detected", "max_threat_severity", "mcp_config_risk", "mcp_risk_score", "mcp_server", "mcp_server_verified", "mcp_tool", "model_name", "model_provider", "pattern_type", "pii_count", "pii_detected", "pii_score", "pii_types", "privilege_scope", "profanity_score", "role", "rpm_exceeded", "rpm_remaining_pct", "rug_pull_detected", "rug_pull_score", "secret_count", "secret_types", "secrets_detected", "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_pii_detected", "session_pii_types", "session_secret_types", "session_secrets_detected", "session_threat_turns", "sexual_score", "suspicious_pattern", "threat_categories", "threat_count", "tool_category", "tool_is_builtin", "tool_is_sensitive", "tool_name", "tool_operation_classes", "tool_poisoning_detected", "tool_poisoning_score", "tool_risk_score", "tpm_exceeded", "tpm_remaining_pct", "violence_score", "weapons_score"];
89
+ export declare const AiGatewayContextKeys: readonly ["content", "crime_score", "detected_threats", "hate_speech_score", "highest_severity", "indirect_injection_score", "injection_score", "invisible_chars_detected", "invisible_chars_score", "jailbreak_score", "loop_count", "loop_detected", "malicious_package_detected", "malicious_package_score", "malicious_packages", "max_threat_severity", "mcp_config_risk", "mcp_risk_score", "mcp_server", "mcp_server_verified", "mcp_tool", "model_name", "model_provider", "package_advisory_count", "package_check_status", "package_ecosystems", "package_install_detected", "package_names", "package_risk_score", "packages_checked", "pattern_type", "pii_count", "pii_detected", "pii_score", "pii_types", "privilege_scope", "profanity_score", "role", "rpm_exceeded", "rpm_remaining_pct", "rug_pull_detected", "rug_pull_score", "secret_count", "secret_types", "secrets_detected", "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_pii_detected", "session_pii_types", "session_secret_types", "session_secrets_detected", "session_threat_turns", "sexual_score", "suspicious_pattern", "threat_categories", "threat_count", "tool_category", "tool_is_builtin", "tool_is_sensitive", "tool_name", "tool_operation_classes", "tool_poisoning_detected", "tool_poisoning_score", "tool_risk_score", "tpm_exceeded", "tpm_remaining_pct", "violence_score", "weapons_score"];
@@ -19,6 +19,9 @@ export const AiGatewayContextKey = {
19
19
  JailbreakScore: 'jailbreak_score',
20
20
  LoopCount: 'loop_count',
21
21
  LoopDetected: 'loop_detected',
22
+ MaliciousPackageDetected: 'malicious_package_detected',
23
+ MaliciousPackageScore: 'malicious_package_score',
24
+ MaliciousPackages: 'malicious_packages',
22
25
  MaxThreatSeverity: 'max_threat_severity',
23
26
  McpConfigRisk: 'mcp_config_risk',
24
27
  McpRiskScore: 'mcp_risk_score',
@@ -27,6 +30,13 @@ export const AiGatewayContextKey = {
27
30
  McpTool: 'mcp_tool',
28
31
  ModelName: 'model_name',
29
32
  ModelProvider: 'model_provider',
33
+ PackageAdvisoryCount: 'package_advisory_count',
34
+ PackageCheckStatus: 'package_check_status',
35
+ PackageEcosystems: 'package_ecosystems',
36
+ PackageInstallDetected: 'package_install_detected',
37
+ PackageNames: 'package_names',
38
+ PackageRiskScore: 'package_risk_score',
39
+ PackagesChecked: 'packages_checked',
30
40
  PatternType: 'pattern_type',
31
41
  PiiCount: 'pii_count',
32
42
  PiiDetected: 'pii_detected',
@@ -90,6 +100,9 @@ export const AiGatewayContextKeys = [
90
100
  AiGatewayContextKey.JailbreakScore,
91
101
  AiGatewayContextKey.LoopCount,
92
102
  AiGatewayContextKey.LoopDetected,
103
+ AiGatewayContextKey.MaliciousPackageDetected,
104
+ AiGatewayContextKey.MaliciousPackageScore,
105
+ AiGatewayContextKey.MaliciousPackages,
93
106
  AiGatewayContextKey.MaxThreatSeverity,
94
107
  AiGatewayContextKey.McpConfigRisk,
95
108
  AiGatewayContextKey.McpRiskScore,
@@ -98,6 +111,13 @@ export const AiGatewayContextKeys = [
98
111
  AiGatewayContextKey.McpTool,
99
112
  AiGatewayContextKey.ModelName,
100
113
  AiGatewayContextKey.ModelProvider,
114
+ AiGatewayContextKey.PackageAdvisoryCount,
115
+ AiGatewayContextKey.PackageCheckStatus,
116
+ AiGatewayContextKey.PackageEcosystems,
117
+ AiGatewayContextKey.PackageInstallDetected,
118
+ AiGatewayContextKey.PackageNames,
119
+ AiGatewayContextKey.PackageRiskScore,
120
+ AiGatewayContextKey.PackagesChecked,
101
121
  AiGatewayContextKey.PatternType,
102
122
  AiGatewayContextKey.PiiCount,
103
123
  AiGatewayContextKey.PiiDetected,
@@ -168,6 +168,20 @@ export const AI_GATEWAY_DETECTORS = [
168
168
  defendsAgainst: ["mcp_rug_pull"],
169
169
  exampleAttacks: [],
170
170
  },
171
+ {
172
+ id: "malicious_package",
173
+ displayName: "Malicious Package (OSV)",
174
+ category: "tool_safety",
175
+ stability: "preview",
176
+ tier: "slow",
177
+ inhouse: false,
178
+ model: null,
179
+ latencyP50Ms: 250,
180
+ 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_names", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Names of all packages parsed from install commands (without ecosystem prefix), e.g. 'requests', 'left-pad'. Available even when the osv.dev lookup fails." }, { name: "package_ecosystems", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Unique package ecosystems seen in this event, e.g. 'PyPI', 'npm'. Useful for policies that restrict which ecosystems are permitted." }, { name: "package_advisory_count", type: "Long", modifiable: false, semantic: "count", description: "Total non-malicious OSV advisories (GHSA- / CVE- IDs) found across all checked packages. Excludes MAL- entries counted in malicious_package_detected." }, { name: "package_risk_score", type: "Long", modifiable: false, semantic: "severity_0_100", description: "Graduated supply-chain risk score (0-100). 100 when any malicious package is found; proportional to advisory_count for advisory-only packages; 0 when all packages are clean." }, { 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." }],
181
+ supportedModes: ["enforce", "monitor", "alert"],
182
+ defendsAgainst: ["supply_chain"],
183
+ exampleAttacks: [{ title: "Typosquatted PyPI install via MCP bash tool", vulnerabilityId: "supply_chain", snippet: "pip install reqeusts", expectedSignal: {} }],
184
+ },
171
185
  ];
172
186
  // Semantic field → contributing detector ids (producesAttrs + normalizationAliases,
173
187
  // resolved at codegen). Used by the client field→detector resolver — no Shield round-trip.
@@ -181,11 +195,21 @@ export const AI_GATEWAY_FIELD_TO_DETECTORS = {
181
195
  "jailbreak_score": ["injection"],
182
196
  "loop_count": ["loop_detector"],
183
197
  "loop_detected": ["loop_detector"],
198
+ "malicious_package_detected": ["malicious_package"],
199
+ "malicious_package_score": ["malicious_package"],
200
+ "malicious_packages": ["malicious_package"],
184
201
  "mcp_config_risk": ["mcp_risk"],
185
202
  "mcp_risk_score": ["mcp_risk"],
186
203
  "mcp_server": ["mcp_risk"],
187
204
  "mcp_server_verified": ["mcp_risk"],
188
205
  "mcp_tool": ["mcp_risk"],
206
+ "package_advisory_count": ["malicious_package"],
207
+ "package_check_status": ["malicious_package"],
208
+ "package_ecosystems": ["malicious_package"],
209
+ "package_install_detected": ["malicious_package"],
210
+ "package_names": ["malicious_package"],
211
+ "package_risk_score": ["malicious_package"],
212
+ "packages_checked": ["malicious_package"],
189
213
  "pattern_type": ["action_pattern"],
190
214
  "pii_count": ["pii"],
191
215
  "pii_detected": ["pii"],
@@ -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,13 @@ 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 PackageAdvisoryCount: "package_advisory_count";
75
+ readonly PackageCheckStatus: "package_check_status";
76
+ readonly PackageEcosystems: "package_ecosystems";
77
+ readonly PackageInstallDetected: "package_install_detected";
78
+ readonly PackageNames: "package_names";
79
+ readonly PackageRiskScore: "package_risk_score";
80
+ readonly PackagesChecked: "packages_checked";
71
81
  readonly ParamTypeViolation: "param_type_violation";
72
82
  readonly ParamTypeViolations: "param_type_violations";
73
83
  readonly Path: "path";
@@ -137,4 +147,4 @@ export type GuardrailsContextKey = (typeof GuardrailsContextKey)[keyof typeof Gu
137
147
  * The full set of authorable context attribute keys for Guardrails.
138
148
  * Iterate this to enumerate the authorable surface (cockpit, conformance).
139
149
  */
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"];
150
+ 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_advisory_count", "package_check_status", "package_ecosystems", "package_install_detected", "package_names", "package_risk_score", "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,13 @@ export const GuardrailsContextKey = {
70
73
  McpServerVerified: 'mcp_server_verified',
71
74
  McpTool: 'mcp_tool',
72
75
  MultiTurnDetection: 'multi_turn_detection',
76
+ PackageAdvisoryCount: 'package_advisory_count',
77
+ PackageCheckStatus: 'package_check_status',
78
+ PackageEcosystems: 'package_ecosystems',
79
+ PackageInstallDetected: 'package_install_detected',
80
+ PackageNames: 'package_names',
81
+ PackageRiskScore: 'package_risk_score',
82
+ PackagesChecked: 'packages_checked',
73
83
  ParamTypeViolation: 'param_type_violation',
74
84
  ParamTypeViolations: 'param_type_violations',
75
85
  Path: 'path',
@@ -195,6 +205,9 @@ export const GuardrailsContextKeys = [
195
205
  GuardrailsContextKey.LoopCount,
196
206
  GuardrailsContextKey.LoopDetected,
197
207
  GuardrailsContextKey.LoopTool,
208
+ GuardrailsContextKey.MaliciousPackageDetected,
209
+ GuardrailsContextKey.MaliciousPackageScore,
210
+ GuardrailsContextKey.MaliciousPackages,
198
211
  GuardrailsContextKey.McpConfigRisk,
199
212
  GuardrailsContextKey.McpRiskScore,
200
213
  GuardrailsContextKey.McpRiskType,
@@ -202,6 +215,13 @@ export const GuardrailsContextKeys = [
202
215
  GuardrailsContextKey.McpServerVerified,
203
216
  GuardrailsContextKey.McpTool,
204
217
  GuardrailsContextKey.MultiTurnDetection,
218
+ GuardrailsContextKey.PackageAdvisoryCount,
219
+ GuardrailsContextKey.PackageCheckStatus,
220
+ GuardrailsContextKey.PackageEcosystems,
221
+ GuardrailsContextKey.PackageInstallDetected,
222
+ GuardrailsContextKey.PackageNames,
223
+ GuardrailsContextKey.PackageRiskScore,
224
+ GuardrailsContextKey.PackagesChecked,
205
225
  GuardrailsContextKey.ParamTypeViolation,
206
226
  GuardrailsContextKey.ParamTypeViolations,
207
227
  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_names", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Names of all packages parsed from install commands (without ecosystem prefix), e.g. 'requests', 'left-pad'. Available even when the osv.dev lookup fails." }, { name: "package_ecosystems", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Unique package ecosystems seen in this event, e.g. 'PyPI', 'npm'. Useful for policies that restrict which ecosystems are permitted." }, { name: "package_advisory_count", type: "Long", modifiable: false, semantic: "count", description: "Total non-malicious OSV advisories (GHSA- / CVE- IDs) found across all checked packages. Excludes MAL- entries counted in malicious_package_detected." }, { name: "package_risk_score", type: "Long", modifiable: false, semantic: "severity_0_100", description: "Graduated supply-chain risk score (0-100). 100 when any malicious package is found; proportional to advisory_count for advisory-only packages; 0 when all packages are clean." }, { 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,13 @@ 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_advisory_count": ["malicious_package"],
513
+ "package_check_status": ["malicious_package"],
514
+ "package_ecosystems": ["malicious_package"],
515
+ "package_install_detected": ["malicious_package"],
516
+ "package_names": ["malicious_package"],
517
+ "package_risk_score": ["malicious_package"],
518
+ "packages_checked": ["malicious_package"],
495
519
  "path_traversal_detected": ["path_traversal"],
496
520
  "path_traversal_severity": ["path_traversal"],
497
521
  "path_traversal_type": ["path_traversal"],
@@ -3346,7 +3346,17 @@ export const AI_GATEWAY_CONTEXT = {
3346
3346
  { "key": "rpm_remaining_pct", "type": "number", "required": false, "description": "Remaining RPM (requests per minute) as percentage (0-100). Gateway-metered, Shield-decided (ADR 0014)" },
3347
3347
  { "key": "rpm_exceeded", "type": "boolean", "required": false, "description": "Whether the RPM limit has been exceeded. Use this to enforce rate limits via Cedar policy" },
3348
3348
  { "key": "tpm_remaining_pct", "type": "number", "required": false, "description": "Remaining TPM (tokens per minute) as percentage (0-100). Gateway-metered, Shield-decided (ADR 0014)" },
3349
- { "key": "tpm_exceeded", "type": "boolean", "required": false, "description": "Whether the TPM limit has been exceeded. Use this to enforce token rate limits via Cedar policy" }
3349
+ { "key": "tpm_exceeded", "type": "boolean", "required": false, "description": "Whether the TPM limit has been exceeded. Use this to enforce token rate limits via Cedar policy" },
3350
+ { "key": "package_install_detected", "type": "boolean", "required": false, "description": "Whether the tool-call arguments contain a recognized package install command (pip, npm, cargo, go get, etc.)" },
3351
+ { "key": "packages_checked", "type": "number", "required": false, "description": "Number of unique packages checked against osv.dev for this tool call" },
3352
+ { "key": "malicious_package_detected", "type": "boolean", "required": false, "description": "Whether any referenced package has a known-malicious (MAL-) OSV advisory. Use to block supply-chain attacks at install time" },
3353
+ { "key": "malicious_package_score", "type": "number", "required": false, "description": "100 when a malicious package was detected, 0 otherwise" },
3354
+ { "key": "malicious_packages", "type": "array", "required": false, "description": "Malicious packages as ecosystem/name[@version] strings (e.g. \'PyPI/evil-pkg@1.0.0\')" },
3355
+ { "key": "package_names", "type": "array", "required": false, "description": "Names of all packages parsed from the install command (without ecosystem prefix). Available even when the osv.dev lookup fails." },
3356
+ { "key": "package_ecosystems", "type": "array", "required": false, "description": "Unique package ecosystems seen in this tool call, e.g. [\'PyPI\', \'npm\']. Useful for policies that restrict which ecosystems are permitted." },
3357
+ { "key": "package_advisory_count", "type": "number", "required": false, "description": "Total non-malicious OSV advisories (GHSA- / CVE-) found across all checked packages. Excludes MAL- entries counted in malicious_package_detected." },
3358
+ { "key": "package_risk_score", "type": "number", "required": false, "description": "Graduated supply-chain risk score (0-100). 100 when any malicious package is found; proportional to advisory count for advisory-only packages; 0 when all packages are clean." },
3359
+ { "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." }
3350
3360
  ]
3351
3361
  },
3352
3362
  {
@@ -3392,7 +3402,17 @@ export const AI_GATEWAY_CONTEXT = {
3392
3402
  { "key": "rpm_remaining_pct", "type": "number", "required": false, "description": "Remaining RPM (requests per minute) as percentage (0-100). Gateway-metered, Shield-decided (ADR 0014)" },
3393
3403
  { "key": "rpm_exceeded", "type": "boolean", "required": false, "description": "Whether the RPM limit has been exceeded. Use this to enforce rate limits via Cedar policy" },
3394
3404
  { "key": "tpm_remaining_pct", "type": "number", "required": false, "description": "Remaining TPM (tokens per minute) as percentage (0-100). Gateway-metered, Shield-decided (ADR 0014)" },
3395
- { "key": "tpm_exceeded", "type": "boolean", "required": false, "description": "Whether the TPM limit has been exceeded. Use this to enforce token rate limits via Cedar policy" }
3405
+ { "key": "tpm_exceeded", "type": "boolean", "required": false, "description": "Whether the TPM limit has been exceeded. Use this to enforce token rate limits via Cedar policy" },
3406
+ { "key": "package_install_detected", "type": "boolean", "required": false, "description": "Whether the server-connect arguments contain a recognized package install command" },
3407
+ { "key": "packages_checked", "type": "number", "required": false, "description": "Number of unique packages checked against osv.dev for this connection event" },
3408
+ { "key": "malicious_package_detected", "type": "boolean", "required": false, "description": "Whether any referenced package has a known-malicious (MAL-) OSV advisory" },
3409
+ { "key": "malicious_package_score", "type": "number", "required": false, "description": "100 when a malicious package was detected, 0 otherwise" },
3410
+ { "key": "malicious_packages", "type": "array", "required": false, "description": "Malicious packages as ecosystem/name[@version] strings" },
3411
+ { "key": "package_names", "type": "array", "required": false, "description": "Names of all packages parsed from install commands (without ecosystem prefix)" },
3412
+ { "key": "package_ecosystems", "type": "array", "required": false, "description": "Unique package ecosystems seen in this connection event" },
3413
+ { "key": "package_advisory_count", "type": "number", "required": false, "description": "Total non-malicious OSV advisories found across all checked packages" },
3414
+ { "key": "package_risk_score", "type": "number", "required": false, "description": "Graduated supply-chain risk score (0-100)" },
3415
+ { "key": "package_check_status", "type": "string", "required": false, "description": "Set to \'degraded\' when the osv.dev lookup failed (fail-open)" }
3396
3416
  ]
3397
3417
  },
3398
3418
  {
@@ -3584,6 +3604,16 @@ export const GUARDRAILS_CONTEXT = {
3584
3604
  { "key": "cross_origin_detected", "type": "boolean", "required": false, "description": "Whether cross-origin escalation patterns were detected (tool calls or references crossing trust boundaries)" },
3585
3605
  { "key": "cross_origin_type", "type": "string", "required": false, "description": "Type of cross-origin escalation: \'cross_origin_tool\', \'cross_origin_server\', or \'none\'" },
3586
3606
  { "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" },
3607
+ { "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)" },
3608
+ { "key": "packages_checked", "type": "number", "required": false, "description": "Number of unique packages checked against the osv.dev database for this event" },
3609
+ { "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" },
3610
+ { "key": "malicious_package_score", "type": "number", "required": false, "description": "100 when a malicious package was detected, 0 otherwise" },
3611
+ { "key": "malicious_packages", "type": "array", "required": false, "description": "Malicious packages as ecosystem/name[@version] strings (e.g. \'PyPI/evil-pkg@1.0.0\')" },
3612
+ { "key": "package_names", "type": "array", "required": false, "description": "Names of all packages parsed from the install command (without ecosystem prefix), e.g. [\'requests\', \'left-pad\']. Available even when the osv.dev lookup fails." },
3613
+ { "key": "package_ecosystems", "type": "array", "required": false, "description": "Unique package ecosystems seen in this event, e.g. [\'PyPI\', \'npm\']. Useful for policy rules that restrict which ecosystems are permitted." },
3614
+ { "key": "package_advisory_count", "type": "number", "required": false, "description": "Total number of non-malicious OSV advisories (GHSA- / CVE- IDs) found across all checked packages. Excludes MAL- entries counted in malicious_package_detected." },
3615
+ { "key": "package_risk_score", "type": "number", "required": false, "description": "Graduated supply-chain risk score (0-100). 100 when any malicious package is found; proportional to advisory_count for advisory-only packages; 0 when all packages are clean." },
3616
+ { "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
3617
  { "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
3618
  { "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
3619
  { "key": "encoded_count", "type": "number", "required": false, "description": "Number of encoded segments found in the content" },
@@ -3700,6 +3730,16 @@ export const GUARDRAILS_CONTEXT = {
3700
3730
  { "key": "cross_origin_detected", "type": "boolean", "required": false, "description": "Whether cross-origin escalation patterns were detected in tool calls crossing trust boundaries" },
3701
3731
  { "key": "cross_origin_type", "type": "string", "required": false, "description": "Type of cross-origin escalation detected in tool call" },
3702
3732
  { "key": "cross_origin_score", "type": "number", "required": false, "description": "Risk score for cross-origin escalation in tool calls (0-100)" },
3733
+ { "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)" },
3734
+ { "key": "packages_checked", "type": "number", "required": false, "description": "Number of unique packages checked against the osv.dev database for this event" },
3735
+ { "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" },
3736
+ { "key": "malicious_package_score", "type": "number", "required": false, "description": "100 when a malicious package was detected, 0 otherwise" },
3737
+ { "key": "malicious_packages", "type": "array", "required": false, "description": "Malicious packages as ecosystem/name[@version] strings (e.g. \'PyPI/evil-pkg@1.0.0\')" },
3738
+ { "key": "package_names", "type": "array", "required": false, "description": "Names of all packages parsed from the install command (without ecosystem prefix), e.g. [\'requests\', \'left-pad\']. Available even when the osv.dev lookup fails." },
3739
+ { "key": "package_ecosystems", "type": "array", "required": false, "description": "Unique package ecosystems seen in this event, e.g. [\'PyPI\', \'npm\']. Useful for policy rules that restrict which ecosystems are permitted." },
3740
+ { "key": "package_advisory_count", "type": "number", "required": false, "description": "Total number of non-malicious OSV advisories (GHSA- / CVE- IDs) found across all checked packages. Excludes MAL- entries counted in malicious_package_detected." },
3741
+ { "key": "package_risk_score", "type": "number", "required": false, "description": "Graduated supply-chain risk score (0-100). 100 when any malicious package is found; proportional to advisory_count for advisory-only packages; 0 when all packages are clean." },
3742
+ { "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
3743
  { "key": "encoded_content_detected", "type": "boolean", "required": false, "description": "Whether encoded content was detected in tool arguments (base64, hex, unicode encoding hiding payloads)" },
3704
3744
  { "key": "encoded_types", "type": "array", "required": false, "description": "Array of encoding types detected in tool arguments (e.g., [\'base64\', \'hex\'])" },
3705
3745
  { "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.22",
3
+ "version": "2.2.24",
4
4
  "engines": {
5
5
  "node": ">=18"
6
6
  },