Repository navigation
Fix literal path handling in volume copies - #161
Conversation
tavateva
left a comment
There was a problem hiding this comment.
APPROVE at 5f5b6d23dfc90229bd33c47e77dba37b887b4c8d.
This fixes #154 at the right layer.
runCommandnow callsexecFile('docker', args), so no host shell parses request data.- Each container
sh -creceives a fixed script:mkdir -p "$1" && cp -r "$2" "$3",rm -rf "$1" && cp -r "$2" "$1"(with optionalchown "$3" "$1"), orrm -rf "$1"/*. The paths follow as positional parameters after ash$0. - Container paths are always absolute under
/host/or/volume/, so a name beginning with-can't be read as an option. - The duplicated private ingress builder is removed, and so is the whitespace normalisation that silently collapsed repeated spaces.
- Cleanup keeps its semantics: the glob stays outside the quotes and hidden entries survive.
reject(stderr || error.message)keeps diagnostics such asspawn docker ENOENT.- Every caller of the three builders is updated, so no string-command path remains.
Verification at the head:
-
npm run test:release: 150 passed, 0 failed.npm run typecheck: clean. ESLint: clean on the changed files; the one warning is a pre-existing directive in an untouched file. -
Independent round trip. No Docker daemon is available here, so I put a
dockershim on PATH. It parses the real-vmappings, maps/hostand/volumeonto temp directories, and runs the generatedsh -cscript with the generated positional arguments. Driving the realcopyFileToVolumeCommand,copyFileToHostCommandanddeleteFilesFromVolumeFolderwith:- the host folder
host $(echo PWNED) it's; - the file
Bob's stack.tif; - the file
a "quoted" $HOME `id` two spaces.tif
both directions copied the exact bytes, with stale destinations replaced. Nothing was expanded or executed, and cleanup left
.keepin place. These are the cases that failed on58b29a2. - the host folder
-
Validate release inputsand the ubuntu/macOS memory collectors are green.coverageand the Windows collectors were still queued when I posted, during GitHub's ongoing Actions incident. I did not exercise Windows Docker Desktop. On Windows, libuv resolvesdockertodocker.exewithout a shell, and Windows filenames can't contain", so the route-fixture coverage is the relevant evidence.
Residual (outside #154, no change requested): a host folder whose name contains : still breaks the -v src:/host spec, as it did before. POSIX allows that character; Windows forbids it. --mount would trade that for comma parsing, so it's a separate decision if it ever matters.
The volume server now preserves paths containing apostrophes, quotes, dollar signs, backticks, and repeated spaces in both copy directions. Docker receives an argument array, and the container runs a fixed script with quoted positional parameters. A filename such as
Bob's stack.tifis treated as a filename throughout the copy.Fixes #154. This is a standalone PR against
main, independent of the status-presentation stacks. Existing callers and JSON request schemas are unchanged.Shared-basis audit
volume-copy.mjsnow owns both directions through its shared Docker-argument builder. The private ingress builder involume-server-script.mjsand both interpolated shell-command strings are removed, including whitespace normalization that altered valid names. Host-native dirname/basename parsing and POSIX container paths retain their existing roles; path strings become positional data only at the Docker boundary.runCommandremains the sole Docker execution facility and now callsexecFile('docker', args). Its cleanup callers migrate to the same argument representation, so no legacy shell runner or competing command form remains. The container shell parses only fixed operation scripts; request paths never enter those scripts.volume-cleanup.mjsstill owns cleanup scope, including hidden-entry preservation and whole-volume retention ofmain-statistics. Host export still replaces the destination before copying, and only private-report exports apply host-derived UID:GID ownership. Copy ordering, concurrency, HTTP status/schema, and client behavior are unchanged. Launch failures with empty stderr retain the native error message (for example, missing Docker), preserving actionable diagnostics after the runner change. No dependency, validation policy, or retry mechanism is added.Validation
git diff --checkpass.