-
Notifications
You must be signed in to change notification settings - Fork 3
sdk run: quote argv elements instead of joining them raw #201
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e7806cb
c785a69
4d54dfa
a0c9132
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -52,6 +52,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | |
| is skipped with nothing to say rather than asserting a version it never read. | ||
|
|
||
| ### Breaking | ||
| - **`sdk run` passes its argv through literally; the container shell no longer | ||
| re-splits or expands it.** Anything passing a `$VAR`, a glob, or a `&&` chain | ||
| as a single argument and counting on the container shell to interpret it now | ||
| gets that string through as one command word: `avocado sdk run -- 'ls /foo && | ||
| ls /bar'` no longer runs two commands, and `avocado sdk run -- echo '$HOME'` | ||
| prints a literal `$HOME`. Ask for a shell explicitly instead — `avocado sdk | ||
| run -- bash -lc 'ls /foo && ls /bar'` — which is the form the flags already | ||
| implied and which only works correctly after this change. | ||
|
|
||
| This one breaks silently at runtime: there is no error and no warning, so a | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "no error, no warning" doesn't hold for That's the exact Only the expansion cases ( Separately, the audit list ( |
||
| pinned-version bump in CI will not fail the build, it will just run a | ||
| different command. Audit any job that shells through `sdk run` before | ||
| upgrading. | ||
|
|
||
| **What it fixes.** The arguments after `--` were spliced into the container's | ||
| script with a bare `join(" ")`, so the shell inside re-parsed them. `avocado | ||
| sdk run -- bash -lc 'U=/opt/x; ls $U'` arrived as `bash -lc U=/opt/x; ls $U`, | ||
| which the shell read as two commands and whose `$U` the *outer* shell expanded | ||
| to nothing — printing plausible output for a different directory rather than | ||
| failing. Each element is quoted now, so argv is argv, matching `docker run` | ||
| and `kubectl exec`. | ||
| - **`is_version_compatible` returns `Option<bool>` instead of `bool`.** Only | ||
| affects consumers of the `avocado_cli` lib target. `None` means the remote | ||
| version could not be read at all, which the old `bool` could not express - | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| //! Shell quoting helpers. | ||
| //! | ||
| //! Several commands splice values into a shell script that runs inside the SDK | ||
| //! container. Anything user-supplied has to be quoted on the way in or the | ||
| //! container shell re-splits and expands it. | ||
|
|
||
| /// Shell escape a string for safe use in a shell command | ||
| pub(crate) fn shell_escape(s: &str) -> String { | ||
| format!("'{}'", s.replace('\'', "'\\''")) | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::*; | ||
|
|
||
| #[test] | ||
| fn test_shell_escape_simple() { | ||
| assert_eq!(shell_escape("hello"), "'hello'"); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_shell_escape_with_spaces() { | ||
| assert_eq!(shell_escape("hello world"), "'hello world'"); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_shell_escape_with_quotes() { | ||
| assert_eq!(shell_escape("it's"), "'it'\\''s'"); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_shell_escape_complex() { | ||
| assert_eq!( | ||
| shell_escape("echo 'hello' && rm -rf /"), | ||
| "'echo '\\''hello'\\'' && rm -rf /'" | ||
| ); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Published HIL doc teaches the pattern this breaks.
docs/src/docs-guides/hardware-in-the-loop.md:140-146(peridio/docs) instructsavocado sdk run cd /opt/_avocado \&\& mkdir -p ./qemux86-64/extensions/my-app/usr \&\& echo "hello from host" \> ./qemux86-64/extensions/my-app/usr/hello.txt, followed by an "Escaping SDK run commands" callout stating that&&and>are escaped precisely so they "reach the container's shell unchanged." That is exactly the contract this PR retires, and the vendor's own guide isn't in the audit list this entry asks users to check.Replayed the documented argv against both code paths:
cd <dir> && mkdir -p ./ext/usr && echo hello from host > ./ext/usr/hello.txt-> exit 0, file created.bash: line 1: cd: too many arguments, exit 2, nothing created.The
echo/redirect half in isolation is worse: it exits 0, printshello from host > ./out.txtto stdout, and writes nothing - so someone following this guide sees a success and a missing file. Worth a companion docs fix landing with this change, not after.