@@ -270,15 +270,25 @@ func (d *Devbox) RunScript(ctx context.Context, envOpts devopt.EnvOptions, cmdNa
270270// better alternative since devbox run and devbox shell are not the same.
271271env ["DEVBOX_SHELL_ENABLED" ] = "1"
272272
273- // wrap the arg in double-quotes, and escape any double-quotes inside it
273+ // wrap the arg in double-quotes, and escape any double-quotes inside it.
274+ //
275+ // TODO(gcurtis): this breaks quote-removal in parameter expansion,
276+ // command substitution, and arithmetic expansion:
277+ //
278+ // $ unset x
279+ // $ echo ${x:-"my file"}
280+ // my file
281+ // $ devbox run -- echo '${x:-"my file"}'
282+ // "my file"
274283for idx , arg := range cmdArgs {
275284cmdArgs [idx ] = strconv .Quote (arg )
276285}
277286
278287var cmdWithArgs []string
279288if _ , ok := d .cfg .Scripts ()[cmdName ]; ok {
280289// it's a script, so replace the command with the script file's path.
281- cmdWithArgs = append ([]string {shellgen .ScriptPath (d .ProjectDir (), cmdName )}, cmdArgs ... )
290+ script := shellgen .ScriptPath (d .ProjectDir (), cmdName )
291+ cmdWithArgs = append ([]string {strconv .Quote (script )}, cmdArgs ... )
282292} else {
283293// Arbitrary commands should also run the hooks, so we write them to a file as well. However, if the
284294// command args include env variable evaluations, then they'll be evaluated _before_ the hooks run,
@@ -293,7 +303,8 @@ func (d *Devbox) RunScript(ctx context.Context, envOpts devopt.EnvOptions, cmdNa
293303if err != nil {
294304return err
295305}
296- cmdWithArgs = []string {shellgen .ScriptPath (d .ProjectDir (), arbitraryCmdFilename )}
306+ script := shellgen .ScriptPath (d .ProjectDir (), arbitraryCmdFilename )
307+ cmdWithArgs = []string {strconv .Quote (script )}
297308env ["DEVBOX_RUN_CMD" ] = strings .Join (append ([]string {cmdName }, cmdArgs ... ), " " )
298309}
299310
0 commit comments