This document describes the security posture of the multi-base crate. It
gives guidance for users on security considerations.
The codebase was reviewed for common security issues. No critical vulnerabilities were found.
-
Integer Overflow. Safe.
- All size calculations use checked arithmetic in debug mode.
- Capacity calculations for
StringandVecuse addition. The allocation fails before overflow. - Risk: Low. An attack would need near-
usize::MAXinputs. Memory allocation fails first.
-
Buffer Overflow and Underflow. Safe.
- All string slicing uses
char::len_utf8()for UTF-8 boundary detection. - No unsafe code or manual pointer arithmetic.
- Rust bounds checking prevents buffer overflows.
- Risk: None. Protected by Rust safety guarantees.
- All string slicing uses
-
Panic Conditions. Safe.
- Identity encoding uses
String::from_utf8_lossy. No panic on invalid UTF-8. - All decode operations return
Result. - Empty inputs return
Error::EmptyInput. - Invalid base codes return
Error::UnknownBase. - One
.expect()inencode_to_validated(). It cannot fail in practice. - Risk: Minimal. Library functions do not panic on arbitrary input.
- Identity encoding uses
-
Resource Exhaustion Attacks. Consider.
- No hard limits on input size.
- Large inputs consume proportional memory.
- Memory allocation failures are handled by the Rust allocator.
- Risk: Medium. Applications should set their own size limits.
- Recommendation: Applications that process untrusted input should enforce a maximum size limit.
-
Input Validation. Complete.
- Empty strings return
Error::EmptyInput. - Invalid base codes return
Error::UnknownBase. - Malformed encoded data is rejected by base-specific decoders.
- All validation goes through
Resulttypes. - Risk: None. Input validation at all boundaries.
- Empty strings return
For applications that process untrusted input, set a maximum size limit:
const MAX_INPUT_SIZE: usize = 10 * 1024 * 1024; // 10 MB
fn safe_decode(input: &str) -> Result<(Base, Vec<u8>), Error> {
if input.len() > MAX_INPUT_SIZE {
return Err(Error::InvalidBaseString);
}
multi_base::decode(input, true)
}Handle errors. Do not expose detailed error messages to untrusted parties:
match multi_base::decode(untrusted_input, true) {
Ok((base, data)) => {
// Process data
}
Err(_) => {
// Log the error internally. Return a generic error to the user.
eprintln!("Invalid multibase input");
}
}The Identity encoding (\0 prefix) uses lossy UTF-8 conversion:
- Invalid UTF-8 bytes are replaced with the Unicode replacement character (U+FFFD).
- This prevents panics. Invalid UTF-8 does not round-trip.
- For binary data that must round-trip, use a different base encoding.
// For binary data preservation, use Base64 or Base58
let encoded = multi_base::encode(Base::Base64, binary_data);
// Identity is for UTF-8 text only
let text_encoded = multi_base::encode(Base::Identity, "valid utf-8 text".as_bytes());Use strict decoding for untrusted input:
// For untrusted input, use strict mode
let (base, data) = multi_base::decode(untrusted, true)?;
// Permissive mode allows case-insensitive decoding for some bases
let (base, data) = multi_base::decode(trusted, false)?;The crate has 17 security tests in tests/security.rs. They cover:
- Large input handling (up to 1 MB).
- Malformed and malicious input patterns.
- Buffer reuse safety.
- Concurrent operation safety.
- Resource exhaustion resistance.
- Integer overflow safety.
- Invalid UTF-8 handling.
- Empty and truncated input handling.
Run security tests:
cargo test --test securityThe crate can be fuzzed with cargo-fuzz. Fuzz targets:
fuzz_decode— Decode arbitrary strings. Checks for panics on any input.fuzz_encode— Encode arbitrary bytes. Checks for panics on any binary data.fuzz_roundtrip— Encode and decode round-trip. Checks encode and decode consistency.
# Install cargo-fuzz
cargo install cargo-fuzz
# Run fuzz tests
cargo fuzz run fuzz_decode
cargo fuzz run fuzz_encode
cargo fuzz run fuzz_roundtripThe crate depends on:
base-x(0.2.7) — Variable-radix base encoding.data-encoding(2.3.1) — Standard base encodings.thiserror(2.0) — Error handling.
The Base256Emoji codec is implemented inline. The external
base256emoji dependency was dropped. See CHANGELOG.md.
All dependencies are maintained and used in the Rust ecosystem.
If you find a security vulnerability in the multi-base crate, report it
as follows:
- Do not open a public GitHub issue.
- Contact the maintainers by email. See
Cargo.tomlfor the address. - Give detailed information about the vulnerability.
- Allow reasonable time for a fix before public disclosure.
- No panics on arbitrary untrusted input.
- Memory safety. No unsafe code is used.
- Input validation at all boundaries.
- Thread-safe operations. All types are
Send + Sync. - Error information without exposure of internal state.
- Protection against resource exhaustion. This is an application responsibility.
- Constant-time operations. The crate is not for cryptographic use.
- Perfect round-trip of invalid UTF-8 in Identity encoding.
- Updated
SECURITY.mdcode examples to usemulti_base::instead of the oldmultibase::module path. - Corrected the stale
base256emojidependency reference.
- Added
#![deny(unsafe_code)]at the crate root. - Added clippy lint configuration with
unsafe_code = "deny". - Added
cargo auditjob in CI.
- Fixed Identity encoding panic risk. Now uses lossy UTF-8 conversion.
- Migrated to
thiserrorfor error handling. - Added 17 security tests.
- Added this
SECURITY.mddocument.
- Initial release with basic security considerations.