T09 · Insecure Skill Coding Practices
- Location
SKILL.md:40- Finding
Predictable Shared Temporary Files Allow Symlink-Based File Clobbering
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 40–53 and 83–89
Vulnerability Type: Unsafe temporary-file handling
Risk Level: MediumVulnerable Code
bash done | sort -u > /tmp/cluster-api-usage.txtbash rg 'v1beta1|v1beta2|v1alpha1' /tmp/cluster-api-usage.txt || echo "No deprecated beta APIs found"bash kubectl get pods --all-namespaces -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.metadata.ownerReferences[0].kind}{"\n"}{end}' > /tmp/all-pods.txt kubectl get pdb --all-namespaces -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.spec.selector.matchLabels}{"\n"}{end}' > /tmp/all-pdbs.txt echo "=== Namespaces with pods but no PDB ===" awk '{print $1}' /tmp/all-pods.txt | sort -u > /tmp/ns-with-pods.txt awk '{print $1}' /tmp/all-pdbs.txt | sort -u > /tmp/ns-with-pdbs.txt comm -23 /tmp/ns-with-pods.txt /tmp/ns-with-pdbs.txtTechnical Analysis
The documented commands create and truncate files with fixed, predictable names under the shared
/tmpdirectory. They do not create a private temporary directory, atomically reserve the files, reject symbolic links, validate file ownership, or establish restrictive permissions.On typical Unix systems,
/tmpis writable by all local users. Although its sticky bit prevents users from deleting files owned by others, it does not prevent an attacker from creating an unused predictable pathname before the victim runs these commands. An attacker can therefore create one of the expected paths as a symbolic link. Shell output redirection follows that link and opens the link target with truncation semantics.The generated files also contain Kubernetes inventory data, including API versions, resource kinds, namespaces, pod names, ownership information, and PodDisruptionBudget selectors. Depending on the operator's
umask, other local users may be able to read this information.Attack Path
- A local attacker predicts that a ...[truncated 1467 chars]
- Remediation
View remediation
Remediation Suggestions
Create an unpredictable, owner-only temporary directory and remove it reliably when execution ends:
bash set -euo pipefail umask 077 TMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/cluster-upgrade-planner.XXXXXXXX")" trap 'rm -rf -- "$TMP_DIR"' EXIT HUP INT TERM API_USAGE="$TMP_DIR/cluster-api-usage.txt" ALL_PODS="$TMP_DIR/all-pods.txt" ALL_PDBS="$TMP_DIR/all-pdbs.txt" NS_WITH_PODS="$TMP_DIR/ns-with-pods.txt" NS_WITH_PDBS="$TMP_DIR/ns-with-pdbs.txt" for api in $(kubectl api-resources --verbs=list -o name); do kubectl get "$api" --all-namespaces \ -o jsonpath='{range .items[*]}{.apiVersion}{"\t"}{.kind}{"\t"}{.metadata.namespace}/{.metadata.name}{"\n"}{end}' \ 2>/dev/null done | sort -u > "$API_USAGE" rg 'v1beta1|v1beta2|v1alpha1' "$API_USAGE" || echo "No deprecated beta APIs found"Apply the same private-directory variables to all pod and PodDisruptionBudget output. Additional hardening should include:
- Avoid running inventory commands as
rootunless strictly required. - Retain
umask 077so temporary output is accessible only to its owner. - Quote every temporary pathname.
- Do not reuse fixed names directly beneath
/tmp. - Ensure cleanup is handled through
trap, including interruption signals. - If persistent reports are required, write them to a user-selected directory with explicit ownership and permission checks rather than to shared temporary storage.
- Avoid running inventory commands as
