clawft_types/config/policies.rs
1//! Security policy configuration types.
2//!
3//! Defines [`CommandPolicyConfig`] (command execution allowlist/denylist)
4//! and [`UrlPolicyConfig`] (SSRF protection for URL fetching).
5
6use serde::{Deserialize, Serialize};
7
8/// Command execution security policy configuration.
9///
10/// Controls which commands the shell and spawn tools are allowed to execute.
11/// In allowlist mode (default), only explicitly permitted commands can run.
12/// In denylist mode, any command not matching a blocked pattern is allowed.
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct CommandPolicyConfig {
15 /// Policy mode: "allowlist" (default, recommended) or "denylist".
16 #[serde(default = "default_policy_mode")]
17 pub mode: String,
18
19 /// Permitted command basenames when in allowlist mode.
20 /// Overrides defaults when non-empty.
21 #[serde(default)]
22 pub allowlist: Vec<String>,
23
24 /// Blocked command patterns when in denylist mode.
25 /// Overrides defaults when non-empty.
26 #[serde(default)]
27 pub denylist: Vec<String>,
28}
29
30fn default_policy_mode() -> String {
31 "allowlist".to_string()
32}
33
34impl Default for CommandPolicyConfig {
35 fn default() -> Self {
36 Self {
37 mode: default_policy_mode(),
38 allowlist: Vec::new(),
39 denylist: Vec::new(),
40 }
41 }
42}
43
44/// URL safety policy configuration for SSRF protection.
45///
46/// Controls which URLs the web fetch tool is allowed to access.
47/// When enabled (default), requests to private networks, loopback
48/// addresses, and cloud metadata endpoints are blocked.
49#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct UrlPolicyConfig {
51 /// Whether URL safety validation is enabled.
52 #[serde(default = "default_url_policy_enabled")]
53 pub enabled: bool,
54
55 /// Allow requests to private/internal IP ranges.
56 #[serde(default, alias = "allowPrivate")]
57 pub allow_private: bool,
58
59 /// Domains that bypass all safety checks.
60 #[serde(default, alias = "allowedDomains")]
61 pub allowed_domains: Vec<String>,
62
63 /// Domains that are always blocked.
64 #[serde(default, alias = "blockedDomains")]
65 pub blocked_domains: Vec<String>,
66}
67
68fn default_url_policy_enabled() -> bool {
69 true
70}
71
72impl Default for UrlPolicyConfig {
73 fn default() -> Self {
74 Self {
75 enabled: default_url_policy_enabled(),
76 allow_private: false,
77 allowed_domains: Vec::new(),
78 blocked_domains: Vec::new(),
79 }
80 }
81}