Repository navigation
fix(plugin): find a shell's -c script after its options and behind env - #40
Merged
Merged
Conversation
A plugin whose command is a POSIX shell gets plugin values in its -c
script through the environment, so a value from the cluster is never read
as shell syntax (SECURITY.md). ExecCommand took the argument right after
the first short option group containing c as the script, and only when the
command itself was one of the five shells, so values were pasted as text
into the script the shell really runs in:
- sh -c -x '...', sh -c -o errexit '...' and sh -c -- '...': a shell reads
options up to the first argument that does not start with - or +, or up
to --, so the script comes after -x, -o errexit or --;
- env bash -c '...' and busybox sh -c '...': the command is not a shell.
shellCode now reads the options as the shells do: groups that start with -
or + (c turns on -c, +c too), o taking the next argument when it ends its
group, -- or a lone - ending the options, and bash's long options. It finds
the shell behind env, whose options it reads as getopt does, and behind
busybox's sh, ash, hush and bash. The script and the options before it get
values through the environment; arguments after the script ($0, $1, ...)
still get them as text. Where the shells read an option differently, or
k10s does not know it (bash's -O, o inside a group, a lone +, other long
options, an env option it does not know), every argument gets the
environment: safe, though a value meant for $1 then arrives as the
variable's name. A Windows build of a shell (bash.exe) counts as the shell.
env -S is not a way to a shell: it builds a command line of its own from a
string and expands ${VAR} in it, so the environment would not keep a value
out of it. It stays a program that reads its own command line, as
python3 -c is, and gets values as text.
SECURITY.md names env and busybox, and puts env -S with python3 -c;
docs/plugins.md says how values reach a -c script.
From the review of p10node#28.
Signed-off-by: Adao Oliveira Jr <junior@users.noreply.github.com>
pierreneter
approved these changes
Nov 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to the review of #28. SECURITY.md says a shell's
-cscript gets plugin values through the environment, butExecCommanddid that only when the script was the argument right after the first short option group containingc, and only when the command itself was the shell. Two kinds of plugin got values pasted into the script as text:sh -c -x '...',sh -c -o errexit '...',sh -c -- '...': a shell reads options up to the first argument that does not start with-or+, so the script comes after-x,-o errexitor--;env bash -c '...',busybox sh -c '...': the command's own name is not a shell.shellCodenow reads the options the way the shells do (POSIXsh -c [options] script [name [args]], plus bash's long options), finds the shell behindenv(its options read as getopt does) andbusybox, and gives values through the environment to the script and the options before it. Arguments after the script ($0,$1, ...) still get them as text, sosh -c '... "$1"' sh $NAMEkeeps working. Where the shells read an option differently, or k10s does not know it (bash's-O,oinside a group, a lone+, other long options, an env option it does not know), every argument gets the environment: safe, though a value meant for$1then arrives as the variable's name.env -Sis not a way to a shell: it builds a command line of its own from a string and expands${VAR}in it, so the environment would not keep a value out of it. It is treated as a program that reads its own command line, likepython3 -c, and SECURITY.md now lists it next topython3 -c. SECURITY.md also namesenvandbusybox, and docs/plugins.md says how values reach a-cscript.Tests:
TestShellCodeMarksWhatTheShellMayRunAsCode(37 command lines), andTestShellOptionsAfterDashCDoNotLetValuesIntoTheScript, which runs sh, bash and env with a value that creates a file if the shell parses it. On main, 4 of its 6 cases fail (sh -c -x,sh -c -o errexit,sh -c --,env sh -c). gofmt, vet andgo test -short ./...pass on Go 1.26.11 and 1.27.4.