Struct SecurityPolicy
pub struct SecurityPolicy {Show 26 fields
pub autonomy: AutonomyLevel,
pub risk_profile_name: String,
pub delegation_policy: DelegationPolicy,
pub workspace_dir: PathBuf,
pub config_path: Option<PathBuf>,
pub data_dir: Option<PathBuf>,
pub workspace_only: bool,
pub allowed_commands: Vec<String>,
pub forbidden_paths: Vec<String>,
pub allowed_roots: Vec<PathBuf>,
pub allowed_roots_read_only: Vec<PathBuf>,
pub allowed_roots_write_only: Vec<PathBuf>,
pub max_actions_per_hour: u32,
pub max_cost_per_day_cents: u32,
pub require_approval_for_medium_risk: bool,
pub block_high_risk_commands: bool,
pub shell_env_passthrough: Vec<String>,
pub shell_timeout_secs: u64,
pub allowed_tools: Option<Vec<String>>,
pub excluded_tools: Option<Vec<String>>,
pub auto_approve: Vec<String>,
pub always_ask: Vec<String>,
pub sandbox_enabled: Option<bool>,
pub sandbox_backend: Option<String>,
pub firejail_args: Vec<String>,
pub tracker: PerSenderTracker,
}Fields§
§autonomy: AutonomyLevel§risk_profile_name: StringName of the risk profile this policy was built from. Used to gate delegation: a Delegate may only target an agent sharing the caller’s risk profile. Empty when constructed outside the profile path.
delegation_policy: DelegationPolicyWhether and to which agents this profile may delegate.
workspace_dir: PathBuf§config_path: Option<PathBuf>§data_dir: Option<PathBuf>§workspace_only: bool§allowed_commands: Vec<String>§forbidden_paths: Vec<String>§allowed_roots: Vec<PathBuf>Directories the agent can read AND write under. Includes
RiskProfileConfig.allowed_roots plus any cross-agent
AccessMode::ReadWrite grants resolved from
agent.workspace.access at policy construction time.
allowed_roots_read_only: Vec<PathBuf>Directories the agent can read but NOT write under. Populated
from cross-agent AccessMode::Read grants at policy
construction time. Empty when no read-only cross-agent access
is configured.
allowed_roots_write_only: Vec<PathBuf>Directories the agent can write but NOT read under. Populated
from cross-agent AccessMode::Write grants; read-side tools
ignore this list.
max_actions_per_hour: u32§max_cost_per_day_cents: u32§require_approval_for_medium_risk: bool§block_high_risk_commands: bool§shell_env_passthrough: Vec<String>§shell_timeout_secs: u64§allowed_tools: Option<Vec<String>>Tool name allowlist. None is unrestricted (default for agents
without an explicit risk_profile.allowed_tools setting).
Some(vec![]) denies every tool. Some(list) admits only the
listed names. Enforced at the agent loop’s tool-dispatch site.
excluded_tools: Option<Vec<String>>Tool name denylist. Subtracts from the allowed set (whether the
allowed set comes from allowed_tools or from the unrestricted
default). None and Some(vec![]) both mean “exclude nothing”.
auto_approve: Vec<String>Tools that never require approval in this profile. Mirrors
RiskProfileConfig.auto_approve.
always_ask: Vec<String>Tools that always require approval in this profile. Mirrors
RiskProfileConfig.always_ask.
sandbox_enabled: Option<bool>Whether the sandbox is enabled for this profile. None
inherits the global default at the call site.
sandbox_backend: Option<String>Sandbox backend identifier (e.g. "firejail", "landlock").
None inherits the global default.
firejail_args: Vec<String>Extra arguments forwarded to firejail when sandbox_backend
resolves to "firejail".
tracker: PerSenderTrackerImplementations§
Source§impl SecurityPolicy
impl SecurityPolicy
Sourcepub fn is_tool_allowed(&self, name: &str) -> bool
pub fn is_tool_allowed(&self, name: &str) -> bool
True when name is admissible under the current policy.
allowed_tools = None is unrestricted; Some(list) is the
allowlist. excluded_tools always subtracts.
pub fn is_tool_excluded(&self, name: &str) -> bool
Source§impl SecurityPolicy
impl SecurityPolicy
Sourcepub fn command_risk_level(&self, command: &str) -> CommandRiskLevel
pub fn command_risk_level(&self, command: &str) -> CommandRiskLevel
Classify command risk. Any high-risk segment marks the whole command high.
Sourcepub fn command_risk_level_for_shell(
&self,
command: &str,
dialect: ShellDialect,
) -> CommandRiskLevel
pub fn command_risk_level_for_shell( &self, command: &str, dialect: ShellDialect, ) -> CommandRiskLevel
Classify command risk using the language the runtime will execute.
Sourcepub fn validate_command_execution(
&self,
command: &str,
approved: bool,
) -> Result<CommandRiskLevel, String>
pub fn validate_command_execution( &self, command: &str, approved: bool, ) -> Result<CommandRiskLevel, String>
Validate full command execution policy (allowlist + risk gate).
Uses the conservative POSIX shell dialect. Shell tools that know the
runtime’s effective shell should call
validate_command_execution_for_shell
so the Windows nul null device is only accepted under cmd.exe.
Sourcepub fn validate_command_execution_for_shell(
&self,
command: &str,
approved: bool,
dialect: ShellDialect,
) -> Result<CommandRiskLevel, String>
pub fn validate_command_execution_for_shell( &self, command: &str, approved: bool, dialect: ShellDialect, ) -> Result<CommandRiskLevel, String>
Validate a command against the policy and the runtime’s shell language.
The dialect decides platform-specific redirect safety (e.g. the Windows
nul null device is discard-only under cmd.exe but an ordinary file
under a POSIX shell).
pub fn is_command_allowed(&self, command: &str) -> bool
Sourcepub fn is_command_allowed_for_shell(
&self,
command: &str,
dialect: ShellDialect,
) -> bool
pub fn is_command_allowed_for_shell( &self, command: &str, dialect: ShellDialect, ) -> bool
Check the command allowlist using the runtime’s actual shell language.
Allowlist + shell-safety check against a specific shell dialect. The
dialect selects the command grammar (PowerShell vs POSIX-like) and gates
platform-specific redirect safety (the Windows nul null device is only
discard-safe under cmd.exe).
Sourcepub fn forbidden_path_argument_for_shell(
&self,
command: &str,
dialect: ShellDialect,
) -> Option<String>
pub fn forbidden_path_argument_for_shell( &self, command: &str, dialect: ShellDialect, ) -> Option<String>
Scan command for forbidden path arguments against a specific shell
dialect. The dialect gates which redirect targets count as safe devices
(the Windows nul null device is only a safe device under cmd.exe) and
which relative forms are recognized as paths — Windows-relative paths are
understood for both cmd.exe and PowerShell, including cross-platform
PowerShell runtimes.
Sourcepub fn forbidden_workspace_path_argument_for_shell(
&self,
command: &str,
dialect: ShellDialect,
) -> Option<String>
pub fn forbidden_workspace_path_argument_for_shell( &self, command: &str, dialect: ShellDialect, ) -> Option<String>
Like SecurityPolicy::forbidden_workspace_path_argument, but against
a specific shell dialect: it uses the effective shell’s path syntax and
classifies platform-specific safe redirect devices by the shell that will
execute the command, resolving relative candidates through symlinks
before the workspace-boundary check.
Sourcepub fn forbidden_path_argument(&self, command: &str) -> Option<String>
pub fn forbidden_path_argument(&self, command: &str) -> Option<String>
Return the first path-like executable or argument blocked by path policy using the host platform’s default shell syntax.
String-level command path guard: flags a path argument that is absolute
and outside the workspace, uses .. traversal, a ~user form, or a
forbidden prefix. Best-effort token parsing, intended as a safety gate
before command execution. Does NOT resolve symlinks, so it is safe for
callers whose working directory is NOT the workspace (e.g. cron jobs run
in data_dir). Shell/skill tools, which run IN the workspace, should use
SecurityPolicy::forbidden_workspace_path_argument, which additionally
follows in-workspace symlinks to block escapes.
Sourcepub fn forbidden_workspace_path_argument(&self, command: &str) -> Option<String>
pub fn forbidden_workspace_path_argument(&self, command: &str) -> Option<String>
Like SecurityPolicy::forbidden_path_argument but for a command that
runs IN the workspace: each workspace-relative path argument is also
resolved (following symlinks, including dangling ones) and re-checked
against the workspace boundary with the host platform’s default shell
syntax, catching an in-workspace symlink that points outside for the
argument forms this static scan can see.
This is best-effort, defense-in-depth hardening over a token-scanned
command line - NOT a complete workspace boundary, and NOT equivalent to
the file tools, which resolve an operation-aware target at the call site.
It flags a path-shaped argument (one with a separator, e.g. link/x, a
redirect target, or an absolute / .. form) that escapes via an
in-workspace symlink. It does NOT, and cannot from a static parse, cover:
a bare argument with no separator (cat somelink) that is a symlink; a
path computed at run time via variable expansion or command substitution
($VAR, $(...)), eval, or a write done inside an executed script
(sh ./x.sh, where only the script path is scanned); a quoted path
holding whitespace ("link dir/out"), which the whitespace tokenizer
fragments; read-vs-write direction (an argument may be read or written, so
a resolved target allowed for EITHER passes, unlike the operation-aware
file tools); or non-Unix relative forms (a link\file path on Windows). A
shell command is Turing-complete; complete containment is the execution
boundary (the OS sandbox and the broader granular sandbox-policy work),
not this preflight.
Sourcepub fn is_path_allowed(&self, path: &str) -> bool
pub fn is_path_allowed(&self, path: &str) -> bool
Check if a file path is allowed (no path traversal, within workspace)
pub fn is_resolved_path_readable(&self, resolved: &Path) -> bool
Sourcepub fn approved_read_root(&self, resolved: &Path) -> Option<PathBuf>
pub fn approved_read_root(&self, resolved: &Path) -> Option<PathBuf>
Return the canonical allowlisted root directory that authorizes reading
resolved: the workspace first, then read-write roots, then read-only
roots. Callers bind a directory-handle-scoped open (cap-std beneath/
no-follow) to this boundary instead of re-walking a pathname that could be
swapped between the readability check and the open. Returns None when no
bounded allowlist root contains the path (e.g. a fully permissive,
non-workspace_only policy, or a device path) — there is then no
confinement boundary to bind to. Assumes resolved is already canonical
and has passed Self::is_resolved_path_readable.
pub fn is_resolved_path_allowed(&self, resolved: &Path) -> bool
pub fn is_runtime_config_path(&self, resolved: &Path) -> bool
pub fn runtime_config_violation_message(&self, resolved: &Path) -> String
pub fn resolved_path_violation_message(&self, resolved: &Path) -> String
Check whether autonomy permits a tool operation without recording it.
Sourcepub fn enforce_tool_operation(
&self,
operation: ToolOperation,
operation_name: &str,
) -> Result<(), String>
pub fn enforce_tool_operation( &self, operation: ToolOperation, operation_name: &str, ) -> Result<(), String>
Enforce policy and record an action for callers without a rate-limit wrapper.
Sourcepub fn reserve_action(&self) -> Option<ActionReservation>
pub fn reserve_action(&self) -> Option<ActionReservation>
Atomically reserve one action slot for a production-wrapped invocation.
Sourcepub fn record_action(&self) -> bool
pub fn record_action(&self) -> bool
Record an action for the current sender and check if rate-limited.
Returns true if allowed, false if budget exhausted.
Sourcepub fn is_rate_limited(&self) -> bool
pub fn is_rate_limited(&self) -> bool
Check if the current sender would be rate-limited without recording.
pub fn resolve_tool_path(&self, path: &str) -> PathBuf
pub fn is_under_allowed_root(&self, path: &str) -> bool
pub fn is_under_read_only_allowed_root(&self, path: &str) -> bool
Sourcepub fn is_under_any_allowed_root(&self, path: &str) -> bool
pub fn is_under_any_allowed_root(&self, path: &str) -> bool
Union of all three root tiers; directionality is enforced later by the resolved-path checks.
pub fn ensure_no_escalation_beyond( &self, parent: &SecurityPolicy, ) -> Result<(), EscalationViolation>
pub fn from_risk_profile( risk_profile: &RiskProfileConfig, workspace_dir: &Path, ) -> Self
pub fn from_profiles( risk_profile: &RiskProfileConfig, runtime_profile: Option<&RuntimeProfileConfig>, workspace_dir: &Path, ) -> Self
pub fn for_agent(config: &Config, agent_alias: &str) -> Result<Self>
pub fn prompt_summary(&self) -> String
Trait Implementations§
Source§impl Clone for SecurityPolicy
impl Clone for SecurityPolicy
Source§fn clone(&self) -> SecurityPolicy
fn clone(&self) -> SecurityPolicy
1.0.0 (const: unstable) · §fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for SecurityPolicy
impl Debug for SecurityPolicy
Auto Trait Implementations§
impl !RefUnwindSafe for SecurityPolicy
impl !UnwindSafe for SecurityPolicy
impl Freeze for SecurityPolicy
impl Send for SecurityPolicy
impl Sync for SecurityPolicy
impl Unpin for SecurityPolicy
impl UnsafeUnpin for SecurityPolicy
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more