#[non_exhaustive]pub struct ArgumentAllowlist {
pub tool: String,
pub argument: String,
pub allowed: Vec<String>,
pub required: bool,
pub deny_unknown_arguments: bool,
}Expand description
Per-tool argument allowlist entry.
When the middleware sees a tools/call for tool, it extracts the
string value at argument from the call’s arguments object and checks
its first token against allowed. If the token is not in the list
the call is rejected with 403.
§Scope: this is not the argument-validation layer
Argument validation belongs downstream, in the tool itself – its input schema and its handler. Only the tool knows its parameter types, value ranges, mutually exclusive options, and which combinations are meaningful. This crate deliberately does not attempt that, and cannot: it sees an untyped JSON object at an authorization boundary.
What an allowlist provides is a coarse, role-scoped gate answering “may this role invoke this tool in roughly this shape”. It is defence in depth layered on top of the tool’s own validation, never a replacement for it. Its deliberate limits follow from that:
- Only the first
shlex::splitword of the value is checked. An allowlist of["ls"]accepts"ls -la; id", because the first parsed word isls; everything after it is unconstrained. The check therefore constrains only the first parsed word, not every program a shell might go on to execute. - Object- and array-valued arguments are denied rather than inspected
wherever an allowlist or
deny_unknown_argumentsactually applies; there is no nested-path matching. - Basename matching is POSIX-only, so
C:\bin\ls.exewill not matchls.
This division is also why presence enforcement is opt-in rather than imposed: whether omitting an argument is safe depends entirely on the tool’s schema and defaults, which are the consumer’s to declare.
By default this constrains the value only when the argument is
present – omitting it entirely skips the check. Set
required to also demand the argument be supplied.
This default is permanent and deliberate: presence enforcement is
opt-in, because an allowlist that constrains a supplied value is a
legitimate configuration and the crate does not impose the stricter
policy on existing deployments. Use
ArgumentAllowlist::new_required whenever omitting the argument must
fail closed – in particular when the tool substitutes its own default
for a missing value, since that default is never checked.
Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.tool: StringTool name to match (exact or glob, e.g. "run_query").
argument: StringArgument key whose value is checked (e.g. "cmd", "query").
allowed: Vec<String>Permitted first-token values. Empty means unrestricted.
required: boolRequire the argument to be present and string-valued.
Defaults to false, preserving the historical semantics: an
allowlist constrains the value when the argument is supplied, and a
caller omitting it passes unchecked. That is safe when the tool’s
input schema already marks the argument required, but fails open
when the handler substitutes a default for a missing value.
When true, a call that omits the argument – or supplies a
non-string – is denied with 403, independently of allowed. Setting
required with an empty allowed therefore means “must be supplied
as a string, any value accepted”.
deny_unknown_arguments: boolReject any top-level argument that no allowlist for this (role, tool)
names.
Defaults to false, preserving the historical semantics: allowlists
constrain only the arguments they name, so {"cmd":"ls","danger":true}
passes when only cmd is allowlisted. That is safe when the tool’s
input schema rejects unknown keys, and fails open when it does not.
When true on ANY allowlist matching a (role, tool) pair, the
permitted argument names become the union of every matching allowlist’s
argument, and any other top-level key is denied
with 403. Object- and array-valued arguments are also denied, because
this crate has no nested-path allowlist to constrain their contents.
Implementations§
Source§impl ArgumentAllowlist
impl ArgumentAllowlist
Sourcepub fn new(
tool: impl Into<String>,
argument: impl Into<String>,
allowed: Vec<String>,
) -> Self
pub fn new( tool: impl Into<String>, argument: impl Into<String>, allowed: Vec<String>, ) -> Self
Create an argument allowlist for a tool.
The argument is optional: the allowed-value list is enforced only when
the caller supplies it. Use new_required when
omitting the argument must fail closed.
Sourcepub fn new_required(
tool: impl Into<String>,
argument: impl Into<String>,
allowed: Vec<String>,
) -> Self
pub fn new_required( tool: impl Into<String>, argument: impl Into<String>, allowed: Vec<String>, ) -> Self
Create an argument allowlist that requires the argument to be present.
This is the recommended constructor for new policies because it fails closed when the caller omits the constrained argument.
Sourcepub const fn with_required(self, required: bool) -> Self
pub const fn with_required(self, required: bool) -> Self
Require the argument to be present and string-valued.
Sourcepub const fn with_deny_unknown_arguments(self, deny: bool) -> Self
pub const fn with_deny_unknown_arguments(self, deny: bool) -> Self
Confine the tool to only the arguments its allowlists name.
Applies to the whole (role, tool) pair, not just this entry: see
deny_unknown_arguments.
Trait Implementations§
Source§impl Clone for ArgumentAllowlist
impl Clone for ArgumentAllowlist
Source§fn clone(&self) -> ArgumentAllowlist
fn clone(&self) -> ArgumentAllowlist
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more