The Yoshi error framework is designed with security and robustness in mind, particularly for high-stakes, performance-critical applications. This document outlines key security considerations, built-in safeguards, and best practices for using Yoshi securely in your projects.
Risk: Error messages often contain details useful for debugging. However, in production environments, these details could inadvertently expose sensitive information (e.g., API keys, database credentials, user personal data, internal system paths, or exact software versions that reveal vulnerabilities).
Yoshi's Safeguards:
- Runtime Sanitization (
is_production_mode()): Yoshi includes an internalsanitize_error_messagefunction. This function performs basic string replacement (e.g., "[REDACTED]" for "password", "token", "key") and truncates very long messages (over 256 bytes) to prevent accidental data dumps.- This sanitization is activated if the
stdfeature is enabled AND theYOSHI_PRODUCTION_MODEenvironment variable is set to"1"or"true".
- This sanitization is activated if the
- Explicit Control over
YoshiKind::Foreign: When wrapping external errors (Yoshi::foreign()), Yoshi captures thetype_nameof the original error. While this is useful for debugging, it's generally safe as type names are rarely sensitive. However, the original error'sDisplayoutput is processed bysanitize_error_message. - Backtrace Redaction: In
stdenvironments,YoshiBacktraceoutput is also automatically redacted ([Backtrace sanitized for production]) whenYOSHI_PRODUCTION_MODEis active, preventing stack traces from revealing sensitive paths or internal logic.
Best Practices:
- Always use
YOSHI_PRODUCTION_MODEin Production: Set this environment variable to1ortruein your production deployments. - Avoid Sensitive Data in Error Messages: Design your error messages (
message,suggestion,YoContextmessages) to be as generic as possible. If sensitive details are needed for debugging, attach them as typed payloads rather than directly in human-readable strings. - Leverage Typed Shells for Internal Debugging: Typed payloads are
#[serde(skip)]by default. This means they are not serialized to JSON or other formats unless you explicitly extract and serialize them. This makes them safer for storing sensitive debug data that should only be accessed programmatically within the application or a secure debugger. - Custom Sanitization Hooks: If Yoshi's default sanitization is insufficient, you can implement custom formatting logic or middleware that inspects and sanitizes error fields before logging or displaying.
- Logging Levels: Integrate Yoshi with
tracingand adjust logging levels based on environment.DEBUGorTRACElevel might include more verbose error details only in development.
Risk: An maliciously crafted or accidentally recursive error chain could lead to infinite recursion during formatting (fmt::Display) or traversal, causing stack overflows or excessive resource consumption (DoS).
Yoshi's Safeguards:
- Bounded Recursion (
MAX_DEPTH): Yoshi's internalformat_source_chain_optimizedfunction explicitly limits the recursion depth (defaultMAX_DEPTH = 32). If the chain exceeds this, it truncates the output with a message like "... (error chain truncated at depth X for security)". This prevents stack overflows and excessive CPU cycles during formatting. - Internal Cycle Detection (Implicit): While not a explicit cycle detection algorithm, the bounded recursion inherently mitigates infinite loops caused by circular references in error sources.
Best Practices:
- Avoid Manual Circular References: When constructing complex
Yoshierrors manually (especiallyYoshiKind::InternalorYoshiKind::Foreignwithsource), ensure you do not create circular dependencies where an error's source directly or indirectly points back to itself.
Risk: Mismatched data types or incorrect interpretation of error context could lead to logical errors or crashes.
Yoshi's Safeguards:
- Structured
YoshiKind: By providing a structuredYoshiKindenum with distinct fields for different error categories, Yoshi enforces type safety at the definition level. This reduces ambiguity compared to unstructured string errors. - Strongly-Typed Shells:
YoContext::shell::<T>()relies on Rust'sAnytrait anddowncast_ref(), which are type-safe. You can only retrieve a shell if its type matches the one you expect, preventing misinterpretations. Arc<str>for Shared Strings: UsingArc<str>for string fields inYoshiKindandYoContextensures immutable, shared ownership, preventing accidental modification of error messages after creation.- Procedural Macro Validation (
yoshi-derive): Theyoshi-derivemacro performs compile-time validation of attribute usage and field mappings, catching many common errors before runtime. This includes checking placeholder usage indisplayformats and uniqueness of error codes.
Best Practices:
- Define Custom Error Enums with
yoshi-derive: For application-specific errors, use#[derive(YoshiError)]to leverage compile-time checks and structured error definitions. - Use
YoshiKindAppropriately: Select theYoshiKindvariant that best semantically describes your error. This aids in programmatic handling and clarity. - Validate Retrieved Shells: Always check the
Optionreturned byshell::<T>()and handleNonecases.
Risk: Excessive error creation, deep context chains, or large payloads could consume too much memory or CPU, impacting application stability.
Yoshi's Safeguards:
- String Interning: Yoshi employs a global string interning pool (
StringInternPool) forArc<str>values inYoshiKindandYoContext. This dramatically reduces memory allocations for frequently repeated strings (e.g., common error messages, metadata keys). Arcfor Costly Clones:YoshiandYoContextuseArcfor fields likemessage,metadatavalues, andpayloads. Cloning aYoshierror orYoContextcreates shallow copies of theseArcs, significantly reducing memory and CPU overhead compared to deep cloning.- Conditional Backtrace Capture: Backtraces are only captured when enabled by environment variables, preventing performance overhead in production by default.
OptimizedFormatBuffer: The internal formatting logic uses a pre-allocated and intelligently growingOptimizedFormatBufferto minimize reallocations during error display.- Memory Usage Statistics (
memory::get_memory_stats): You can query global statistics on string interning hits/misses and estimated memory savings, helping to identify and address allocation hotspots.
Best Practices:
- Monitor Error Rates: Use
yoshi_std::error_instance_count()to monitor the rate of error creation in your application. High rates might indicate underlying issues (e.g., retry loops, misconfigured external services). - Limit Context Depth (Implicitly): While Yoshi protects against recursion, avoid excessively deep manual context chains if not strictly necessary, as they still increase overall memory footprint per error instance.
- Consider Clearing Intern Pool (Long-running applications): For extremely long-running services where unique strings might accumulate, consider occasionally calling
yoshi_std::memory::cleanup_intern_pool()ifstdfeature is enabled. This can help prevent memory leaks from unused interned strings, though it might introduce a brief performance hiccup.
Risk: While Yoshi aims to be secure, it relies on several Rust crates (e.g., once_cell, serde, tracing, rayon if used). Vulnerabilities in these dependencies could impact your application.
Yoshi's Approach:
- Minimal Dependencies: Yoshi strives for a minimal dependency footprint, especially for its
no_stdcore. - Audited Dependencies: Core dependencies are widely used and regularly audited by the Rust community.
Best Practices:
- Regular Dependency Audits: Use tools like
cargo auditto regularly check for known vulnerabilities in your project's dependency tree, including Yoshi's transitive dependencies. - Keep Dependencies Updated: Regularly update Yoshi and its dependencies to benefit from security patches and performance improvements.
The Yoshi error framework provides a robust and secure foundation for error handling in Rust applications. By understanding its built-in safeguards and following best practices for information disclosure, resource management, and type safety, you can leverage Yoshi to build highly resilient and secure systems. Always prioritize careful design of error messages and rigorous testing in production-like environments.