@@ -19,16 +19,47 @@ package oci
1919import (
2020 "fmt"
2121 "os"
22+ "regexp"
23+ "strings"
2224 "syscall"
2325)
2426
27+ // shellMetachars represents a set of shell metacharacters that are commonly
28+ // used for shell scripting and may lead to security vulnerabilities if not
29+ // properly handled.
30+ //
31+ // These metacharacters include: | & ; ( ) < > \t \n $ \ `
32+ const shellMetachars = "|&;()<> \t \n $\\ `"
33+
2534type syscallExec struct {}
2635
2736var _ Runtime = (* syscallExec )(nil )
2837
38+ // Escape1 escapes shell metacharacters in a single command-line argument.
39+ func Escape1 (arg string ) string {
40+ if strings .ContainsAny (arg , shellMetachars ) {
41+ // Argument contains shell metacharacters. Double quote the
42+ // argument, and backslash-escape any characters that still have
43+ // meaning inside of double quotes.
44+ e := regexp .MustCompile ("([$`\" \\ \\ ])" ).ReplaceAllString (arg , `\$1` )
45+ return fmt .Sprintf (`"%s"` , e )
46+ }
47+ return arg
48+ }
49+
50+ // Escape escapes shell metacharacters in a slice of command-line arguments
51+ // and returns a new slice containing the escaped arguments.
52+ func Escape (args []string ) []string {
53+ escaped := make ([]string , len (args ))
54+ for i := range args {
55+ escaped [i ] = Escape1 (args [i ])
56+ }
57+ return escaped
58+ }
59+
2960func (r syscallExec ) Exec (args []string ) error {
30- //nolint:gosec // TODO: Can we harden this so that there is less risk of command injection
31- err := syscall .Exec (args [0 ], args , os .Environ ())
61+ args = Escape ( args )
62+ err := syscall .Exec (args [0 ], args , os .Environ ()) //nolint:gosec
3263 if err != nil {
3364 return fmt .Errorf ("could not exec '%v': %v" , args [0 ], err )
3465 }
0 commit comments