{"record":{"id":"fdc1657c0d6b19ff","repo":"Kuberwastaken/claurst","slug":"session-id-contains-illegal-characters","errorCode":null,"errorMessage":"session_id contains illegal characters","messagePattern":"session_id contains illegal characters","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-rust/crates/tools/src/todo_write.rs","lineNumber":25,"sourceCode":"use std::path::{Path, PathBuf};\r\nuse tracing::debug;\r\n\r\n// ---------------------------------------------------------------------------\r\n// Session-aware persistence helpers\r\n// ---------------------------------------------------------------------------\r\n\r\n/// Validate that `session_id` is a plain filename — no path separators or\r\n/// `..` components that could be used for directory traversal (issue #204).\r\nfn validate_session_id(session_id: &str) -> Result<(), String> {\r\n    if session_id.contains('/') || session_id.contains('\\\\') || session_id.contains(\"..\") {\r\n        return Err(\"session_id contains illegal characters\".into());\r\n    }\r\n    Ok(())\r\n}\r\n\r\n/// Returns the path to the persisted todo list for `session_id`.\r\npub fn todos_path(session_id: &str) -> anyhow::Result<PathBuf> {\r\n    validate_session_id(session_id).map_err(|e| anyhow::anyhow!(e))?;\r\n    Ok(todos_dir().join(format!(\"{}.json\", session_id)))\r\n}\r\n\r\n/// Directory holding persisted todo lists (`<claurst home>/todos`).\r\nfn todos_dir() -> PathBuf {\r\n    claurst_core::config::Settings::config_dir().join(\"todos\")\r\n}\r\n\r\n/// Load the persisted todo list for `session_id`. Returns an empty vec if the\r\n/// file does not exist, cannot be parsed, or if `session_id` contains illegal\r\n/// path characters (issue #204).\r\npub fn load_todos(session_id: &str) -> Vec<Value> {\r\n    load_todos_in(&todos_dir(), session_id)\r\n}\r\n\r\n/// Like [`load_todos`] but reads from an explicit todos directory. Lets tests\r\n/// run hermetically without depending on a writable HOME.\r\n///\r","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/Kuberwastaken/claurst/blob/b0637c97ec34144387cbf2f74f65df6d16a6cef1/src-rust/crates/tools/src/todo_write.rs#L7-L43","documentation":"Security validation guard (issue #204): the session_id passed to todos_path contains '/', '\\\\', or '..' and is rejected to prevent directory traversal — a crafted session_id could otherwise write the todo file outside the session storage directory.","triggerScenarios":"Thrown at src-rust/crates/tools/src/todo_write.rs:25 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Use a plain identifier (UUID, alphanumeric slug) as session_id","Sanitize session ids at their source before persisting todos"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"b0637c97ec34144387cbf2f74f65df6d16a6cef1","analyzedAt":"2026-09-10T00:24:58.650Z","contentChangedAt":"2026-09-10T00:24:58.650Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}