diff --git a/README.md b/README.md index 934b67b..02d5f5a 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,11 @@ Arguments: - `args`: List of command-line arguments like argv in execve (default: auto-generated from `flags`) - Example: `[ "--silent" "--connect-timeout" "30" ]` - If provided, overrides automatic generation from `flags` + - Will be escaped +- `unquotedArgs`: List of command-line arguments (unescaped) + - WARNING: These are not escaped and can therefore be interpreted as shell commands + - Example: `[ "--silet" "--conect-timeout" "30" ]` + - If provided, overrides `args` and `flags` - `preHook`: Shell script executed before the command (default: `""`) - `passthru`: Additional attributes for the derivation's passthru (default: `{}`) - `aliases`: List of additional symlink names for the executable (default: `[]`) diff --git a/checks/args-direct.nix b/checks/args-direct.nix index 35ecab3..3f9c277 100644 --- a/checks/args-direct.nix +++ b/checks/args-direct.nix @@ -4,7 +4,7 @@ }: let - wrappedPackage = self.lib.wrapPackage { + escapedArgsPackage = self.lib.wrapPackage { inherit pkgs; package = pkgs.hello; args = [ @@ -13,17 +13,49 @@ let "--verbose" ]; }; + unescapedArgsPackage = self.lib.wrapPackage { + inherit pkgs; + package = pkgs.hello; + unquotedArgs = [ + "--greeting" + "hi" + "--verbose" + ]; + }; in pkgs.runCommand "args-direct-test" { } '' echo "Testing direct args list..." - wrapperScript="${wrappedPackage}/bin/hello" + wrapperScript="${escapedArgsPackage}/bin/hello" + echo "Check escaped arguments" if [ ! -f "$wrapperScript" ]; then echo "FAIL: Wrapper script not found" exit 1 fi + if ! grep -q -- '"--greeting"' "$wrapperScript"; then + echo "FAIL: escaped --greeting not found" + cat "$wrapperScript" + exit 1 + fi + + if ! grep -q '"hi"' "$wrapperScript"; then + echo "FAIL: escaped 'hi' not found" + cat "$wrapperScript" + exit 1 + fi + + if ! grep -q -- '"--verbose"' "$wrapperScript"; then + echo "FAIL: escaped --verbose not found" + cat "$wrapperScript" + exit 1 + fi + echo "SUCCESS: escaped arguments passed" + + wrapperScript="${unescapedArgsPackage}/bin/hello" + echo "Check unescaped arguments" + # check that arguments are present if ! grep -q -- "--greeting" "$wrapperScript"; then echo "FAIL: --greeting not found" cat "$wrapperScript" @@ -36,12 +68,34 @@ pkgs.runCommand "args-direct-test" { } '' exit 1 fi + # check hat arguments are not escaped if ! grep -q -- "--verbose" "$wrapperScript"; then echo "FAIL: --verbose not found" cat "$wrapperScript" exit 1 fi + if grep -q -- '"--greeting"' "$wrapperScript"; then + echo "FAIL: escaped --greeting found (should be unescaped)" + cat "$wrapperScript" + exit 1 + fi + + if grep -q '"hi"' "$wrapperScript"; then + echo "FAIL: escaped 'hi' found (should be unescaped)" + cat "$wrapperScript" + exit 1 + fi + + + if grep -q -- '"--verbose"' "$wrapperScript"; then + echo "FAIL: escaped --verbose found (should be unescaped)" + cat "$wrapperScript" + exit 1 + fi + echo "SUCCESS: escaped arguments passed" + + echo "" echo "SUCCESS: Direct args test passed" touch $out '' diff --git a/lib/default.nix b/lib/default.nix index 52ecc71..8a73fc7 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -419,6 +419,7 @@ let flagSeparator ? " ", # " " for "--flag value" or "=" for "--flag=value" args ? generateArgsFromFlags flags flagSeparator, + unquotedArgs ? [ ], preHook ? "", passthru ? { }, aliases ? [ ], @@ -457,10 +458,13 @@ let # Generate flag arguments with proper line breaks and indentation flagsString = - if args == [ ] then + if args == [ ] && unquotedArgs == [ ] then "" else - " \\\n " + lib.concatStringsSep " \\\n " (map wrapperLib.escapeShellArgWithEnv args); + " \\\n " + + lib.concatStringsSep " \\\n " ( + if unquotedArgs != [ ] then unquotedArgs else map wrapperLib.escapeShellArgWithEnv args + ); finalWrapper = wrapper { inherit