pub struct SecurityConfig<State = Unvalidated> { /* private fields */ }Expand description
Security configuration with default-deny settings.
This configuration controls various security checks performed during archive extraction to prevent common vulnerabilities.
§Performance Note
This struct contains heap-allocated collections (Vec<String>). For
performance, pass by reference (&SecurityConfig) rather than cloning. If
shared ownership is needed across threads, consider wrapping in
Arc<SecurityConfig>.
§Examples
use exarch_core::SecurityConfig;
// Use secure defaults
let config = SecurityConfig::default();
// Customize via fluent builder
let custom = SecurityConfig::default()
.with_max_file_size(100 * 1024 * 1024)
.with_max_total_size(1024 * 1024 * 1024)
.with_allow_symlinks(true);§Typestate
SecurityConfig carries a phantom State type parameter — Unvalidated
(the default) or Validated — that tracks whether
validate has been called. Builder methods
are only available in the Unvalidated state; security-sensitive APIs
(the ArchiveFormat trait and
everything downstream of it) require SecurityConfig<Validated>. This
makes skipping validation a compile error instead of a runtime gap.
§Sealing
Fields are private and reachable only through
Deref<Target = SecurityConfigFields>, so
cfg.max_file_size continues to work as plain field access for both states.
DerefMut is implemented only for
SecurityConfig<Unvalidated>, so a SecurityConfig<Validated>’s fields
cannot be reassigned after the fact — the only way to produce one is
validate itself, and it stays that way for
its entire lifetime.
Implementations§
Source§impl SecurityConfig<Unvalidated>
impl SecurityConfig<Unvalidated>
Sourcepub fn permissive() -> Self
pub fn permissive() -> Self
Creates a permissive configuration for trusted archives.
This configuration allows symlinks, hardlinks, absolute paths, and solid archives. Use only when extracting archives from trusted sources.
Sourcepub fn validate(self) -> Result<SecurityConfig<Validated>>
pub fn validate(self) -> Result<SecurityConfig<Validated>>
Validates that the configuration values are logically consistent,
transitioning to the Validated typestate on success.
Returns an error if any field has a value that would make security
enforcement impossible (zero limits or non-positive ratio). Consumes
self: the only way to obtain a SecurityConfig<Validated>, which is
what every security-sensitive API in this crate requires. Once
returned, the Validated config’s fields can no longer be reassigned
(see the “Sealing” section on the type-level docs), so this check can
never be silently invalidated afterward.
§Errors
Returns ArchiveError::InvalidConfiguration if:
max_compression_ratiois not positivemax_file_sizeis zeromax_total_sizeis zeromax_path_depthis zeromax_file_countis zeromax_solid_block_memoryis zeromax_tar_metadata_bytesis zero- any entry in
allowed_extensionsorbanned_path_componentsis empty, contains a null byte, or exceedscrate::MAX_CONFIG_ENTRY_LENGTHbytes
§Examples
use exarch_core::SecurityConfig;
let config = SecurityConfig::default();
assert!(config.validate().is_ok());
let bad = SecurityConfig::default().with_max_file_size(0);
assert!(bad.validate().is_err());Sourcepub fn with_max_file_size(self, size: u64) -> Self
pub fn with_max_file_size(self, size: u64) -> Self
Sets the maximum size for a single extracted file in bytes.
§Examples
use exarch_core::SecurityConfig;
let config = SecurityConfig::default().with_max_file_size(100 * 1024 * 1024);
assert_eq!(config.max_file_size, 100 * 1024 * 1024);Sourcepub fn with_max_total_size(self, size: u64) -> Self
pub fn with_max_total_size(self, size: u64) -> Self
Sets the maximum total size for all extracted files in bytes.
§Examples
use exarch_core::SecurityConfig;
let config = SecurityConfig::default().with_max_total_size(1024 * 1024 * 1024);
assert_eq!(config.max_total_size, 1024 * 1024 * 1024);Sourcepub fn with_max_compression_ratio(self, ratio: f64) -> Self
pub fn with_max_compression_ratio(self, ratio: f64) -> Self
Sets the maximum allowed compression ratio (uncompressed / compressed).
§Examples
use exarch_core::SecurityConfig;
let config = SecurityConfig::default().with_max_compression_ratio(50.0);
assert_eq!(config.max_compression_ratio, 50.0);Sourcepub fn with_max_file_count(self, count: usize) -> Self
pub fn with_max_file_count(self, count: usize) -> Self
Sets the maximum number of files that can be extracted.
§Examples
use exarch_core::SecurityConfig;
let config = SecurityConfig::default().with_max_file_count(500);
assert_eq!(config.max_file_count, 500);Sourcepub fn with_max_path_depth(self, depth: usize) -> Self
pub fn with_max_path_depth(self, depth: usize) -> Self
Sets the maximum path depth allowed.
§Examples
use exarch_core::SecurityConfig;
let config = SecurityConfig::default().with_max_path_depth(16);
assert_eq!(config.max_path_depth, 16);Sourcepub fn with_allowed(self, allowed: AllowedFeatures) -> Self
pub fn with_allowed(self, allowed: AllowedFeatures) -> Self
Sets the feature flags controlling allowed archive features.
§Examples
use exarch_core::SecurityConfig;
use exarch_core::config::AllowedFeatures;
let features = AllowedFeatures::default();
let config = SecurityConfig::default().with_allowed(features);
assert!(!config.allowed.symlinks);Sourcepub fn with_allow_symlinks(self, allow: bool) -> Self
pub fn with_allow_symlinks(self, allow: bool) -> Self
Enables or disables symlinks in extracted archives.
§Examples
use exarch_core::SecurityConfig;
let config = SecurityConfig::default().with_allow_symlinks(true);
assert!(config.allowed.symlinks);Sourcepub fn with_allow_hardlinks(self, allow: bool) -> Self
pub fn with_allow_hardlinks(self, allow: bool) -> Self
Enables or disables hardlinks in extracted archives.
§Examples
use exarch_core::SecurityConfig;
let config = SecurityConfig::default().with_allow_hardlinks(true);
assert!(config.allowed.hardlinks);Sourcepub fn with_allow_absolute_paths(self, allow: bool) -> Self
pub fn with_allow_absolute_paths(self, allow: bool) -> Self
Enables or disables absolute paths in archive entries.
§Examples
use exarch_core::SecurityConfig;
let config = SecurityConfig::default().with_allow_absolute_paths(true);
assert!(config.allowed.absolute_paths);Sourcepub fn with_allow_world_writable(self, allow: bool) -> Self
pub fn with_allow_world_writable(self, allow: bool) -> Self
Enables or disables world-writable files.
§Examples
use exarch_core::SecurityConfig;
let config = SecurityConfig::default().with_allow_world_writable(true);
assert!(config.allowed.world_writable);Sourcepub fn with_preserve_permissions(self, preserve: bool) -> Self
pub fn with_preserve_permissions(self, preserve: bool) -> Self
Enables or disables preserving file permissions from the archive.
§Examples
use exarch_core::SecurityConfig;
let config = SecurityConfig::default().with_preserve_permissions(true);
assert!(config.preserve_permissions);Sourcepub fn with_allowed_extensions(self, extensions: Vec<String>) -> Self
pub fn with_allowed_extensions(self, extensions: Vec<String>) -> Self
Sets the list of allowed file extensions.
An empty list allows all extensions.
§Examples
use exarch_core::SecurityConfig;
let config = SecurityConfig::default()
.with_allowed_extensions(vec!["txt".to_string(), "pdf".to_string()]);
assert!(config.is_extension_allowed("txt"));
assert!(!config.is_extension_allowed("exe"));Sourcepub fn with_banned_path_components(self, components: Vec<String>) -> Self
pub fn with_banned_path_components(self, components: Vec<String>) -> Self
Sets the list of banned path components.
§Examples
use exarch_core::SecurityConfig;
let config = SecurityConfig::default().with_banned_path_components(vec![".git".to_string()]);
assert!(!config.is_path_component_allowed(".git"));
assert!(config.is_path_component_allowed(".ssh"));Sourcepub fn with_allow_solid_archives(self, allow: bool) -> Self
pub fn with_allow_solid_archives(self, allow: bool) -> Self
Enables or disables extraction from solid 7z archives.
§Examples
use exarch_core::SecurityConfig;
let config = SecurityConfig::default().with_allow_solid_archives(true);
assert!(config.allow_solid_archives);Sourcepub fn with_max_solid_block_memory(self, size: u64) -> Self
pub fn with_max_solid_block_memory(self, size: u64) -> Self
Sets the maximum memory for solid archive extraction in bytes.
Only applies when allow_solid_archives is true.
§Examples
use exarch_core::SecurityConfig;
let config = SecurityConfig::default()
.with_allow_solid_archives(true)
.with_max_solid_block_memory(1024 * 1024 * 1024);
assert_eq!(config.max_solid_block_memory, 1024 * 1024 * 1024);Sourcepub fn with_max_tar_metadata_bytes(self, size: u64) -> Self
pub fn with_max_tar_metadata_bytes(self, size: u64) -> Self
Sets the maximum bytes the TAR reader may consume for headers and metadata records (GNU long-name/long-link, PAX extended headers, GNU sparse extension blocks) in the gap between two consecutive entries.
§Examples
use exarch_core::SecurityConfig;
let config = SecurityConfig::default().with_max_tar_metadata_bytes(64 * 1024);
assert_eq!(config.max_tar_metadata_bytes, 64 * 1024);Source§impl<State> SecurityConfig<State>
Read-only queries and crate-internal helpers available regardless of
validation state.
impl<State> SecurityConfig<State>
Read-only queries and crate-internal helpers available regardless of validation state.
Sourcepub fn is_path_component_allowed(&self, component: &str) -> bool
pub fn is_path_component_allowed(&self, component: &str) -> bool
Validates whether a path component is allowed.
Comparison is case-insensitive to prevent bypass on case-insensitive filesystems (Windows, macOS default).
Sourcepub fn is_extension_allowed(&self, extension: &str) -> bool
pub fn is_extension_allowed(&self, extension: &str) -> bool
Validates whether a file extension is allowed.
When allowed_extensions is empty, all extensions are permitted.
When it is non-empty, only listed extensions are permitted.
Sourcepub fn is_path_extension_allowed(&self, extension: Option<&str>) -> bool
pub fn is_path_extension_allowed(&self, extension: Option<&str>) -> bool
Returns true if a file with the given optional extension may be
extracted.
When allowed_extensions is non-empty and extension is None
(the file has no extension), the file is treated as not allowed.
§Examples
use exarch_core::SecurityConfig;
let config = SecurityConfig::default().with_allowed_extensions(vec!["txt".to_string()]);
assert!(config.is_path_extension_allowed(Some("txt")));
assert!(!config.is_path_extension_allowed(Some("exe")));
// Files without an extension are blocked when the allowlist is non-empty.
assert!(!config.is_path_extension_allowed(None));
// Empty allowlist permits everything, including extension-less files.
let permissive = SecurityConfig::default();
assert!(permissive.is_path_extension_allowed(None));Trait Implementations§
Source§impl<State: Clone> Clone for SecurityConfig<State>
impl<State: Clone> Clone for SecurityConfig<State>
Source§fn clone(&self) -> SecurityConfig<State>
fn clone(&self) -> SecurityConfig<State>
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<State: Debug> Debug for SecurityConfig<State>
impl<State: Debug> Debug for SecurityConfig<State>
Source§impl Default for SecurityConfig<Unvalidated>
impl Default for SecurityConfig<Unvalidated>
Source§fn default() -> Self
fn default() -> Self
Creates a SecurityConfig with secure default settings.
Default values:
max_file_size: 50 MBmax_total_size: 500 MBmax_compression_ratio: 100.0max_file_count: 10,000max_path_depth: 32allowed: All features disabled (deny-by-default)preserve_permissions: falseallowed_extensions: empty (allow all)banned_path_components:[".git", ".ssh", ".gnupg", ".aws", ".kube", ".docker", ".env"]allow_solid_archives: false (solid archives rejected)max_solid_block_memory: 512 MBmax_tar_metadata_bytes: 4 MiB
Source§impl<State> Deref for SecurityConfig<State>
impl<State> Deref for SecurityConfig<State>
Source§type Target = SecurityConfigFields
type Target = SecurityConfigFields
Source§fn deref(&self) -> &SecurityConfigFields
fn deref(&self) -> &SecurityConfigFields
Source§impl DerefMut for SecurityConfig<Unvalidated>
Only Unvalidated configs are mutable — see the “Sealing” section on
SecurityConfig’s type-level docs for why this is the crux of the
typestate guarantee.
impl DerefMut for SecurityConfig<Unvalidated>
Only Unvalidated configs are mutable — see the “Sealing” section on
SecurityConfig’s type-level docs for why this is the crux of the
typestate guarantee.