{"record":{"id":"28fb83bf9b6b26b9","repo":"jdx/mise","slug":"invalid-tool-version-s-contains-path-traversa","errorCode":null,"errorMessage":"invalid tool version {s:?}: contains path-traversal sequence","messagePattern":"invalid tool version (.+?): contains path-traversal sequence","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/toolset/tool_request.rs","lineNumber":631,"sourceCode":"/// The deny list is the minimum set of characters that can break out of either\n/// a single- or double-quoted shell string, or that trigger expansion *inside*\n/// double quotes: quotes themselves, backslash, backtick, and `$`. Plus control\n/// characters (newlines split shell tokens) and `..` (filesystem traversal).\n/// Everything else is allowed so legitimate version vocabulary (npm-style\n/// semver ranges like `>=20 <21 || >=22` or `^1.0.0`, dates, channel names,\n/// `lts/hydrogen`, etc.) continues to work — those characters are only\n/// dangerous in *unquoted* shell context, which cannot occur without one of\n/// the rejected expansion characters appearing first. Leading dashes are also\n/// rejected so backend install tools cannot mistake a version for a CLI flag.\nfn validate_version_string(s: &str) -> Result<()> {\n    if s.is_empty() {\n        return Ok(());\n    }\n    if s.starts_with('-') {\n        bail!(\"invalid tool version {s:?}: must not start with '-'\");\n    }\n    if s.contains(\"..\") {\n        bail!(\"invalid tool version {s:?}: contains path-traversal sequence\");\n    }\n    if let Some(c) = s.chars().find(|c| is_forbidden_version_char(*c)) {\n        bail!(\"invalid tool version {s:?}: contains forbidden character {c:?}\");\n    }\n    Ok(())\n}\n\n/// Validate `ref:`/`branch:`/`tag:`/`rev:` values. Same character rules as\n/// version strings: branch/tag names already use the same broad vocabulary\n/// (`/`, `+`, `-`, etc.), so only shell-quote-breaking characters and leading\n/// dashes need rejection. Kept as a separate function for distinct error\n/// messages.\nfn validate_ref_string(s: &str) -> Result<()> {\n    if s.is_empty() {\n        return Ok(());\n    }\n    if s.starts_with('-') {\n        bail!(\"invalid tool ref {s:?}: must not start with '-'\");","sourceCodeStart":613,"sourceCodeEnd":649,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/toolset/tool_request.rs#L613-L649","documentation":"validate_version_string blocks version strings containing '..' to prevent path-traversal: a version is used to build install paths, and '..' could escape the tool's install directory. Such strings are rejected with this bail.","triggerScenarios":"ToolRequest::new_with_options -> validate_version_string sees a version containing '..' anywhere — e.g. 'node@22/../evil' or an unvalidated variable interpolated into a version spec.","commonSituations":"Malicious or malformed input in scripts generating version strings; typo'd relative paths pasted into version fields; attempts to reference versions outside the install tree.","solutions":["Remove the '..' sequence; use a real version or ref syntax (e.g. ref:main) for non-version installs","Validate/normalize any user-supplied version before passing it to mise","Use 'path:' backend syntax if you actually need a local path, not a version string","Keep version specs sourced from `mise ls-remote` output"],"exampleFix":"// before\nnode = '22/../../shared'\n// after\nnode = '22'","handlingStrategy":"validation","validationCode":"// block traversal sequences in version strings before invoking mise\nif (version.includes('..')) throw new Error('path traversal in version');","typeGuard":"const traversalSafe = (v) => typeof v === 'string' && !v.includes('..');","tryCatchPattern":"try { installTool(name, version) } catch (e) { if (String(e).includes('path-traversal')) { console.error('version contains ../ — refusing'); } else { throw e; } }","preventionTips":["Treat version strings as untrusted input; sanitize before use","Source versions from `mise ls-remote` rather than free-form input","Use path:/ref: syntax for local or branch installs instead of embedding paths in versions","Log and reject any version containing '..' in CI pipelines"],"tags":["validation","security","path-traversal"],"backgroundTag":"path-traversal-blocked","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}