{"record":{"id":"84a27361033b5b8c","repo":"astrid-runtime/astrid","slug":"invalid-astrid-volume-region-name-name","errorCode":null,"errorMessage":"invalid Astrid volume region name {name:?}","messagePattern":"invalid Astrid volume region name (.+?)","errorType":"validation","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/astrid-storage/src/volume.rs","lineNumber":46,"sourceCode":"    /// Construct a portable region name.\n    ///\n    /// # Errors\n    ///\n    /// Rejects empty names, absolute names, traversal, empty components,\n    /// backslashes, control characters, and names beyond the format limit.\n    pub fn new(name: impl Into<String>) -> io::Result<Self> {\n        let name = name.into();\n        if name.is_empty()\n            || name.len() > MAX_REGION_NAME_BYTES\n            || name.starts_with('/')\n            || name.ends_with('/')\n            || name.contains('\\\\')\n            || name.chars().any(char::is_control)\n            || name\n                .split('/')\n                .any(|part| part.is_empty() || part == \".\" || part == \"..\")\n        {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidInput,\n                format!(\"invalid Astrid volume region name {name:?}\"),\n            ));\n        }\n        Ok(Self(name))\n    }\n\n    /// Borrow the canonical UTF-8 region name.\n    #[must_use]\n    pub fn as_str(&self) -> &str {\n        &self.0\n    }\n}\n\n/// One path-free namespace mutation committed as part of a volume transaction.\n#[derive(Clone, Debug, PartialEq, Eq)]\npub enum VolumeMetadataMutation {\n    /// Move `source` to an absent `destination`.","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage/src/volume.rs#L28-L64","documentation":"VolumeRegion::new validates the region name and rejects names containing backslashes, control characters, empty path segments, or '.'/'..' segments (plus the earlier checks in the same condition). The name is used as a storage path component, so unsafe values are refused with InvalidInput at construction time.","triggerScenarios":"Calling VolumeRegion::new with a name containing '\\\\', any control char, an empty '/'-separated segment ('a//b', leading/trailing '/'), '.', or '..' segments.","commonSituations":"Deriving region names from user input or file paths without sanitizing; Windows-style paths with backslashes smuggled in; path traversal attempts ('../secret') being blocked by design.","solutions":["Sanitize the name: strip control chars and backslashes before constructing","Reject or normalize input containing '..' or empty segments before calling VolumeRegion::new","Use only simple relative identifiers like 'alpha/beta' (no leading, trailing, or doubled slashes)","Validate user-supplied names against a stricter allowlist (alphanumeric, '-', '_', '/')"],"exampleFix":"// before\nlet region = VolumeRegion::new(\"..\\\\etc/passwd\")?;\n// after\nlet clean = name.replace('\\\\', \"/\");\nlet region = VolumeRegion::new(&clean)?; // now passes validation if segments are safe","handlingStrategy":"validation","validationCode":"fn valid_region_name(name: &str) -> bool {\n    !name.contains('\\\\') && !name.chars().any(char::is_control)\n        && name.split('/').all(|p| !p.is_empty() && p != \".\" && p != \"..\")\n}\nassert!(valid_region_name(user_input), \"invalid region name\");","typeGuard":"fn as_region(name: &str) -> Option<VolumeRegion> { VolumeRegion::new(name).ok() }","tryCatchPattern":"match VolumeRegion::new(name) {\n    Err(e) if e.kind() == std::io::ErrorKind::InvalidInput => return Err(MyError::BadRegion(name.into())),\n    other => other?,\n}","preventionTips":["Sanitize any user/path-derived input before constructing region names","Use an allowlist regex like ^[A-Za-z0-9_][A-Za-z0-9_/-]*$","Never accept Windows-style separators; normalize '\\\\' to '/' first","Add unit tests covering '..', '//', backslash and control-char inputs"],"tags":["validation","path-safety","storage"],"backgroundTag":"invalid-argument-value","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}