Skip to main content

ToolsetArgsError

Enum ToolsetArgsError 

Source
#[non_exhaustive]
pub enum ToolsetArgsError { DangerousKey { matched_key: &'static str, }, NestingTooDeep { depth: usize, max_depth: usize, }, TooManyNodes { count_limit: usize, }, }
Expand description

All distinct reasons crate::validate_toolset_tool_args can reject a payload.

The set is #[non_exhaustive] — the validator may grow new check classes in future versions and callers should match with a _ => fallback. (Unlike crate::ToolsetFormatError, which is exhaustive by design, this type intentionally carries the #[non_exhaustive] attribute.)

§Redaction guarantee

No variant Display output ever contains:

  • The inbound argument key string (even the rejected one).
  • Any byte from any argument value.

Error messages reference only compile-time &'static str constants from the denylist, ensuring that a crafted payload carrying secret-shaped values cannot leak through Display.

Variants (Non-exhaustive)§

This enum is marked as non-exhaustive
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
§

DangerousKey

The argument payload contains a key that is in the JS-runtime-dangerous denylist at some depth (including within arrays).

The matched_key field holds the matched &'static str constant from crate::ARGS_KEY_DENYLIST, NOT the input key string. This ensures the error message never echoes attacker-controlled bytes.

§Why this class of key is dangerous

When the wallet’s JSON output is consumed by a downstream JavaScript agent runtime, certain property names have special semantics that can be exploited:

  • toJSON — custom serialisation hook; overrides JSON.stringify.
  • then — presence makes an object “thenable”, hijacking await/Promise.resolve.
  • __proto__ — prototype pollution via Object.assign or spread.
  • constructor / prototype — class-hierarchy tampering.
  • toString / valueOf — coercion hooks invoked in string + number contexts.
  • __defineGetter__ / __defineSetter__ / __lookupGetter__ / __lookupSetter__ — Object.prototype accessor-injection vectors.

These keys have NO legitimate use in any matrix-tool argument struct (StellarPayArgs, StellarPayCommitArgs, StellarBalancesArgs, SEP tool args). Their presence at any depth is unambiguously attacker-authored.

Fields

§matched_key: &'static str

The matched &'static str constant from crate::ARGS_KEY_DENYLIST.

This is NOT the input key string — it is the constant from the denylist that the input key matched. The Display output is therefore attacker-controlled-bytes-free.

§

NestingTooDeep

The argument payload nesting depth exceeds crate::TOOLSET_ARGS_MAX_DEPTH.

Excessively-nested payloads are refused to prevent work-stack exhaustion and to bound the cost of the iterative walk. The depth bound is set substantially above the deepest legitimate matrix-tool arg shape (see crate::TOOLSET_ARGS_MAX_DEPTH documentation for the sizing rationale).

depth is the exact depth of the first node that exceeded the bound (the walk short-circuits at that node and never descends further).

Fields

§depth: usize

The exact depth of the first node that exceeded the bound.

The walk short-circuits at this node; no further nodes are visited.

§max_depth: usize

The depth bound that was exceeded (TOOLSET_ARGS_MAX_DEPTH).

§

TooManyNodes

The argument payload total node count exceeds crate::TOOLSET_ARGS_MAX_NODES.

Payloads with an excessive number of nodes (deep OR wide) are refused to bound the total work performed by the iterative walk.

§Why this bound is necessary

The depth bound (TOOLSET_ARGS_MAX_DEPTH) prevents stack-like traversal cost but does not bound WIDTH: a flat object or array with N million elements pushes N million references onto the work-stack in a single iteration. The node-count cap closes this O(payload-width) unbounded case.

The MCP transport bounds message size via the frame-size limit, but the CLI --args consumer does NOT have that guard. This cap ensures the walk is bounded on both transports.

count_limit is the only field — no attacker-controlled value is echoed.

Fields

§count_limit: usize

The node-count limit that was exceeded (TOOLSET_ARGS_MAX_NODES).

Trait Implementations§

Source§

impl Debug for ToolsetArgsError

Source§

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

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

impl Display for ToolsetArgsError

Source§

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

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

impl Error for ToolsetArgsError

1.30.0 · Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0:

use the Display impl or to_string()

1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0:

replaced by Error::source, which can support downcasting

Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more

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<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

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

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

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.