{"record":{"id":"c6499ec0fe43b6f6","repo":"AprilNEA/OpenLogi","slug":"id-must-be-one-synthetic-path-component-without-separators","errorCode":null,"errorMessage":"--id must be one synthetic path component without separators","messagePattern":"--id must be one synthetic path component without separators","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/openlogi-cli/src/cmd/fixture/contribute.rs","lineNumber":453,"sourceCode":"    if matches {\n        Ok(())\n    } else {\n        bail!(\n            \"the selected direct-capture target does not match the profile transport and slot; \\\n             reconnect the same device and use the same --device selector\"\n        )\n    }\n}\n\nfn validate_args(args: &ContributeArgs) -> Result<()> {\n    if args.id.trim().is_empty() || matches!(args.id.as_str(), \".\" | \"..\") {\n        bail!(\"--id must be a nonempty synthetic path component\");\n    }\n    if Path::new(&args.id).file_name() != Some(OsStr::new(&args.id))\n        || args.id.contains('/')\n        || args.id.contains('\\\\')\n    {\n        bail!(\"--id must be one synthetic path component without separators\");\n    }\n    if args.name.trim().is_empty() {\n        bail!(\"--name must be a nonempty synthetic device name\");\n    }\n    if args.output.file_name() != Some(OsStr::new(&args.id)) {\n        bail!(\"--output directory name must exactly equal --id\");\n    }\n    Ok(())\n}\n\nfn validate_state(args: &ContributeArgs, state: &ContributionState) -> Result<()> {\n    if state.version != STATE_VERSION {\n        bail!(\"unsupported contribution state version {}\", state.version);\n    }\n    if state.fixture_id != args.id\n        || state.profile_id != format!(\"{}-profile\", args.id)\n        || state.profile_name != args.name\n    {","sourceCodeStart":435,"sourceCodeEnd":471,"githubUrl":"https://github.com/AprilNEA/OpenLogi/blob/e846e6f4b4405e33bd6a9aaf949a482ce34cb6d8/crates/openlogi-cli/src/cmd/fixture/contribute.rs#L435-L471","documentation":"The contribute command requires `--id` to be exactly one path component with no separators. It checks `Path::file_name()` round-trips to the whole value and rejects any `/` or `\\\\`. This prevents the synthetic fixture output from escaping or nesting outside its intended directory (path-traversal / nested-path ids).","triggerScenarios":"Pass `--id` containing `/` (e.g. `a/b`), a backslash (`a\\\\b`), an absolute path (`/tmp/x`), a trailing slash (`x/`), or `..`-tricks (`a/../b`) — anything where `Path::new(id).file_name() != Some(id)` or separators are present.","commonSituations":"Copy-pasting a full path into `--id` instead of only the directory name, Windows-style separators typed on Linux/macOS, or building ids by joining segments.","solutions":["Use a single name without separators, e.g. `--id my-device` instead of `--id devices/my-device`.","If you need hierarchy, run the command with `--output /base/my-device` and keep the id as just `my-device` (the output's last component must equal the id anyway).","Sanitize the id before calling: replace `/` and `\\\\` with `-` or reject it in your wrapper script."],"exampleFix":"// before\nopenlogi fixture contribute --id devices/mx-master --name \"MX Master\" --output fixtures/devices/mx-master\n// after\nopenlogi fixture contribute --id mx-master --name \"MX Master\" --output fixtures/devices/mx-master","handlingStrategy":"validation","validationCode":"case \"$ID\" in */*|\\\\\\\\*) echo \"--id must be one path component\" >&2; exit 1;; esac\n[ \"$(basename \"$ID\")\" = \"$ID\" ] || exit 1","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep ids as bare slugs (letters, digits, dashes); never build them by joining paths.","Put path structure only in --output, whose last component must equal the id.","Sanitize inputs from spreadsheets/CSVs that may carry slashes."],"tags":["cli","validation","path-traversal"],"backgroundTag":"path-traversal-blocked","analyzedSha":"e846e6f4b4405e33bd6a9aaf949a482ce34cb6d8","analyzedAt":"2026-09-13T03:07:16.451Z","contentChangedAt":"2026-09-13T03:07:16.451Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}