Skip to content

Instantly share code, notes, and snippets.

@ceilidhboy
Last active April 18, 2026 11:42
Show Gist options
  • Select an option

  • Save ceilidhboy/8af1b44c737df5ccf5b26066b02d640f to your computer and use it in GitHub Desktop.

Select an option

Save ceilidhboy/8af1b44c737df5ccf5b26066b02d640f to your computer and use it in GitHub Desktop.
BASH script to scan for compromised axios package (v1.14.1)
#!/bin/bash
# by Mike Scott 18-Apr-26
COMPROMISED_AXIOS="1.14.1"
COMPROMISED_AXIOS_OLD="0.30.4"
COMPROMISED_PLAIN_CRYPTO="4.2.1"
RED='\033[0;31m'
GREEN='\033[0;32m'
AMBER='\033[0;33m'
YELLOW='\033[1;33m'
NC='\033[0m'
usage() {
echo "Usage: $0 <directory>"
echo ""
echo "Scan for compromised axios versions in npm/yarn/pnpm lock files."
echo ""
echo "Arguments:"
echo " directory Directory to scan (required)"
echo ""
echo "Options:"
echo " -h, --help Show this help message"
echo ""
echo "Examples:"
echo " $0 ~/projects # Scan ~/projects directory"
echo " $0 /var/www # Scan /var/www directory"
exit 1
}
if [ -z "$1" ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
usage
fi
SCAN_DIR="$1"
if [ ! -d "$SCAN_DIR" ]; then
echo "Error: Directory '$SCAN_DIR' does not exist." >&2
exit 1
fi
echo "=== SCANNING FOR COMPROMISED AXIOS VERSION SUPPLY CHAIN ATTACK ==="
echo "Scanning directory: $SCAN_DIR"
echo ""
AFFECTED_COUNT=0
AT_RISK_COUNT=0
SAFE_COUNT=0
echo "=== FINDING LOCK FILES ==="
LOCK_FILES=$(find "$SCAN_DIR" -maxdepth 6 \( -name "package-lock.json" -o -name "yarn.lock" -o -name "pnpm-lock.yaml" -o -name "bun.lock" \) 2>/dev/null | grep -v node_modules | grep -v .cache | grep -v .Trash | grep -v Library)
LOCK_FILE_COUNT=$(echo "$LOCK_FILES" | wc -l)
echo "Found $LOCK_FILE_COUNT lock files"
echo ""
echo "=== AFFECTED (compromised versions in lock files) ==="
AFFECTED=""
while IFS= read -r lockfile; do
if [ -z "$lockfile" ]; then
continue
fi
dirname=$(dirname "$lockfile")
if [[ "$lockfile" == *"package-lock.json" ]]; then
if grep -q "\"axios\":\[\"${COMPROMISED_AXIOS}\"" "$lockfile" 2>/dev/null; then
echo -e "${RED}AFFECTED:${NC} $lockfile -> axios@${COMPROMISED_AXIOS}"
AFFECTED_COUNT=$((AFFECTED_COUNT + 1))
elif grep -q "\"axios\":\[\"${COMPROMISED_AXIOS_OLD}\"" "$lockfile" 2>/dev/null; then
echo -e "${RED}AFFECTED:${NC} $lockfile -> axios@${COMPROMISED_AXIOS_OLD}"
AFFECTED_COUNT=$((AFFECTED_COUNT + 1))
elif grep -q "\"plain-crypto-js\":\[\"${COMPROMISED_PLAIN_CRYPTO}\"" "$lockfile" 2>/dev/null; then
echo -e "${RED}AFFECTED:${NC} $lockfile -> plain-crypto-js@${COMPROMISED_PLAIN_CRYPTO}"
AFFECTED_COUNT=$((AFFECTED_COUNT + 1))
fi
elif [[ "$lockfile" == *"yarn.lock" ]]; then
if grep -q "axios@${COMPROMISED_AXIOS}:" "$lockfile" 2>/dev/null; then
echo -e "${RED}AFFECTED:${NC} $lockfile -> axios@${COMPROMISED_AXIOS}"
AFFECTED_COUNT=$((AFFECTED_COUNT + 1))
elif grep -q "axios@${COMPROMISED_AXIOS_OLD}:" "$lockfile" 2>/dev/null; then
echo -e "${RED}AFFECTED:${NC} $lockfile -> axios@${COMPROMISED_AXIOS_OLD}"
AFFECTED_COUNT=$((AFFECTED_COUNT + 1))
elif grep -q "plain-crypto-js@${COMPROMISED_PLAIN_CRYPTO}:" "$lockfile" 2>/dev/null; then
echo -e "${RED}AFFECTED:${NC} $lockfile -> plain-crypto-js@${COMPROMISED_PLAIN_CRYPTO}"
AFFECTED_COUNT=$((AFFECTED_COUNT + 1))
fi
elif [[ "$lockfile" == *"pnpm-lock.yaml" ]]; then
if grep -q "axios@${COMPROMISED_AXIOS}:" "$lockfile" 2>/dev/null; then
echo -e "${RED}AFFECTED:${NC} $lockfile -> axios@${COMPROMISED_AXIOS}"
AFFECTED_COUNT=$((AFFECTED_COUNT + 1))
elif grep -q "axios@${COMPROMISED_AXIOS_OLD}:" "$lockfile" 2>/dev/null; then
echo -e "${RED}AFFECTED:${NC} $lockfile -> axios@${COMPROMISED_AXIOS_OLD}"
AFFECTED_COUNT=$((AFFECTED_COUNT + 1))
elif grep -q "plain-crypto-js@${COMPROMISED_PLAIN_CRYPTO}:" "$lockfile" 2>/dev/null; then
echo -e "${RED}AFFECTED:${NC} $lockfile -> plain-crypto-js@${COMPROMISED_PLAIN_CRYPTO}"
AFFECTED_COUNT=$((AFFECTED_COUNT + 1))
fi
elif [[ "$lockfile" == *"bun.lock" ]]; then
if grep -q "axios@${COMPROMISED_AXIOS};" "$lockfile" 2>/dev/null; then
echo -e "${RED}AFFECTED:${NC} $lockfile -> axios@${COMPROMISED_AXIOS}"
AFFECTED_COUNT=$((AFFECTED_COUNT + 1))
elif grep -q "axios@${COMPROMISED_AXIOS_OLD};" "$lockfile" 2>/dev/null; then
echo -e "${RED}AFFECTED:${NC} $lockfile -> axios@${COMPROMISED_AXIOS_OLD}"
AFFECTED_COUNT=$((AFFECTED_COUNT + 1))
elif grep -q "plain-crypto-js@${COMPROMISED_PLAIN_CRYPTO};" "$lockfile" 2>/dev/null; then
echo -e "${RED}AFFECTED:${NC} $lockfile -> plain-crypto-js@${COMPROMISED_PLAIN_CRYPTO}"
AFFECTED_COUNT=$((AFFECTED_COUNT + 1))
fi
fi
done <<< "$LOCK_FILES"
if [ $AFFECTED_COUNT -eq 0 ]; then
echo "None found"
fi
echo ""
echo "=== PACKAGE.JSON DEPS (exact versions matching compromised, and caret ranges) ==="
PACKAGE_JSON_FILES=$(find "$SCAN_DIR" -maxdepth 6 -name "package.json" 2>/dev/null | grep -v node_modules | grep -v .cache | grep -v .Trash | grep -v Library)
while IFS= read -r pkgfile; do
if [ -z "$pkgfile" ]; then
continue
fi
if grep -qE "\"axios\":\s*\"1\.14\.1\"" "$pkgfile" 2>/dev/null; then
VERSION=$(grep -oE "\"axios\":\s*\"[^\"]+\"" "$pkgfile" | head -1)
echo -e "${AMBER}CRITICAL:${NC} $pkgfile -> $VERSION ${AMBER}(exact version - will install compromised 1.14.1)${NC}"
AT_RISK_COUNT=$((AT_RISK_COUNT + 1))
elif grep -qE "\"axios\":\s*\"0\.30\.4\"" "$pkgfile" 2>/dev/null; then
VERSION=$(grep -oE "\"axios\":\s*\"[^\"]+\"" "$pkgfile" | head -1)
echo -e "${AMBER}CRITICAL:${NC} $pkgfile -> $VERSION ${AMBER}(exact version - will install compromised 0.30.4)${NC}"
AT_RISK_COUNT=$((AT_RISK_COUNT + 1))
elif grep -qE "\"plain-crypto-js\":\s*\"4\.2\.1\"" "$pkgfile" 2>/dev/null; then
VERSION=$(grep -oE "\"plain-crypto-js\":\s*\"[^\"]+\"" "$pkgfile" | head -1)
echo -e "${AMBER}CRITICAL:${NC} $pkgfile -> $VERSION ${AMBER}(exact version - will install compromised 4.2.1)${NC}"
AT_RISK_COUNT=$((AT_RISK_COUNT + 1))
elif grep -qE "\"axios\":\s*\"\^1\." "$pkgfile" 2>/dev/null; then
VERSION=$(grep -oE "\"axios\":\s*\"[^\"]+\"" "$pkgfile" | head -1)
echo -e "${GREEN}SAFE:${NC} $pkgfile -> $VERSION ${GREEN}(caret range - resolves to latest 1.x)${NC}"
SAFE_COUNT=$((SAFE_COUNT + 1))
elif grep -qE "\"axios\":\s*\"\^0\." "$pkgfile" 2>/dev/null; then
VERSION=$(grep -oE "\"axios\":\s*\"[^\"]+\"" "$pkgfile" | head -1)
echo -e "${GREEN}SAFE:${NC} $pkgfile -> $VERSION"
SAFE_COUNT=$((SAFE_COUNT + 1))
elif grep -qE "\"plain-crypto-js\":\s*\"\^" "$pkgfile" 2>/dev/null; then
VERSION=$(grep -oE "\"plain-crypto-js\":\s*\"[^\"]+\"" "$pkgfile" | head -1)
echo -e "${GREEN}SAFE:${NC} $pkgfile -> $VERSION"
SAFE_COUNT=$((SAFE_COUNT + 1))
fi
done <<< "$PACKAGE_JSON_FILES"
if [ $AT_RISK_COUNT -eq 0 ] && [ $SAFE_COUNT -eq 0 ]; then
echo "None found"
fi
echo ""
echo "=== SUMMARY ==="
echo "AFFECTED: $AFFECTED_COUNT project(s)"
echo "AT RISK: $AT_RISK_COUNT project(s)"
echo "SAFE: $SAFE_COUNT project(s)"
echo ""
if [ $AFFECTED_COUNT -eq 0 ] && [ $AT_RISK_COUNT -eq 0 ]; then
echo -e "${GREEN}=== CLEAN ===${NC}"
echo -e "${GREEN}No compromised or at-risk projects found.${NC}"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment