pub struct Policy {
pub allow_effects: BTreeSet<String>,
pub allow_fs_read: Vec<PathBuf>,
pub allow_fs_write: Vec<PathBuf>,
pub allow_net_host: Vec<String>,
pub allow_proc: Vec<String>,
pub allow_approval: Vec<String>,
pub budget: Option<u64>,
}Expand description
Re-exported so embedders can build a handlers::State::policy_ceiling
without taking a direct dependency on lex-runtime.
Policy a program is run under. Empty allow_effects = pure-only
execution.
Wildcard scopes (read before embedding): the scope lists
(allow_fs_read, allow_fs_write, allow_net_host, allow_proc)
follow an empty = allow ANY convention, not empty = deny.
Granting a scoped effect in allow_effects while leaving its scope
list empty therefore opens the unrestricted form (any path / host
/ binary). That’s intentional for trusted local use (lex run),
but it’s a footgun for embedders that build a Policy from
untrusted input. Such embedders should populate the scope list for
every kind they grant, or call Policy::wildcard_scoped_grants
to detect the wide-open ones and refuse them. (#552)
Fields§
§allow_effects: BTreeSet<String>§allow_fs_read: Vec<PathBuf>Path scope for the [fs_read] effect. Empty = any path
(wildcard), not deny — see the type-level note above (#552).
allow_fs_write: Vec<PathBuf>Path scope for the [fs_write] effect. Empty = any path
(wildcard), not deny — see the type-level note above (#552).
allow_net_host: Vec<String>Per-host scope on the [net] effect. Empty = any host (when
[net] is in allow_effects); non-empty = only requests to
these hosts succeed. Hosts compare against the URL’s host
substring (port-agnostic). Lets a tool be granted [net] but
scoped to e.g. api.openai.com only — without this, [net]
is a blank check to exfiltrate anywhere.
allow_proc: Vec<String>Per-binary scope on the [proc] effect. Empty = ANY binary
allowed once [proc] is granted (treat as a global escape
hatch; only acceptable for trusted code). Non-empty =
proc.spawn(cmd, args) must match cmd against the
basename portion of one of these entries. Per-arg validation
is the caller’s responsibility — see SECURITY.md’s
“argument injection” note.
allow_approval: Vec<String>Per-scope allowlist on the [approval] effect. Empty = any
scope allowed once approval is granted (treat as a global
human-escalation escape hatch; only acceptable for trusted
code). Non-empty = approval.request(scope, reason) must
match scope against one of these entries — lets an operator
grant e.g. “payment approvals only” rather than a blanket
human-in-the-loop channel.
budget: Option<u64>Implementations§
Source§impl Policy
impl Policy
pub fn pure() -> Policy
Sourcepub fn wildcard_scoped_grants(&self) -> Vec<&'static str>
pub fn wildcard_scoped_grants(&self) -> Vec<&'static str>
Report the granted scoped effects whose scope list is empty —
i.e. the ones the runtime treats as unrestricted (“any”):
proc (any binary), net (any host), fs_read / fs_write
(any path). Returns an empty vec when no granted kind is left
wide open.
Intended for embedders that expose execution to untrusted
callers: build the effective Policy, then refuse to run (or
loudly log) if this returns non-empty. Pure / time / rand
grants never appear here — they have no scope. (#552)