Skip to content

Instantly share code, notes, and snippets.

@april
Last active November 25, 2024 02:43
Show Gist options
  • Save april/3da7c3720b0d9f3ee7dc9a95f623578d to your computer and use it in GitHub Desktop.
Save april/3da7c3720b0d9f3ee7dc9a95f623578d to your computer and use it in GitHub Desktop.
find all apps using Electron and their versions, on macOS systems
# latest supported electron version as of october 2024
LATEST_SUPPORTED_VERSION=30
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m' # no color
mdfind "kind:app" 2>/dev/null | sort -u | while read app;
do
filename="$app/Contents/Frameworks/Electron Framework.framework/Electron Framework"
if [[ -f $filename ]]; then
appname=$(echo $app | awk -F'/' '{print $NF}')
electronVersion=$(strings "$filename" | grep "Chrome/" | grep -i Electron | grep -v '%s' | sort -u | cut -f 3 -d '/')
major=$(echo $electronVersion | awk -F'.' '{print $1}')
if [ "$major" -lt "$LATEST_SUPPORTED_VERSION" ]; then
printf "App Name: ${RED}${appname}${NC}\n"
else
printf "App Name: ${GREEN}${appname}${NC}\n"
fi
echo "Electron Version: ${electronVersion}"
echo -n "File Name: ${filename}"
echo -e "\n"
fi
done
@TrimarcJake
Copy link

Quick and dirty improvement of output:

for filename in /Applications/*.app/Contents/Frameworks/Electron\ Framework.framework/Electron\ Framework
do
  appName=$(echo $filename | cut -f 3 -d '/') 
  echo "App Name:         $appName"

  electronVersion=$(strings "$filename" | grep "Chrome/" | grep -i Electron | grep -v '%s' | sort -u | cut -f 3 -d '/')
  echo "Electron Version: $electronVersion"
  
  echo -n "File Name:        $filename "
  echo -e "\n"
done

@april
Copy link
Author

april commented Sep 28, 2023

That's great Jake, I'll make that the default version. :)

@adamshostack, I'm thinking about ways to improve this.

@TrimarcJake
Copy link

Cool! I was also going to add in highlighting of vulnerable versions, but that pesky job thing got in the way.

@april
Copy link
Author

april commented Sep 28, 2023

@adamshostack (and @TrimarcJake) -- I just made a change such that it will find every app on your system now, regardless of where it lives. If you'd be willing to test it out, I'd appreciate that.

@TrimarcJake
Copy link

@april working for me!

@april
Copy link
Author

april commented Sep 28, 2023

Heck yeah, thanks for testing it for me and thanks to @adamshostack for nudging me to think about a better way to find things. :)

@adamshostack
Copy link

Win!

~/Downloads/Twitter Archive Browser.app. No way there'd be bad webp there! :)

@leoncowle
Copy link

Very useful. Thanks!

Tiniest did-you-know:
You can replace:
appName=$(echo $filename | cut -f 3 -d '/')
with:
appName=$(basename "${app}");

@april
Copy link
Author

april commented Sep 28, 2023

Nice thinking, I inlined it as well.

@TrimarcJake
Copy link

@leoncowle TIL!

@leoncowle
Copy link

Nice thinking, I inlined it as well.

Normally I would inline too, but ${app} needs quotes around it (i.e. "${app}"), otherwise basename only uses the 1st word of the app name if it has space(s) in it. Doable inline, with escaping quotes, etc, but maybe easier to keep separate?

@april
Copy link
Author

april commented Sep 28, 2023

Are you sure? This worked just fine for me in bash and zsh. 😅

@TrimarcJake
Copy link

Same:
image

@leoncowle
Copy link

Hmmmm, on mine (bash, not using the zsh shebang at the top):

2nd one is Teams, but name is just showing as "Microsoft". Latest copy & paste of your code above.

...
...

App Name: Authy
Electron Version: 16.2.8
File Name: /Applications/Authy Desktop.app/Contents/Frameworks/Electron Framework.framework/Electron Framework

App Name: Microsoft
Electron Version: 19.1.8
File Name: /Applications/Microsoft Teams.app/Contents/Frameworks/Electron Framework.framework/Electron Framework

App Name: Postman.app
Electron Version: 18.3.5
File Name: /Applications/Postman.app/Contents/Frameworks/Electron Framework.framework/Electron Framework

...
...

@TrimarcJake
Copy link

@leoncowle I replicated your behavior.
image

@TrimarcJake
Copy link

TrimarcJake commented Sep 28, 2023

You can still inline it, I think?

This

echo "App Name:          $(basename "${app}")"

worked great!

@adamshostack
Copy link

adamshostack commented Sep 28, 2023

Randomly, why find apps vs "Electron Framework.framework"? Would that be faster and more accurate? (Are there places there's files of kind other than app that might have electron?)

Edit: mdfind doesn't seem to search inside apps

bash-3.2$ mdfind 'Electron Framework.framework' 2>/dev/null | sort -u
/Users/adam/bin/vulnerable-electron.sh
bash-3.2$

@april
Copy link
Author

april commented Sep 29, 2023

Because mdfind doesn't search inside bundles. :\

@janvhs
Copy link

janvhs commented Sep 29, 2023

Btw, mdfind uses the user's locale for their syntax. Therefore a German user would need to use mdfind "art:app"

@april
Copy link
Author

april commented Sep 29, 2023

I tried overriding LANG=de_DE.UTF-8 LC_CTYPE=de_DE.UTF-8 LC_ALL=de_DE.UTF-8, and setting the language for Terminal to German, and it still insists on using en_US.

Does overriding any of those to en_US.UTF-8 let mdfind work with kind:app?

@janvhs
Copy link

janvhs commented Sep 30, 2023

No that doesn't seem to change anything. Idk maybe mdfind uses the language set via system settings or something

@janvhs
Copy link

janvhs commented Sep 30, 2023

Just changed my mac to English and now it works

@FnTm
Copy link

FnTm commented Oct 5, 2023

Wanted to share a slightly updated version of the script above that we used internally to help make running the script more actionable for our employees. The main change is that it outputs and highlights only the apps that are on unsafe electron versions.

#!/usr/bin/env bash

RED='\033[0;31m'
NC='\033[0m' # No Color

# patched versions for CVE-2023-4863: 22.3.24, 24.8.3, 25.8.1, 26.2.1
mdfind "kind:app" 2>/dev/null | sort -u | while read app;
do
  filename="$app/Contents/Frameworks/Electron Framework.framework/Electron Framework"
  if [[ -f $filename ]]; then

    electronVersion=$(strings "$filename" | grep "Chrome/" | grep -i Electron | grep -v '%s' | sort -u | cut -f 3 -d '/')

    semver=( ${electronVersion//./ } )
    major="${semver[0]}"
    minor="${semver[1]}"
    patch="${semver[2]}"
    echo "${major}.${minor}.${patch}"

    if [[ ( $major -lt 22 ) || ( $major == 22 && $minor -lt 3 ) || ( $major == 22 && $minor == 3 && $patch -lt 26 )
    || ( $major == 23 )
    || ( $major == 24 && $minor -lt 8 ) || ( $major == 24 && $minor == 8 && $patch -lt 6 )
    || ( $major == 25 && $minor -lt 8 ) || ( $major == 25 && $minor == 8 && $patch -lt 4 )
    || ( $major == 26 && $minor -lt 2 ) || ( $major == 26 && $minor == 2 && $patch -lt 4 )
    || ( $major == 27 && $minor -lt 0 ) || ( $major == 27 && $minor == 0 && $patch -lt 0 )
     ]]; then
      printf "App Name:          ${RED}$(basename ${app})${NC}\n"
      echo "Electron Version:  $electronVersion"
      echo -n "File Name:         $filename "
      echo -e "\n"
    fi
  fi
done

@april
Copy link
Author

april commented Oct 23, 2024

went ahead and updated the script today:

  • it's no longer specifically looking for CVE versions (since they're all unsupported version now anyways)
  • it does look for unsupported versions, and marks them in red versus green
  • it should now be both bash and zsh compatible

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment