Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 56a2dc372a | |||
| 59320c3bc0 |
Generated
+3
-3
@@ -2412,7 +2412,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "socktop"
|
||||
version = "1.60.1"
|
||||
version = "1.60.2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"assert_cmd",
|
||||
@@ -2432,7 +2432,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "socktop_agent"
|
||||
version = "1.60.1"
|
||||
version = "1.60.2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"assert_cmd",
|
||||
@@ -2464,7 +2464,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "socktop_connector"
|
||||
version = "1.60.1"
|
||||
version = "1.60.2"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"futures-util",
|
||||
|
||||
+22
-2
@@ -124,6 +124,15 @@ pub(crate) fn parse_args<I: IntoIterator<Item = String>>(args: I) -> Result<Pars
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// An unrecognized option must never fall through to the
|
||||
// positional URL slot: an older binary handed a newer flag
|
||||
// would otherwise "connect" to the flag text — and offer to
|
||||
// save it over a named profile's URL.
|
||||
if arg.starts_with('-') {
|
||||
return Err(format!(
|
||||
"Unknown option '{arg}'. Usage: {prog} [--tls-ca CERT_PEM|-t CERT_PEM] [--verify-hostname] [--profile NAME|-P NAME] [--save] [--demo] [--compact] [--no-kill] [ws://HOST:PORT/ws]"
|
||||
));
|
||||
}
|
||||
if url.is_none() {
|
||||
url = Some(arg);
|
||||
} else {
|
||||
@@ -155,6 +164,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
Ok(v) => v,
|
||||
Err(msg) => {
|
||||
eprintln!("{msg}");
|
||||
// --help produces the bare usage text and exits cleanly; real
|
||||
// parse errors must be visible to scripts and CI as a failure.
|
||||
if !msg.starts_with("Usage:") {
|
||||
std::process::exit(2);
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
@@ -271,7 +285,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
if (1..=names.len()).contains(&idx) {
|
||||
let name = &names[idx - 1];
|
||||
if name == "demo" {
|
||||
return run_demo_mode(parsed.tls_ca.as_deref(), parsed.compact, parsed.no_kill).await;
|
||||
return run_demo_mode(
|
||||
parsed.tls_ca.as_deref(),
|
||||
parsed.compact,
|
||||
parsed.no_kill,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
if let Some(entry) = profiles_mut.profiles.get(name) {
|
||||
(
|
||||
@@ -331,7 +350,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
);
|
||||
eprintln!("If you don't have an agent running, you can try the demo mode.");
|
||||
if prompt_yes_no("Would you like to start the demo mode now? [Y/n]: ") {
|
||||
return run_demo_mode(parsed.tls_ca.as_deref(), parsed.compact, parsed.no_kill).await;
|
||||
return run_demo_mode(parsed.tls_ca.as_deref(), parsed.compact, parsed.no_kill)
|
||||
.await;
|
||||
} else {
|
||||
eprintln!("Aborting. You can run 'socktop --help' for usage information.");
|
||||
return Ok(());
|
||||
|
||||
@@ -156,3 +156,29 @@ fn test_no_kill_env_var_accepted() {
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unknown_option_rejected_not_treated_as_url() {
|
||||
// Regression guard for the socktop.io incident (Aug 2026): socktop 1.60.1
|
||||
// parsed the then-unknown --no-kill flag as the positional websocket URL,
|
||||
// which made it prompt to overwrite the 'local' profile's URL with the
|
||||
// literal string "--no-kill". Unknown options must fail loudly instead of
|
||||
// falling through to the URL slot.
|
||||
let exe = env!("CARGO_BIN_EXE_socktop");
|
||||
let out = Command::new(exe)
|
||||
.args(["--not-a-real-flag", "--dry-run", "ws://127.0.0.1:3000/ws"])
|
||||
.output()
|
||||
.expect("run socktop with unknown flag");
|
||||
assert_eq!(
|
||||
out.status.code(),
|
||||
Some(2),
|
||||
"unknown option should exit 2, got: {:?}\nstderr: {}",
|
||||
out.status.code(),
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
let err = String::from_utf8_lossy(&out.stderr);
|
||||
assert!(
|
||||
err.contains("Unknown option '--not-a-real-flag'"),
|
||||
"stderr should name the rejected option\n{err}"
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user