Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions e2e/cli/test_use
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ mise use --pin dummy@1
assert "cat mise.toml" '[tools]
dummy = "1.0.0"'

assert_fail "mise use dummy@--version" "must not start with '-'"
assert "cat mise.toml" '[tools]
dummy = "1.0.0"'

MISE_PIN=1 mise use --fuzzy dummy@1
assert "cat mise.toml" '[tools]
dummy = "1"'
Expand Down
28 changes: 24 additions & 4 deletions src/toolset/tool_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,11 +413,15 @@ impl ToolRequest {
/// semver ranges like `>=20 <21 || >=22` or `^1.0.0`, dates, channel names,
/// `lts/hydrogen`, etc.) continues to work — those characters are only
/// dangerous in *unquoted* shell context, which cannot occur without one of
/// the rejected expansion characters appearing first.
/// the rejected expansion characters appearing first. Leading dashes are also
/// rejected so backend install tools cannot mistake a version for a CLI flag.
fn validate_version_string(s: &str) -> Result<()> {
if s.is_empty() {
return Ok(());
}
if s.starts_with('-') {
bail!("invalid tool version {s:?}: must not start with '-'");
}
if s.contains("..") {
bail!("invalid tool version {s:?}: contains path-traversal sequence");
}
Expand All @@ -429,12 +433,16 @@ fn validate_version_string(s: &str) -> Result<()> {

/// Validate `ref:`/`branch:`/`tag:`/`rev:` values. Same character rules as
/// version strings: branch/tag names already use the same broad vocabulary
/// (`/`, `+`, `-`, etc.), and only the shell-quote-breaking characters need
/// rejection. Kept as a separate function for distinct error messages.
/// (`/`, `+`, `-`, etc.), so only shell-quote-breaking characters and leading
/// dashes need rejection. Kept as a separate function for distinct error
/// messages.
fn validate_ref_string(s: &str) -> Result<()> {
if s.is_empty() {
return Ok(());
}
if s.starts_with('-') {
bail!("invalid tool ref {s:?}: must not start with '-'");
}
if s.contains("..") {
bail!("invalid tool ref {s:?}: contains path-traversal sequence");
}
Expand Down Expand Up @@ -612,6 +620,9 @@ mod tests {
"1.0\"x",
"1.0'x",
"1.0\\x",
// backend commands could parse leading dashes as flags
"--version",
"-v",
// control characters / newline splitting
"1.0\nrm",
"1.0\rrm",
Expand All @@ -637,7 +648,16 @@ mod tests {

#[test]
fn test_validate_ref_string_rejects_metacharacters() {
for v in ["a$(id)", "a..b", "a`b`", "a\"b", "a'b", "a\\b"] {
for v in [
"a$(id)",
"a..b",
"a`b`",
"a\"b",
"a'b",
"a\\b",
"--version",
"-v",
] {
assert!(
validate_ref_string(v).is_err(),
"expected ref {v:?} to be rejected"
Expand Down
Loading