Skip to main content

SecurityConfig

Struct SecurityConfig 

Source
pub struct SecurityConfig {
    pub allow_seed_commands: bool,
    pub allow_local_network: bool,
    pub allow_env_vars: Vec<String>,
    pub allow_blueprint_read_paths: bool,
    pub read_paths: Vec<String>,
    pub credential_store: CredentialStoreKind,
}
Expand description

[security] in ~/.leviath/config.toml.

Distinct from a blueprint’s [security] block, which configures taint tracking for one agent - this one holds machine-wide switches.

Fields§

§allow_seed_commands: bool

Whether a blueprint’s seed = { command = "..." } regions may run.

On by default. A command seed executes at spawn - before the first inference, and therefore before any tool-approval prompt - so it is the one place a manifest can run something without the user being asked. It is still confined to the run’s workdir, routed through the entry stage’s sandbox when the agent declares one, and capped by [limits] script_shell_timeout_secs. Set this to false to refuse them machine-wide, or pass --no-seed-commands for a single run. Inspect an agent’s command seeds before installing it with lev validate <path>.

§allow_local_network: bool

Whether agent-driven fetches may reach loopback, private, and link-local addresses.

Off by default. An agent’s web_fetch URL is chosen by the model out of context an attacker can influence - a search result, a page fetched a moment ago, an issue body - so an unrestricted fetch makes the agent a confused deputy inside the user’s network. The concrete targets are http://169.254.169.254/… (cloud metadata, which returns instance credentials), http://127.0.0.1:3000/api/… (the user’s own lev serve), and anything on the LAN.

Turn this on when the agent is genuinely meant to talk to something local - a self-hosted model, a dev server under test. It applies to the script host’s http_get/http_post and to redirect following; see leviath_core::net.

§allow_env_vars: Vec<String>

Credential-shaped environment variables that agent scripts may read.

A Rhai script tool or script provider calling env_var("NAME") gets any ordinary variable - PATH, TZ, an app’s own config. A name that looks like a credential (see leviath_core::secrets::is_sensitive_env_name) is refused unless it appears here, because a two-line script tool reading ANTHROPIC_API_KEY and POSTing it elsewhere was otherwise a working exfiltration path with no prompt anywhere in it.

List the exact names a script legitimately needs - typically the key for a custom provider script:

[security]
allow_env_vars = ["MY_PROVIDER_KEY"]

Matching is case-insensitive and exact. There is no wildcard: "*" is read as a variable literally named *, not as “allow everything”.

§allow_blueprint_read_paths: bool

Whether a blueprint’s [read_paths] declarations are honored as-is.

Off by default. A [read_paths] block travels inside the agent.leviath you installed, and a manifest may only tighten what your config allows, never widen it - otherwise any agent package could read ~/.ssh, this very config file (your API keys), or a password store by shipping one TOML line. With this off, an agent’s declared read paths are inert until you grant them via Self::read_paths or [agent_read_paths.<name>]. Turning it on says “any blueprint I run may read every path it declares” - reads only, each access still resolves symlinks and must land inside a declared entry, but prefer the per-agent grant for anything you did not author yourself.

§read_paths: Vec<String>

Machine-wide read grants for agents that declare [read_paths].

Entries use the same three forms as a blueprint’s [read_paths] allow: an exact path (grants its subtree), glob: and regex: patterns (matched against the symlink-resolved real path, written with / on every OS, regex auto-anchored). ~/ expands to your home; a relative entry resolves against the run’s workdir.

[security]
read_paths = ["~/.leviath/runs", "glob:~/design-docs/**"]

A grant only takes effect for a path the running blueprint also declares - by itself it grants nothing, so listing a directory here does not open it to agents that never asked.

§credential_store: CredentialStoreKind

Where provider API keys and MCP OAuth tokens are kept.

file by default - ~/.leviath/config.toml and ~/.leviath/mcp-auth.json, both created 0600 so they are never even briefly world-readable. This is what Claude Code and Codex do, and it is the only backend that works headless, in a container, over SSH, and on a CI runner.

Set it to keychain to move secrets into the OS credential store (macOS Keychain, Windows Credential Manager, Secret Service elsewhere), so a stolen ~/.leviath directory yields nothing:

[security]
credential_store = "keychain"

Then run lev auth migrate to move the secrets you already have. It is opt-in rather than the default because an unavailable keychain is not a degraded experience but a broken one - every inference fails at once - and the environments Leviath is most useful in are the least likely to have a working credential store. lev auth status reports whether this machine actually has one.

Trait Implementations§

Source§

impl Clone for SecurityConfig

Source§

fn clone(&self) -> SecurityConfig

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for SecurityConfig

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for SecurityConfig

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for SecurityConfig

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Eq for SecurityConfig

Source§

impl PartialEq for SecurityConfig

Source§

fn eq(&self, other: &SecurityConfig) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for SecurityConfig

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for SecurityConfig

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> ConditionalSend for T
where T: Send,

Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Converts Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Converts &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Converts &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSend for T
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DynEq for T
where T: Any + Eq,

Source§

fn dyn_eq(&self, other: &(dyn DynEq + 'static)) -> bool

This method tests for self and other values to be equal. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> FromTemplate for T
where T: Clone + Default + Unpin,

Source§

type Template = T

The Template for this type.
Source§

impl<T> FromWorld for T
where T: Default,

Source§

fn from_world(_world: &mut World) -> T

Creates Self using default().

Source§

impl<T> FutureExt for T

Source§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
Source§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> IntoResult<T> for T

Source§

fn into_result(self) -> Result<T, RunSystemError>

Converts this type into the system output type.
Source§

impl<A> Is for A
where A: Any,

Source§

fn is<T>() -> bool
where T: Any,

Checks if the current type “is” another type, using a TypeId equality comparison. This is most useful in the context of generic logic. Read more
Source§

impl<T> NoneValue for T
where T: Default,

Source§

type NoneType = T

Source§

fn null_value() -> T

The none-equivalent value.
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Serialize for T
where T: Serialize + ?Sized,

Source§

fn erased_serialize(&self, serializer: &mut dyn Serializer) -> Result<(), Error>

Source§

fn do_erased_serialize( &self, serializer: &mut dyn Serializer, ) -> Result<(), ErrorImpl>

Source§

impl<T> Template for T
where T: Clone + Default + Unpin,

Source§

type Output = T

The type of value produced by this Template.
Source§

fn build_template( &self, _context: &mut TemplateContext<'_, '_>, ) -> Result<<T as Template>::Output, BevyError>

Uses this template and the given entity context to produce a Template::Output.
Source§

fn clone_template(&self) -> T

Clones this template. See Clone.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> TypeData for T
where T: 'static + Send + Sync + Clone,

Source§

fn clone_type_data(&self) -> Box<dyn TypeData>

Creates a type-erased clone of this value.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more