@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.
- package/_schemas/ai_gateway/templates/templates.json +0 -13
- package/_schemas/guardrails/context.json +72 -0
- package/_schemas/guardrails/templates/defaults/malicious_package.cedar +59 -0
- package/_schemas/guardrails/templates/profiles/code_agent/supply_chain.cedar +24 -6
- package/_schemas/guardrails/templates/templates.json +15 -1
- package/dist/ai_gateway-defaults.gen.js +0 -44
- package/dist/guardrails-context.gen.d.ts +7 -1
- package/dist/guardrails-context.gen.js +12 -0
- package/dist/guardrails-defaults.gen.js +109 -8
- package/dist/guardrails-detectors.gen.js +20 -0
- package/dist/service-schemas.gen.js +12 -0
- package/package.json +1 -1
- package/_schemas/ai_gateway/templates/llm_default_allow.cedar +0 -21
|
@@ -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,
|
|
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:
|
|
9
|
-
// - indirect_injection_score:
|
|
10
|
-
// - tool_is_sensitive:
|
|
11
|
-
// - suspicious_pattern:
|
|
12
|
-
// - pattern_type:
|
|
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,
|
|
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,
|
|
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:
|
|
1602
|
-
// - indirect_injection_score:
|
|
1603
|
-
// - tool_is_sensitive:
|
|
1604
|
-
// - suspicious_pattern:
|
|
1605
|
-
// - pattern_type:
|
|
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,
|
|
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,
|
|
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,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
|
-
);
|