darktrojan / openwith

Open With add-on for Firefox
https://addons.mozilla.org/addon/open-with/
412 stars 71 forks source link

Catalina: quarantine XA and warnings by macOS malware scanner with JDownloader #271

Open JayBrown opened 4 years ago

JayBrown commented 4 years ago

I'm using the OpenWith FF extension i.a. to open URLs in JDownloader. The setting in OpenWith options is straight-forward: "/Applications/JDownloader 2.0/JDownloader2.app/Contents/MacOS/JavaApplicationStub"

If I open iTerm and manually execute e.g. "/Applications/JDownloader 2.0/JDownloader2.app/Contents/MacOS/JavaApplicationStub" 'https://foo', everything works fine.

But if the URL is passed from Firefox via OpenWith via ~/.config/OpenWithFF/open_with_mac.py to JDownloader, the extension seems to be creating temporary files, and also calling a 7zip dylib, and since the parent process is Firefox, macOS apparently treats it as a download, ergo these files receive the dreaded quarantine extended attribute, which spawns the Gatekeeper and malware scan in Catalina, and the user will get annoying prompts:

snap1

snap2

Once I also got a third prompt, but I failed to create a screenshot.

At any rate, JDownloader still launches fine and will accept the URL for download, but those warnings are definitely a nuisance.

I can't say if something can be done within the scope of OpenWith: since this is a browser extension, I assume that macOS will treat everything coming from OpenWith as coming from the browser, i.e. as a "download", and therefore it will receive the quarantine XA.

I will however see, if I can slap a little shell script in the middle to circumvent this… and will report back.

JayBrown commented 4 years ago

Addendum: I tried it with a small shell script instead…

#!/bin/zsh
# open with JDownloader
for url in "$@"
do
    "Applications/JDownloader 2.0/JDownloader2.app/Contents/MacOS/JavaApplicationStub" "$url"
done

…which launches JDownloader alright, but I'm still getting the prompts. So macOS is probably looking at the process chain, going all the way back to Firefox, ergo quarantine XA.

JayBrown commented 4 years ago

Workaround solution would be to use OpenWith to pass the URL(s) to a shell script that writes them into individual files in a cache directory. That cache dir is in turn watched by a macOS Launch Agent, which will cat the individual cache files, and then open them in JDownloader. But it's just a workaround… see below… and there might be hickups somewhere… but I've tested it, and it seems to work… no prompts from macOS' malware scan.

First script (called with OpenWith in Firefox etc.):

#!/bin/zsh

# jdownloader-ffow2cache.zsh v0.1
# open with JDownloader (interim script)

cachedir="$HOME/.cache/OpenWithFF"
mkdir -p "$cachedir" 2>/dev/null

for url in "$@"
do
    posixdate=$(date +%s)
    echo -n "$url" > "$cachedir/$posixdate"
    xattr -cr "$cachedir/$posixdate" 2>/dev/null
done

Second script (put somewhere in your $PATH, e.g. /usr/local/bin)

#!/bin/zsh

# jdownloader-launch.zsh v0.1
# launch JDownloader

open -a JDownloader2 &>/dev/null &
exit

Third script (executable for the LaunchAgent, put e.g. in /usr/local/bin):

#!/bin/zsh

# jdownloader-cache2jd.zsh v0.1
# Open with JDownloader (cache to JDownloader / LaunchAgent executable)

jdloc="/Applications/JDownloader 2.0/JDownloader2.app/Contents/MacOS/JavaApplicationStub"

tmpdir="/tmp/owjd"
mkdir -p "$tmpdir" 2>/dev/null

cachedir="$HOME/.cache/OpenWithFF"

sleep 1

cachelist=$(find "$cachedir" -type f | sort)
if [[ $(echo "$cachelist" | wc -l) -gt 1 ]] ; then
    sleeper=true
else
    sleeper=false
fi
while read -r cachefile
do
    echo "Cache file: $cachefile"
    url=$(cat "$cachefile" 2>/dev/null)
    if ! [[ $url ]] ; then
        echo "No URL in cache file"
        rm -f "$cachefile" 2>/dev/null
        continue
    else
        echo "URL: $url"
    fi
    posixdate=$(basename "$cachefile")
    if [[ -f "$tmpdir/$posixdate" ]] ; then
        echo "Pre-existing cache file"
        rm -f "$cachefile" 2>/dev/null
        continue
    else
        echo "New cache file"
        if ! [[ $(ps aux | grep "JDownloader 2.0/JDownloader2.app/Contents/MacOS/JavaApplicationStub" | grep -v "grep" 2>/dev/null) ]] ; then
            zsh -c "/usr/local/bin/jdownloader-launch.zsh" &
            sleep 8
        fi
        "$jdloc" "$url"
        mv "$cachefile" "$tmpdir/$posixdate" 2>/dev/null
        if $sleeper ; then
            sleep 10
        fi
    fi
done < <(echo -e "$cachelist"

The xml plist for the LaunchAgent (substitute <USER> with your actual username, write to ~/Library/LaunchAgents & load with launchctl):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>local.lcars.OpenWithJDownloader</string>
    <key>LowPriorityIO</key>
    <true/>
    <key>Nice</key>
    <integer>5</integer>
    <key>ProcessType</key>
    <string>Adaptive</string>
    <key>Program</key>
    <string>/usr/local/bin/jdownloader-cache2jd.zsh</string>
    <key>StandardErrorPath</key>
    <string>/tmp/local.lcars.OpenWithJDownloader.stderr</string>
    <key>StandardOutPath</key>
    <string>/tmp/local.lcars.OpenWithJDownloader.stdout</string>
    <key>WatchPaths</key>
    <array>
        <string>/Users/<USER>/.cache/OpenWithFF</string>
    </array>
</dict>
</plist>