Skip to content

Instantly share code, notes, and snippets.

@albertorb
Created March 26, 2026 14:16
Show Gist options
  • Select an option

  • Save albertorb/b2991be56e616fe0379907f6474e7e62 to your computer and use it in GitHub Desktop.

Select an option

Save albertorb/b2991be56e616fe0379907f6474e7e62 to your computer and use it in GitHub Desktop.
Helper script to check if you have been compromised due to litellm 1.82.7 and 1.82.8.
#!/usr/bin/env bash
set -u
# ===== CONFIG =====
TARGET_VERSIONS=("1.82.7" "1.82.8")
TARGET_VERSIONS_REGEX='1\.(82\.7|82\.8)'
TARGET_VERSIONS_LABEL="1.82.7 / 1.82.8"
REPO_PATH="${1:-}"
if [ -z "$REPO_PATH" ]; then
echo -n "Enter the repository path to scan (e.g., ~/repos): "
read -r REPO_PATH
fi
# Expand tilde if present
REPO_PATH="${REPO_PATH/#\~/$HOME}"
if [ ! -d "$REPO_PATH" ]; then
echo "Error: Directory '$REPO_PATH' does not exist."
exit 1
fi
if command -v rg >/dev/null 2>&1; then
GREP_CMD="rg"
else
GREP_CMD="grep"
fi
FOUND_ANY=0
FOUND_GENERIC_PTH=0
print_header() {
echo "========================================"
echo " LiteLLM ${TARGET_VERSIONS_LABEL} Compromise Check Script"
echo "========================================"
echo "Scanning path: $REPO_PATH"
echo "Date: $(date '+%Y-%m-%d %H:%M:%S %Z')"
echo ""
}
print_step() {
local step="$1"
local title="$2"
echo "---- [${step}] ${title} ----"
}
print_none_found() {
echo "No findings."
}
mark_found() {
FOUND_ANY=1
}
safe_find() {
# shellcheck disable=SC2048,SC2086
find $* 2>/dev/null
}
collect_python_bins() {
{
command -v python 2>/dev/null || true
command -v python3 2>/dev/null || true
safe_find "$REPO_PATH" -type f \( -path "*/.venv/bin/python" -o -path "*/venv/bin/python" -o -path "*/.venv/bin/python3" -o -path "*/venv/bin/python3" \)
safe_find "$HOME" -maxdepth 4 -type f \( -path "*/.venv/bin/python" -o -path "*/.virtualenvs/*/bin/python" -o -path "*/.pyenv/versions/*/bin/python" \)
} | awk 'NF' | sort -u
}
collect_site_packages_dirs() {
{
safe_find "$REPO_PATH" -type d -name site-packages
safe_find "$HOME" -maxdepth 6 -type d -name site-packages
[ -d "/usr/local/lib" ] && safe_find "/usr/local/lib" -maxdepth 4 -type d -name site-packages
[ -d "/opt/homebrew/lib" ] && safe_find "/opt/homebrew/lib" -maxdepth 4 -type d -name site-packages
} | awk 'NF' | sort -u
}
print_header
# ===== 1. Check installed versions =====
print_step 1 "Checking installed litellm versions"
PY_BINS="$(collect_python_bins)"
if [ -z "$PY_BINS" ]; then
echo "No Python interpreters discovered to inspect."
else
echo "Inspecting litellm via discovered Python interpreters..."
while IFS= read -r pybin; do
[ -x "$pybin" ] || continue
echo "- Checking: $pybin"
out="$($pybin -m pip show litellm 2>/dev/null | awk -F': ' '/^Name:|^Version:|^Location:/{print $0}')"
if [ -n "$out" ]; then
echo "$out"
if echo "$out" | grep -Eq "Version: (${TARGET_VERSIONS_REGEX})"; then
mark_found
fi
else
echo " litellm not installed in this interpreter"
fi
done <<< "$PY_BINS"
fi
echo ""
echo "Scanning site-packages METADATA for versions: ${TARGET_VERSIONS_LABEL}..."
SITE_PKGS="$(collect_site_packages_dirs)"
if [ -z "$SITE_PKGS" ]; then
echo "No site-packages directories discovered."
else
METADATA_HITS=0
while IFS= read -r sp; do
[ -d "$sp" ] || continue
hits="$(safe_find "$sp" -type f -path "*/litellm-*.dist-info/METADATA" | xargs -I{} sh -c 'grep -Eq "Version: ('"${TARGET_VERSIONS_REGEX}"')" "{}" && echo "{}"' 2>/dev/null)"
if [ -n "$hits" ]; then
echo "$hits"
METADATA_HITS=1
mark_found
fi
done <<< "$SITE_PKGS"
[ "$METADATA_HITS" -eq 0 ] && print_none_found
fi
echo ""
# ===== 2. Check for malicious .pth file =====
print_step 2 "Searching for litellm_init.pth"
PTH_HITS="$(
{
safe_find "$REPO_PATH" -type f -name "litellm_init.pth"
safe_find "$HOME" -maxdepth 7 -type f -name "litellm_init.pth"
[ -d "/usr/local/lib" ] && safe_find "/usr/local/lib" -maxdepth 6 -type f -name "litellm_init.pth"
[ -d "/opt/homebrew/lib" ] && safe_find "/opt/homebrew/lib" -maxdepth 6 -type f -name "litellm_init.pth"
} | sort -u
)"
if [ -n "$PTH_HITS" ]; then
echo "$PTH_HITS"
mark_found
echo ""
echo "Inspecting litellm_init.pth contents:"
while IFS= read -r pth; do
[ -f "$pth" ] || continue
echo "----- $pth -----"
sed -n '1,120p' "$pth"
done <<< "$PTH_HITS"
else
print_none_found
fi
echo ""
# ===== 3. Scan dependency files =====
print_step 3 "Scanning dependency files"
echo "Pinned to compromised versions (${TARGET_VERSIONS_LABEL}):"
if [ "$GREP_CMD" = "rg" ]; then
PINNED="$($GREP_CMD -l --hidden --glob '*.txt' --glob '*.toml' --glob '*.cfg' --glob '*.ini' --glob '!**/.venv/**' --glob '!**/venv/**' --glob '!**/site-packages/**' 'litellm\s*==\s*1\.(82\.7|82\.8)' "$REPO_PATH" 2>/dev/null)"
else
PINNED="$(grep -r -l --include='*.txt' --include='*.toml' --include='*.cfg' --include='*.ini' -E 'litellm==1\.(82\.7|82\.8)' "$REPO_PATH" 2>/dev/null)"
fi
if [ -n "$PINNED" ]; then
echo "$PINNED"
mark_found
else
print_none_found
fi
echo ""
echo "Any litellm usage (dependency manifests only):"
if [ "$GREP_CMD" = "rg" ]; then
ANY_USAGE="$($GREP_CMD -l --hidden --glob '*.txt' --glob '*.toml' --glob '*.cfg' --glob '*.ini' --glob '!**/.venv/**' --glob '!**/venv/**' --glob '!**/site-packages/**' 'litellm' "$REPO_PATH" 2>/dev/null)"
else
ANY_USAGE="$(grep -r -l --include='*.txt' --include='*.toml' --include='*.cfg' --include='*.ini' 'litellm' "$REPO_PATH" 2>/dev/null)"
fi
if [ -n "$ANY_USAGE" ]; then
echo "$ANY_USAGE"
else
print_none_found
fi
echo ""
# ===== 4. Scan .pth files for suspicious patterns =====
print_step 4 "Scanning .pth files for incident indicators"
if [ "$GREP_CMD" = "rg" ]; then
SUSP_PTH="$(
safe_find "$REPO_PATH" -type f -name '*.pth'
safe_find "$HOME" -maxdepth 7 -type f -name '*.pth'
[ -d "/usr/local/lib" ] && safe_find "/usr/local/lib" -maxdepth 6 -type f -name '*.pth'
[ -d "/opt/homebrew/lib" ] && safe_find "/opt/homebrew/lib" -maxdepth 6 -type f -name '*.pth'
)"
if [ -n "$SUSP_PTH" ]; then
IOC_MATCHES="$(echo "$SUSP_PTH" | xargs -I{} rg --with-filename -n 'litellm_init|litellm\.cloud|models\.litellm\.cloud|tpcp\.tar\.gz|/tmp/tpcp' {} 2>/dev/null)"
if [ -n "$IOC_MATCHES" ]; then
echo "$IOC_MATCHES"
mark_found
else
echo "No incident-specific indicators in .pth files."
fi
echo ""
echo "Generic risky patterns in .pth files (manual review):"
GENERIC_PTH_MATCHES="$(echo "$SUSP_PTH" | xargs -I{} rg --with-filename -n 'base64|subprocess|Popen|exec\(|requests\.|urllib|socket' {} 2>/dev/null)"
if [ -n "$GENERIC_PTH_MATCHES" ]; then
echo "$GENERIC_PTH_MATCHES"
FOUND_GENERIC_PTH=1
else
print_none_found
fi
else
print_none_found
fi
else
print_none_found
fi
echo ""
# ===== 5. Check potential exfiltration =====
print_step 5 "Checking shell history and DNS indicators"
HISTORY_HITS="$(grep -h 'litellm\.cloud\|models\.litellm\.cloud' "$HOME/.bash_history" "$HOME/.zsh_history" "$HOME/.sh_history" 2>/dev/null)"
if [ -n "$HISTORY_HITS" ]; then
echo "$HISTORY_HITS"
mark_found
else
echo "No suspicious shell history hits for litellm.cloud."
fi
echo ""
echo "Checking DNS resolution for models.litellm.cloud:"
if command -v host >/dev/null 2>&1; then
host models.litellm.cloud 2>/dev/null || echo "Domain not resolving"
elif command -v nslookup >/dev/null 2>&1; then
nslookup models.litellm.cloud 2>/dev/null || echo "Domain not resolving"
else
echo "Neither 'host' nor 'nslookup' is available."
fi
echo ""
# ===== 6. Check temp artifacts =====
print_step 6 "Checking /tmp for exfiltration artifacts"
TMP_HITS="$(
{
safe_find /tmp -type f -name 'tpcp.tar.gz'
safe_find /tmp -type f -name 'tpcp*'
} | sort -u
)"
if [ -n "$TMP_HITS" ]; then
echo "$TMP_HITS"
mark_found
else
print_none_found
fi
echo ""
echo "========================================"
if [ "$FOUND_ANY" -eq 1 ]; then
echo "Potential indicators found."
else
echo "No indicators found by this script."
fi
if [ "$FOUND_GENERIC_PTH" -eq 1 ]; then
echo "Generic .pth patterns were found (not specific to this incident); review step [4]."
fi
echo ""
echo "If litellm==1.82.7 or litellm==1.82.8 or litellm_init.pth is found:"
echo "1. Immediately uninstall: pip uninstall litellm -y"
echo "2. Rotate ALL secrets (SSH, cloud creds, API keys, etc.)"
echo "3. Treat the system as COMPROMISED"
echo "4. Rebuild affected environments from clean sources"
echo "========================================"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment