Skip to content

feat: Introduce shell metacharacter escaping for exec #491

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

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

servusdei2018
Copy link

In order to mitigate potential security vulnerabilities arising from shell injection attacks, this PR introduces a function to escape shell metacharacters which may be present in command-line arguments.

It's worth noting that two potential vulnerabilities still exist in

cmdline := fmt.Sprintf("%v setup %v %v\n", o.runtime, o.runtimeArgs, toolkitDir)
//nolint:gosec // TODO: Can we harden this so that there is less risk of command injection
cmd := exec.Command("sh", "-c", cmdline)
and
cmdline := fmt.Sprintf("%v cleanup %v %v\n", o.runtime, o.runtimeArgs, toolkitDir)
//nolint:gosec // TODO: Can we harden this so that there is less risk of command injection
cmd := exec.Command("sh", "-c", cmdline)
where the string o.runtimeArgs is directly interpolated into cmdline, leaving it susceptible to injection attacks. To address this, a more comprehensive solution would involve reimplementing o.runtimeArgs as []string, allowing for proper sanitization using the introduced oci.Escape() function; however, this likely involves a breaking change.

@servusdei2018
Copy link
Author

cc @elezar

Copy link
Member

@elezar elezar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My one question would be whether the logic that we're implementing here exists in some third-pary package somewhere. I'm sure that runc for example needs to also check the arguments that are passed to its hooks.

@servusdei2018
Copy link
Author

servusdei2018 commented Oct 13, 2024

Hmm I believe I did look at runc and couldn't find the exact logic they used. I also looked at Docker and they use shellescape internally.

@ArangoGutierrez
Copy link
Collaborator

Hey @servusdei2018, let's revise this valuable contribution. Recently, we have done a lot of hardening work, so it's worth revisiting your contribution, starting with a rebase

Copilot

This comment was marked as outdated.

Copy link

copy-pr-bot bot commented Jul 11, 2025

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@servusdei2018
Copy link
Author

Rebased @ArangoGutierrez

Copilot

This comment was marked as outdated.

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces functions to escape shell metacharacters in command-line arguments and updates various exec invocations to use these escaping utilities to mitigate injection risks.

  • Adds EscapeArg and Escape functions with accompanying tests.
  • Updates syscall.Exec and exec.Command calls across multiple packages to use escaped arguments.
  • Includes a new test suite for argument escaping behavior.

Reviewed Changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
internal/oci/runtime_syscall_exec.go Implements EscapeArg and Escape; applies escaping in Exec
internal/oci/runtime_syscall_exec_test.go Adds tests for the Escape function
internal/ldconfig/safe-exec_other.go Applies oci.Escape to syscall.Exec in non-Linux SafeExec
internal/ldconfig/safe-exec_linux.go Applies oci.Escape to both branches of SafeExec on Linux
cmd/nvidia-ctk-installer/.../container.go Uses oci.Escape before building exec.Command
cmd/nvidia-container-runtime/main_test.go Updates tests to use oci.EscapeArg and oci.Escape
cmd/nvidia-container-runtime-hook/main.go Applies oci.Escape before syscall.Exec in hook logic
Comments suppressed due to low confidence (3)

internal/oci/runtime_syscall_exec_test.go:42

  • Current tests cover spaces and pipes but miss other metacharacters like backticks, dollar signs, semicolons, quotes, and newlines. Add cases for those to ensure EscapeArg handles all defined metacharacters.
			input:    []string{"echo", "Hello World", "and", "goodbye | cat"},

internal/oci/runtime_syscall_exec.go:65

  • [nitpick] Clarify in the docstring that Escape is intended for commands passed through a shell, not for direct use with syscall.Exec or exec.Command without a shell, to avoid confusion about its purpose.
// Escape escapes shell metacharacters in a slice of command-line arguments

internal/oci/runtime_syscall_exec.go:42

  • Escaping shell metacharacters is unnecessary when calling syscall.Exec directly, as execve bypasses the shell and does not interpret these characters. This transformation will corrupt arguments like spaces or dollar signs. Consider removing Escape here and relying on direct exec without shell escaping.
	args = Escape(args)

Copy link
Collaborator

@ArangoGutierrez ArangoGutierrez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you prepend to the commits that start with nit a prefix [no-relnote] , thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants