Skip to content

Commit 39979e6

Browse files
committed
chore(cli): drop redundant tempfile dev-dependency entry
`tempfile` was promoted from `[dev-dependencies]` to `[dependencies]` once the cp-style single-file download path started using `TempDir::new_in` from production code. The original `[dev-dependencies]` line stayed behind by accident — entries under `[dependencies]` are already available to test compilation, so the second declaration is dead weight. Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
1 parent 7b69bcc commit 39979e6

2 files changed

Lines changed: 30 additions & 31 deletions

File tree

crates/openshell-cli/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,5 @@ rcgen = { version = "0.13", features = ["crypto", "pem"] }
9292
reqwest = { workspace = true }
9393
serde_json = { workspace = true }
9494
temp-env = "0.3"
95-
tempfile = "3"
9695
tokio-stream = { workspace = true }
9796
url = { workspace = true }

crates/openshell-cli/src/ssh.rs

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,7 @@ fn split_sandbox_path(path: &str) -> (&str, &str) {
609609
/// checks on sandbox-side source paths in download flows.
610610
const SANDBOX_WORKSPACE_ROOT: &str = "/sandbox";
611611

612-
/// Lexically normalise a POSIX-style absolute path by resolving `.` and `..`
612+
/// Lexically clean a POSIX-style absolute path by resolving `.` and `..`
613613
/// components, collapsing repeated separators, and stripping any trailing
614614
/// slash. Returns `None` if the input is empty or relative — the caller is
615615
/// expected to reject those before reaching this helper.
@@ -619,7 +619,7 @@ const SANDBOX_WORKSPACE_ROOT: &str = "/sandbox";
619619
/// client-side to refuse obvious path-traversal attempts before issuing the
620620
/// SSH command. Symlink-based escapes inside the sandbox must be addressed
621621
/// server-side.
622-
fn lexical_normalise_absolute_path(path: &str) -> Option<String> {
622+
fn lexical_clean_absolute_path(path: &str) -> Option<String> {
623623
if !path.starts_with('/') {
624624
return None;
625625
}
@@ -647,26 +647,26 @@ fn lexical_normalise_absolute_path(path: &str) -> Option<String> {
647647
/// Validate that a sandbox-side source path passed to `sandbox download`
648648
/// resolves under the sandbox writable root.
649649
///
650-
/// Returns the normalised, traversal-resolved path on success. Refuses any
650+
/// Returns the cleaned, traversal-resolved path on success. Refuses any
651651
/// path that lexically escapes `/sandbox` (e.g. `/etc/passwd`,
652652
/// `/sandbox/../etc/passwd`) with a user-facing error.
653653
///
654654
/// This is a lexical guard only — it does not follow symlinks. Call
655-
/// `canonicalize_sandbox_source_path` after this on any path that will be
656-
/// passed to a subsequent SSH I/O operation, so a symlink such as
655+
/// `resolve_sandbox_source_path` after this on any path that will be passed
656+
/// to a subsequent SSH I/O operation, so a symlink such as
657657
/// `/sandbox/etc-link -> /etc` cannot leak files outside the workspace.
658658
fn validate_sandbox_source_path(path: &str) -> Result<String> {
659659
if path.is_empty() {
660660
return Err(miette::miette!("sandbox source path is empty"));
661661
}
662-
let normalised = lexical_normalise_absolute_path(path)
662+
let cleaned = lexical_clean_absolute_path(path)
663663
.ok_or_else(|| miette::miette!("sandbox source path must be absolute (got '{path}')"))?;
664-
if !is_under_sandbox_workspace(&normalised) {
664+
if !is_under_sandbox_workspace(&cleaned) {
665665
return Err(miette::miette!(
666666
"sandbox source path '{path}' is outside the sandbox workspace ({SANDBOX_WORKSPACE_ROOT})"
667667
));
668668
}
669-
Ok(normalised)
669+
Ok(cleaned)
670670
}
671671

672672
/// Pure helper: is `path` equal to `/sandbox` or a descendant of it?
@@ -680,28 +680,28 @@ fn is_under_sandbox_workspace(path: &str) -> bool {
680680
/// The lexical guard in `validate_sandbox_source_path` cannot see symlinks; a
681681
/// path such as `/sandbox/etc-link/passwd` (where `etc-link -> /etc`) clears
682682
/// the lexical check but would still leak `/etc/passwd` once `tar -C` follows
683-
/// the link. Canonicalising on the remote side and re-validating closes that
684-
/// gap. The returned canonical path is what the caller should hand to probe
685-
/// and tar invocations.
686-
async fn canonicalize_sandbox_source_path(
683+
/// the link. Resolving symlinks on the remote side and re-validating closes
684+
/// that gap. The returned fully-resolved path is what the caller should hand
685+
/// to probe and tar invocations.
686+
async fn resolve_sandbox_source_path(
687687
session: &SshSessionConfig,
688688
sandbox_path: &str,
689689
) -> Result<String> {
690-
let canonical_cmd = format!("realpath -e -- {path}", path = shell_escape(sandbox_path));
691-
let canonical = ssh_run_capture_stdout(session, &canonical_cmd)
690+
let resolve_cmd = format!("realpath -e -- {path}", path = shell_escape(sandbox_path));
691+
let resolved = ssh_run_capture_stdout(session, &resolve_cmd)
692692
.await
693-
.wrap_err_with(|| format!("failed to canonicalise sandbox source path '{sandbox_path}'"))?;
694-
if canonical.is_empty() {
693+
.wrap_err_with(|| format!("failed to resolve sandbox source path '{sandbox_path}'"))?;
694+
if resolved.is_empty() {
695695
return Err(miette::miette!(
696696
"sandbox source path '{sandbox_path}' does not exist"
697697
));
698698
}
699-
if !is_under_sandbox_workspace(&canonical) {
699+
if !is_under_sandbox_workspace(&resolved) {
700700
return Err(miette::miette!(
701-
"sandbox source path '{sandbox_path}' resolves to '{canonical}', outside the sandbox workspace ({SANDBOX_WORKSPACE_ROOT})"
701+
"sandbox source path '{sandbox_path}' resolves to '{resolved}', outside the sandbox workspace ({SANDBOX_WORKSPACE_ROOT})"
702702
));
703703
}
704-
Ok(canonical)
704+
Ok(resolved)
705705
}
706706

707707
/// Resolve the host-side target path for a downloaded *file*, following
@@ -934,7 +934,7 @@ pub async fn sandbox_sync_down(
934934
) -> Result<()> {
935935
let sandbox_path = validate_sandbox_source_path(sandbox_path)?;
936936
let session = ssh_session_config(server, name, tls).await?;
937-
let sandbox_path = canonicalize_sandbox_source_path(&session, &sandbox_path).await?;
937+
let sandbox_path = resolve_sandbox_source_path(&session, &sandbox_path).await?;
938938
let kind = probe_sandbox_source_kind(&session, &sandbox_path).await?;
939939

940940
match kind {
@@ -1540,31 +1540,31 @@ mod tests {
15401540
}
15411541

15421542
#[test]
1543-
fn lexical_normalise_resolves_dot_and_dotdot_segments() {
1543+
fn lexical_clean_resolves_dot_and_dotdot_segments() {
15441544
assert_eq!(
1545-
lexical_normalise_absolute_path("/sandbox/./a"),
1545+
lexical_clean_absolute_path("/sandbox/./a"),
15461546
Some("/sandbox/a".to_string())
15471547
);
15481548
assert_eq!(
1549-
lexical_normalise_absolute_path("/sandbox/sub/../a"),
1549+
lexical_clean_absolute_path("/sandbox/sub/../a"),
15501550
Some("/sandbox/a".to_string())
15511551
);
15521552
assert_eq!(
1553-
lexical_normalise_absolute_path("/sandbox/../etc/passwd"),
1553+
lexical_clean_absolute_path("/sandbox/../etc/passwd"),
15541554
Some("/etc/passwd".to_string())
15551555
);
15561556
assert_eq!(
1557-
lexical_normalise_absolute_path("//sandbox///foo//"),
1557+
lexical_clean_absolute_path("//sandbox///foo//"),
15581558
Some("/sandbox/foo".to_string())
15591559
);
1560-
assert_eq!(lexical_normalise_absolute_path("/"), Some("/".to_string()));
1560+
assert_eq!(lexical_clean_absolute_path("/"), Some("/".to_string()));
15611561
}
15621562

15631563
#[test]
1564-
fn lexical_normalise_refuses_relative_paths() {
1565-
assert_eq!(lexical_normalise_absolute_path(""), None);
1566-
assert_eq!(lexical_normalise_absolute_path("sandbox/a"), None);
1567-
assert_eq!(lexical_normalise_absolute_path("./a"), None);
1564+
fn lexical_clean_refuses_relative_paths() {
1565+
assert_eq!(lexical_clean_absolute_path(""), None);
1566+
assert_eq!(lexical_clean_absolute_path("sandbox/a"), None);
1567+
assert_eq!(lexical_clean_absolute_path("./a"), None);
15681568
}
15691569

15701570
#[test]

0 commit comments

Comments
 (0)