You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
lex-core::includes: platform-absolute include src (Windows C:\foo, \\server\share, \foo) is now rejected up front in resolve_path with the new IncludeError::AbsolutePath variant instead of relying on PathBuf::join's "absolute replaces base" semantics + the downstream root-escape check. The spec forbids absolute filesystem paths from entering the resolution pipeline; this holds the line at the input boundary and surfaces a clear "use relative or root-absolute" message instead of a misleading "escapes root" error. The root-absolute form (leading / against the includes root) is unchanged. Addresses item #4 from the security review. (#TBD)
Added
lex-core::includes: resource limits to bound resolver work against adversarial input. ResolveConfig::max_total_includes (default 1000) caps the total number of lex.include annotations resolved across the entire document — max_depth alone bounds chain length but a doc with thousands of includes at depth 1 still blows past it. FsLoader::with_max_file_size(bytes) (default 10 MiB) caps per-include file size; oversize files are rejected before any bytes hit memory. Both are surfaced as their own IncludeError variants (TotalIncludesExceeded, FileTooLarge) with include_site for editor diagnostics. Configurable via new [includes].max_total_includes and [includes].max_file_size keys in lex.toml. Addresses item #3 from the security review. (#503)
Security
lex-core: FsLoader now defends against arbitrary-file-read via symlink path traversal. Previously the resolver's lexical ..-normalization correctly blocked textual root escapes, but a symlink inside the repository pointing outside the resolution root (e.g., repo/sneaky -> /etc) bypassed the check — lexical_normalize doesn't touch the filesystem, so it can't see through symlinks. FsLoader now stores its allowed root and, on every load, calls fs::canonicalize on both the requested path and the root, then verifies the canonical target sits under the canonical root. Symlinks pointing outside root are rejected as IncludeError::RootEscape before any read happens. Editors and CI that process untrusted Lex repositories should pick up this fix immediately. Surfaces a new LoadError::OutsideRoot variant; Loader trait now returns LoadedFile { source, canonical_path } instead of bare String so the resolver can use the loader's authoritative identity for cycle detection. (#502)
Changed
lex-core::includes: Loader::load now returns LoadedFile { source, canonical_path } instead of String. Implementations decide what canonical_path means — FsLoader returns the post-fs::canonicalize path (symlinks resolved, case-folded on case-insensitive FS); MemoryLoader returns the lookup key unchanged. The resolver uses canonical_path for cycle detection and origin stamping, so symlink loops and case-folded re-includes are now caught as IncludeError::Cycle rather than slipping through to IncludeError::DepthExceeded.
lex-core::includes: FsLoader::new now takes the resolution root: FsLoader::new(root: PathBuf). Default impl removed (a loader without a root would be unsafe).
lex-core::includes: FsLoader now rejects non-regular files (FIFOs, sockets, devices, directories) before reading. Previously a malicious symlink to /dev/zero could block or OOM the reader once the symlink check landed; this is the second layer of defense.