@highflame/policy 2.2.42 → 2.2.43

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.
@@ -0,0 +1,103 @@
1
+ // =============================================================================
2
+ // Session Risk Accumulation
3
+ // =============================================================================
4
+ // Blocks the privileged action a probing conversation is working toward. A
5
+ // patient attacker expects some turns to be refused; what they want is one
6
+ // tool call at the end — send the email, move the money, read the file. So
7
+ // the useful question at a tool call is not "is this call suspicious?" but
8
+ // "what has this conversation been doing up to now?"
9
+ //
10
+ // Shield accumulates that history on the session and projects it three ways,
11
+ // because attackers come in three shapes:
12
+ // - session_max_* — a high-water mark that never decays. "Did this session
13
+ // EVER cross a line?" Catches the attacker who probes hard, is refused,
14
+ // goes quiet, then calmly asks for the tool.
15
+ // - session_cumulative_risk_score — an uncapped running sum. "How much
16
+ // total pressure has this session applied?" Catches death by a thousand
17
+ // cuts, where no single turn is alarming.
18
+ // - session_threat_turns — a count of turns that tripped a detector. "Is
19
+ // this sustained, or a one-off?" Separates probing from a false positive.
20
+ //
21
+ // Requires a stable session_id on every request, prompts AND tool calls. The
22
+ // tool call must ride the same session as the conversation, or it reads 0.
23
+ //
24
+ // Detection layers:
25
+ // - session (aggregate over detection history, always available)
26
+ // - tool_validator (tool_is_sensitive, always available)
27
+ //
28
+ // Context keys consumed:
29
+ // - session_max_injection_score, session_max_jailbreak_score: Long (0-100)
30
+ // - session_cumulative_risk_score: Long — uncapped sum
31
+ // - session_threat_turns: Long — count
32
+ // - tool_is_sensitive: Bool
33
+ //
34
+ // Compliance:
35
+ // - OWASP LLM01, OWASP LLM06, OWASP ASI01, OWASP ASI04
36
+ //
37
+ // Category: agent-security
38
+ // Namespace: Guardrails
39
+ // =============================================================================
40
+
41
+ // ---------------------------------------------------------------------------
42
+ // Section 1: A session that ever crossed the line does not get to act
43
+ // The conversation is what scored high; the tool call is what gets stopped.
44
+ // ---------------------------------------------------------------------------
45
+
46
+ @id("agent-security.block-tool-after-injection-in-session")
47
+ @name("Block tools after an injection or jailbreak in the session")
48
+ @description("Blocks call_tool when session_max_injection_score >= 60 or session_max_jailbreak_score >= 60, because an earlier turn attempted injection or jailbreak.")
49
+ @severity("critical")
50
+ @tags("category:agent-security,threat:escalation,detection:aggregate,surface:call-tool,scope:multi-turn,owasp:llm01")
51
+ @reject_message("Tool execution blocked: an earlier turn in this session attempted prompt injection or jailbreak. Start a new session to use tools.")
52
+ forbid (
53
+ principal,
54
+ action == Guardrails::Action::"call_tool",
55
+ resource
56
+ )
57
+ when {
58
+ (context has session_max_injection_score && context.session_max_injection_score >= 60) ||
59
+ (context has session_max_jailbreak_score && context.session_max_jailbreak_score >= 60)
60
+ };
61
+
62
+ // ---------------------------------------------------------------------------
63
+ // Section 2: Accumulated pressure gates sensitive tools
64
+ // No single turn set a max, but the session as a whole kept pushing.
65
+ // ---------------------------------------------------------------------------
66
+
67
+ @id("agent-security.block-sensitive-tool-on-session-risk")
68
+ @name("Block sensitive tools once the session has accumulated risk")
69
+ @description("Blocks call_tool when session_cumulative_risk_score >= 151 and tool_is_sensitive is true.")
70
+ @severity("high")
71
+ @tags("category:agent-security,threat:escalation,detection:aggregate,surface:call-tool,scope:multi-turn,owasp:asi01")
72
+ @reject_message("Tool execution blocked: this session has accumulated significant risk across earlier turns. Sensitive tools are withheld for the remainder of the session.")
73
+ forbid (
74
+ principal,
75
+ action == Guardrails::Action::"call_tool",
76
+ resource
77
+ )
78
+ when {
79
+ context has session_cumulative_risk_score &&
80
+ context.session_cumulative_risk_score >= 151 &&
81
+ context has tool_is_sensitive && context.tool_is_sensitive == true
82
+ };
83
+
84
+ // ---------------------------------------------------------------------------
85
+ // Section 3: Sustained probing, independent of any single score
86
+ // Two is the smallest bar that separates repeated from one-off. Long-running
87
+ // agent sessions accumulate turns faster and warrant a higher bar.
88
+ // ---------------------------------------------------------------------------
89
+
90
+ @id("agent-security.block-tool-on-repeated-threat-turns")
91
+ @name("Block tool use in a session with repeated threat turns")
92
+ @description("Blocks call_tool when session_threat_turns >= 2, because more than one turn in this session tripped a detector.")
93
+ @severity("high")
94
+ @tags("category:agent-security,threat:escalation,detection:aggregate,surface:call-tool,scope:multi-turn,owasp:asi04")
95
+ @reject_message("Tool execution blocked: more than one turn in this session tripped a detector. This is sustained probing, not a one-off false positive.")
96
+ forbid (
97
+ principal,
98
+ action == Guardrails::Action::"call_tool",
99
+ resource
100
+ )
101
+ when {
102
+ context has session_threat_turns && context.session_threat_turns >= 2
103
+ };
@@ -599,6 +599,56 @@
599
599
  "surface:process-response",
600
600
  "detection:rule"
601
601
  ]
602
+ },
603
+ {
604
+ "id": "security.multi-turn-trajectory",
605
+ "name": "Multi-Turn Trajectory Escalation",
606
+ "description": "Block a conversation whose trajectory is an attack even when no single message is: fires on the gap between the multi-turn model and the single-turn classifier.",
607
+ "category": "security",
608
+ "file": "multi_turn_trajectory.cedar",
609
+ "severity": "critical",
610
+ "tags": [
611
+ "category:security",
612
+ "threat:injection",
613
+ "threat:jailbreak",
614
+ "detection:ml",
615
+ "scope:multi-turn",
616
+ "owasp:llm01",
617
+ "owasp:llm02"
618
+ ]
619
+ },
620
+ {
621
+ "id": "agent-security.session-risk-accumulation",
622
+ "name": "Session Risk Accumulation",
623
+ "description": "Block the privileged action a probing conversation is working toward, using the session's high-water mark, cumulative risk, and count of threat turns.",
624
+ "category": "agent-security",
625
+ "file": "session_risk_accumulation.cedar",
626
+ "severity": "critical",
627
+ "tags": [
628
+ "category:agent-security",
629
+ "threat:escalation",
630
+ "detection:aggregate",
631
+ "surface:call-tool",
632
+ "scope:multi-turn",
633
+ "owasp:asi01",
634
+ "owasp:asi04"
635
+ ]
636
+ },
637
+ {
638
+ "id": "agent-identity.dual-attribution",
639
+ "name": "Dual Attribution",
640
+ "description": "Block privileged agent actions that cannot be attributed to a human. Deploy in monitor mode first; a service key is unverified until the agent is adopted.",
641
+ "category": "agent-identity",
642
+ "file": "dual_attribution.cedar",
643
+ "severity": "critical",
644
+ "tags": [
645
+ "category:agent-identity",
646
+ "detection:rule",
647
+ "surface:call-tool",
648
+ "scope:per-agent",
649
+ "posture:deny-default",
650
+ "owasp:asi01"
651
+ ]
602
652
  }
603
653
  ]
604
654
  }
@@ -104,7 +104,6 @@ export declare const AgentOpsContextKey: {
104
104
  readonly PiiDetected: "pii_detected";
105
105
  readonly PiiScore: "pii_score";
106
106
  readonly PiiTypes: "pii_types";
107
- readonly Principal: "principal";
108
107
  readonly PrincipalClearances: "principal_clearances";
109
108
  readonly PrincipalCompartments: "principal_compartments";
110
109
  readonly PrivilegeScope: "privilege_scope";
@@ -174,4 +173,4 @@ export type AgentOpsContextKey = (typeof AgentOpsContextKey)[keyof typeof AgentO
174
173
  * The full set of authorable context attribute keys for AgentOps.
175
174
  * Iterate this to enumerate the authorable surface (cockpit, conformance).
176
175
  */
177
- export declare const AgentOpsContextKeys: 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", "cwd", "detected_language", "detected_script", "detected_threats", "detector_count", "direction", "egress_hosts", "encoded_content_detected", "encoded_count", "encoded_score", "encoded_types", "event", "exec_allowlist", "exec_target_paths", "factuality_score", "flow_compartments", "flow_confidentiality", "flow_data_types", "flow_integrity", "flow_origins", "flow_resolution_status", "flow_sink", "flow_sink_effects", "flow_sink_is_external", "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", "isolation_tier", "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", "max_threat_severity", "mcp_config_risk", "mcp_risk_score", "mcp_risk_type", "mcp_server", "mcp_server_verified", "mcp_tool", "mechanism_capabilities", "model_name", "model_provider", "multi_turn_detection", "network_egress", "package_check_status", "package_install_detected", "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", "principal_clearances", "principal_compartments", "privilege_scope", "profanity_score", "read_target_paths", "request_id", "resolved_target_paths", "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", "source", "sql_injection_detected", "sql_injection_score", "sql_injection_type", "surface", "suspicious_pattern", "threat_categories", "threat_count", "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", "unresolved_target", "user_email", "violence_score", "weapons_score", "workspace_root", "writable_paths", "write_target_paths"];
176
+ export declare const AgentOpsContextKeys: 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", "cwd", "detected_language", "detected_script", "detected_threats", "detector_count", "direction", "egress_hosts", "encoded_content_detected", "encoded_count", "encoded_score", "encoded_types", "event", "exec_allowlist", "exec_target_paths", "factuality_score", "flow_compartments", "flow_confidentiality", "flow_data_types", "flow_integrity", "flow_origins", "flow_resolution_status", "flow_sink", "flow_sink_effects", "flow_sink_is_external", "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", "isolation_tier", "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", "max_threat_severity", "mcp_config_risk", "mcp_risk_score", "mcp_risk_type", "mcp_server", "mcp_server_verified", "mcp_tool", "mechanism_capabilities", "model_name", "model_provider", "multi_turn_detection", "network_egress", "package_check_status", "package_install_detected", "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_clearances", "principal_compartments", "privilege_scope", "profanity_score", "read_target_paths", "request_id", "resolved_target_paths", "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", "source", "sql_injection_detected", "sql_injection_score", "sql_injection_type", "surface", "suspicious_pattern", "threat_categories", "threat_count", "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", "unresolved_target", "user_email", "violence_score", "weapons_score", "workspace_root", "writable_paths", "write_target_paths"];
@@ -106,7 +106,6 @@ export const AgentOpsContextKey = {
106
106
  PiiDetected: 'pii_detected',
107
107
  PiiScore: 'pii_score',
108
108
  PiiTypes: 'pii_types',
109
- Principal: 'principal',
110
109
  PrincipalClearances: 'principal_clearances',
111
110
  PrincipalCompartments: 'principal_compartments',
112
111
  PrivilegeScope: 'privilege_scope',
@@ -275,7 +274,6 @@ export const AgentOpsContextKeys = [
275
274
  AgentOpsContextKey.PiiDetected,
276
275
  AgentOpsContextKey.PiiScore,
277
276
  AgentOpsContextKey.PiiTypes,
278
- AgentOpsContextKey.Principal,
279
277
  AgentOpsContextKey.PrincipalClearances,
280
278
  AgentOpsContextKey.PrincipalCompartments,
281
279
  AgentOpsContextKey.PrivilegeScope,
@@ -95,7 +95,6 @@ export declare const GuardrailsContextKey: {
95
95
  readonly PiiDetected: "pii_detected";
96
96
  readonly PiiScore: "pii_score";
97
97
  readonly PiiTypes: "pii_types";
98
- readonly Principal: "principal";
99
98
  readonly PrivilegeScope: "privilege_scope";
100
99
  readonly ProfanityScore: "profanity_score";
101
100
  readonly ReadTargetPaths: "read_target_paths";
@@ -156,4 +155,4 @@ export type GuardrailsContextKey = (typeof GuardrailsContextKey)[keyof typeof Gu
156
155
  * The full set of authorable context attribute keys for Guardrails.
157
156
  * Iterate this to enumerate the authorable surface (cockpit, conformance).
158
157
  */
159
- 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", "exec_target_paths", "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_input_request_detected", "mcp_input_request_methods", "mcp_input_request_score", "mcp_input_request_types", "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", "read_target_paths", "request_id", "resolved_target_paths", "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", "unresolved_target", "violence_score", "weapons_score", "write_target_paths"];
158
+ 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", "exec_target_paths", "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_input_request_detected", "mcp_input_request_methods", "mcp_input_request_score", "mcp_input_request_types", "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", "privilege_scope", "profanity_score", "read_target_paths", "request_id", "resolved_target_paths", "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", "unresolved_target", "violence_score", "weapons_score", "write_target_paths"];
@@ -97,7 +97,6 @@ export const GuardrailsContextKey = {
97
97
  PiiDetected: 'pii_detected',
98
98
  PiiScore: 'pii_score',
99
99
  PiiTypes: 'pii_types',
100
- Principal: 'principal',
101
100
  PrivilegeScope: 'privilege_scope',
102
101
  ProfanityScore: 'profanity_score',
103
102
  ReadTargetPaths: 'read_target_paths',
@@ -248,7 +247,6 @@ export const GuardrailsContextKeys = [
248
247
  GuardrailsContextKey.PiiDetected,
249
248
  GuardrailsContextKey.PiiScore,
250
249
  GuardrailsContextKey.PiiTypes,
251
- GuardrailsContextKey.Principal,
252
250
  GuardrailsContextKey.PrivilegeScope,
253
251
  GuardrailsContextKey.ProfanityScore,
254
252
  GuardrailsContextKey.ReadTargetPaths,