Skip to content

Instantly share code, notes, and snippets.

@diachedelic
Last active June 30, 2022 02:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save diachedelic/fc68e08443a2a8c1dce831a9c7dfd300 to your computer and use it in GitHub Desktop.
Save diachedelic/fc68e08443a2a8c1dce831a9c7dfd300 to your computer and use it in GitHub Desktop.
A shell script which detects the bloated dependencies in a package.json.
#!/bin/bash
# fatdeps.sh is a script that counts the number of subdependencies of every
# dependency found in a package.json file. It can be used to discover bloat,
# which is a major security risk in Node.js and browser applications.
# fatdeps.sh depends on the 'jq' and 'npx' commands.
# USAGE
# $ ./fatdeps.sh /path/to/package.json
# EXAMPLE OUTPUT
# Nr. deps Package Size
# 2 JSONStream@1.3.5 447.79kb
# 44 archiver@2.1.1 2.63mb
# 0 async@0.2.10 72.93kb
# 1 axios@0.21.4 393.63kb
# 0 bcryptjs@2.4.3 216.21kb
# 7 chai@4.3.6 931.86kb
# 0 clone@2.1.2 15.51kb
# 0 cookie@0.3.1 16.43kb
# 2 country-language@0.1.7 358.24kb
# 1 diceware-generator@3.0.1 22.34kb
# 0 diceware-wordlist-en-eff@1.0.1 169.34kb
# 0 email-addresses@2.0.2 92.69kb
# 1 emoji-strip@1.0.1 50.11kb
# 0 esbuild@0.12.29 90.01kb
# 0 faker@4.1.0 5.23mb
# 0 humanname@0.2.2 23.31kb
# 9 knox@0.9.2 409.57kb
# 99 mapkit-token@1.0.3 2.79mb
# 0 mime@1.6.0 50.53kb
# 86 mocha@8.4.0 6.01mb
# You can help protect your application from supply chain attacks by removing
# excessively bloated dependencies, which disproportionately increase your
# application's attack surface.
package_json=${1:-package.json}
# We parse the output of howfat with this horrendous regular expression, so that
# we can print the data like the table above.
rx_output="^([@a-zA-Z][^@]+)@([^@]+)@([^ ]+) \((([^,]+) deps?, )?(([^,]+), )[^,]+\)"
# Capturing groups:
# [1] package name
# [2] version specifier
# [3] fetched version
# [5] number of subdependencies
# [7] size
jq -r '
.dependencies + .devDependencies
| to_entries
| map(.key + "@" + .value)
| .[]
' "$package_json" \
| xargs npx howfat@0.2.6 \
--no-colors \
--reporter tree \
| while read -r line; do
# Loop thru each line, looking for top level dependencies. Print the relevant
# portions.
if [[ $line =~ $rx_output ]]
then
name="${BASH_REMATCH[1]}"
version="${BASH_REMATCH[3]}"
subdeps="${BASH_REMATCH[5]:-0}"
size="${BASH_REMATCH[7]}"
echo -e "$subdeps\t$name@$version\t$size"
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment