Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inform user of outdated Docker Desktop Version #693

Open
deeplow opened this issue Jan 30, 2024 · 9 comments · May be fixed by #1037
Open

Inform user of outdated Docker Desktop Version #693

deeplow opened this issue Jan 30, 2024 · 9 comments · May be fixed by #1037

Comments

@deeplow
Copy link
Contributor

deeplow commented Jan 30, 2024

Even though we are shipping updates when critical vulnerabilities are found in the container image, the user may be running an outdated Docker Desktop version, which in the worst-case scenario is a container escape vulnerability, which completely undermines the security of the system.

We should add to the updater a way of notifying the user of Docker Desktop updates.

@deeplow deeplow mentioned this issue Feb 15, 2024
60 tasks
@apyrgio apyrgio changed the title Updater: also Inform User of Outdated Docker Desktop Version updater: inform user of outdated Docker Desktop Version Mar 7, 2024
@apyrgio apyrgio changed the title updater: inform user of outdated Docker Desktop Version Inform user of outdated Docker Desktop Version Mar 7, 2024
@harrislapiroff harrislapiroff added this to the 0.7.0 milestone Mar 7, 2024
@almet
Copy link
Contributor

almet commented Jun 11, 2024

As I understand it, the goal here is to have a way to prompt the user that their installed Docker Desktop version is outdated, when it's the case.

My understanding is that it should only be checked on Windows and macOS machines, as Linux doesn't rely on Docker Desktop.

How Docker desktop checks for the latest release.

As Docker Desktop is closed-source, I did some reverse engineering (using mitm-proxy) to find how Docker Desktop itself is looking for updates.

I found this URL is used on my Apple Silicon machine:

https://desktop.docker.com/mac/main/arm64/appcast.xml

It's returning XML unfortunately (I wish it would be JSON, but 🤷🏼‍♂️)

Here is the generic version:

https://desktop.docker.com/{platform}/main/{architecture}/appcast.xml

Where:

  • {platform} is one of linux, mac or win
  • {architecture} is one of arm64 and amd64

In fact, this appcast.xml file is defined by Sparkle and defined here.

Changes to the current code base

The current code base already has a way to do some checks, which is documented here, and I plan on doing the following changes:

  1. Change the name of the settings so they are more specific (changing updater_{check,latest_version,changelog} to updater_release_*), and providing a way to migrate the old settings to this new naming.

  2. Introducing new settings:

    • updater_docker_check which will make it possible for the user to enable / disable this check;
    • updater_docker_latest_version, storing the latest known remote version
    • eventually updater_docker_latest_changelog where we could cache the changelog (provided by appcast.xml)

    The settings would then look like this:

    		# Updater settings
            "updater_last_check": None,  # last check in UNIX epoch (secs since 1970)
            "updater_errors": 0,
            
            # Update release settings
            "updater_release_check": None,
            "updater_release_latest_version": get_version(),
            "updater_release_latest_changelog": "",
            
            # Update docker settings
            "updater_docker_check": None,
            "updater_docker_latest_version": None,
            "updater_docker_latest_changelog": "",
  3. Use the already-in-place mechanism to do the checks, additionally checking for this new version check if it's enabled / not disabled, depending if we want to make this opt-in or opt-out (I would advise asking the user, so it's opt-in, to not leak anything to third parties without user consent).

Here are command lines for this. (Tested on macOS and windows) :

docker version --format '{{.Server.Platform.Name}}'
"Docker Desktop 4.19.0 (106363)"

Security considerations

Parsing a remotely loaded XML file can be an attack vector, as there are multiple XML vulnerabilities out there. To circumvent this, relying on defusedxml might help.

That would also be good to have another non-xml way to get the latest version, but that would diverge from the official way, as far as I'm aware.

@apyrgio
Copy link
Contributor

apyrgio commented Jun 11, 2024

Very cool Alexis, thanks a lot for the dig! Diving into your comments right now:

It seems that the only way to check if there's a new Docker Desktop version out is to:

  1. Hit a URL that's in a location that Docker dictates, and is not advertised by default.
  2. Parse the returned XML in a safe way (didn't know about defusedxml, nice), and grab the latest release.
    • Which is the latest release btw? Are we sure that the user can install it? I'm seeing some restrictions in the xml:

      <sparkle:minimumSystemVersion>
      ( [EditionID] != Home && [EditionID] != HomeEval && [EditionID] != Core && [EditionID] != CoreN && [EditionID] != CoreSingleLanguage && [EditionID] != CoreCountrySpecific && [BuildNumber] >= 19044 ) || ( [BuildNumber] >= 19044 )
      </sparkle:minimumSystemVersion>
      

      Also, I don't know if they have any beta/stable channels, which may confuse our parsing logic.

What I'm concerned about is that we need to handle the following cases:

  1. An appcast.xml URL that is not there (highly unlikely, but it can be the case)
  2. Parsing XML responses securely.
  3. Getting the wrong latest release in the appcast.xml (e.g., because the user is in a system that cannot upgrade to it)
  4. Disabled update checks by the user in Docker Desktop settings

From a UX perspective, based on your suggestions, I understand that we also need to:

  1. Prompt the user twice, once to enable Dangerzone updates, and once to check for Docker Desktop updates.
    • Do so only if Docker Desktop is installed, else the user may not understand what we ask from them.
  2. Grab the Docker Desktop changelog and show it to the user
  3. Have a backoff mechanism as well.

The security audit that spawned this issue says the following:

The assessment team recommends implementing a feature in Dangerzone that checks the host system for the
latest version of Docker/Docker Desktop upon startup. If the feature detects an outdated Docker installation,
Dangerzone could then provide a warning to the user, recommending an update. This precaution aims to
mitigate the risk of attackers exploiting vulnerabilities within the container to escape to the host system.

It assumed that a mechanism existed locally where you could check for the latest version of Docker. It would be great if docker info or docker version provided this info, but unfortunately it doesn't. With that said, I believe that reimplementing a subset of the Sparkle client in our application for another app (Docker) would open a different can of worms than the ones we have now. It can work, sure, but we have to be very careful with regards to security and user privacy.

So, ultimately I think we should think this through before going forward. Maybe there's another way with less corner cases that can work here, at least for a subset of the affected users.

@almet
Copy link
Contributor

almet commented Jun 11, 2024

Thanks for the feedback. I agree that redoing a sparkle client seems superfluous, and I share your concerns about the restrictions present in the XML, which seem to follow a language we don't know.

You comment made me look for alternate ways to know the latest available version of Docker Desktop. Maybe Docker Desktop is storing the data somewhere we can reuse ? 🤔 That would mean the checks are done out of band for us, and that we can reuse their code by just looking at the results.

But… I'm not even sure that's possible. I'll have a closer look.

@almet
Copy link
Contributor

almet commented Jun 11, 2024

After some tinkering on my system, I'm unable to find this information. I'm putting here my findings, but I'm not sure they're relevant.

I've been looking at the following locations:

~/Library/Group\ Containers/group.com.docker/, contains some version information, but it's fairly weird, I'm not sure we should rely on it:

cat unleash-repo-schema-v1-Docker\ Desktop.json | jq ".SidebarLayout"
{
  "name": "SidebarLayout",
  "description": "Enables new Sidebar Layout for Docker Desktop",
  "enabled": true,
  "strategies": [
    {
      "id": 0,
      "name": "flexibleRollout",
      "constraints": [
        {
          "contextName": "version",
          "operator": "SEMVER_LT",
          "values": [],
          "value": "4.31.0",
          "caseInsensitive": false,
          "inverted": true
        }
      ],
      "parameters": {
        "groupId": "SidebarLayout",
        "rollout": "100",
        "stickiness": "default"
      },
      "segments": null
    }
  ],
  "createdAt": "0001-01-01T00:00:00Z",
  "strategy": "",
  "parameters": null,
  "variants": []
}

There is a settings.json file there, where we can see if the automatic updates are activated, what's the channel, etc. It might prove useful.

cat settings.json | jq | grep -i Update

  "updateAvailableTime": 1692453100698,
  "updateInstallTime": 0,
  "disableUpdate": false,
  "acceptCanaryUpdates": false,
  "useNightlyBuildUpdates": false,
  "autoDownloadUpdates": false,
  "updateHostsFile": false,

@almet
Copy link
Contributor

almet commented Jun 12, 2024

FYI, I'm not pursuing the effort on this pull request because the path forward is not clear. I've pushed the changes (related to renaming the settings) to the 2024-06-docker-desktop-version-check branch in case it's useful for the future.

@apyrgio
Copy link
Contributor

apyrgio commented Jun 12, 2024

Thanks for documenting your findings Alexis. They will be really useful once we decide to work again on this issue. For the record, I was thinking that we could at least notify the user that their Docker Desktop installation is outdated if, e.g., it's been 6 months since the last release (docker version returns the build date of the software, for instance).

This is one possible metric we can use that does not rely on external sources. It doesn't cover every use case, sure, but it will help the vast majority of our users, who have installed Docker Desktop at some point and then forgot about it.

One other thing I was considering is if Docker Desktop already has such a mechanism. My thinking was that:

  • Our users need to start Docker Desktop manually, in order to run Dangerzone
  • Sparkle project can notify users about updates, if they are critical

So, if Docker Desktop informs users about important upgrades on startup, we're good.

@almet almet self-assigned this Jun 13, 2024
@apyrgio apyrgio removed this from the 0.7.0 milestone Jun 13, 2024
@harrislapiroff harrislapiroff added this to the 0.8.0 milestone Jun 13, 2024
@harrislapiroff harrislapiroff assigned apyrgio and unassigned almet Jul 11, 2024
@almet
Copy link
Contributor

almet commented Sep 9, 2024

One other thing I was considering is if Docker Desktop already has such a mechanism. My thinking was that:

  • Our users need to start Docker Desktop manually, in order to run Dangerzone
  • Sparkle project can notify users about updates, if they are critical

So, if Docker Desktop informs users about important upgrades on startup, we're good.

This is the case: Docker Desktop is displaying a warning to the users when they start the program, at least on OSX (I'm not sure on Windows, but I expect this to be the same, we should check).

Here is how this is displayed to the end users:

  1. The small tray icon has a exclamation mark next to it (I'm not sure it's related, but I think)
image
  1. When opening the application, on the bottom-right corner there is a "New version available" message coming up.
image

None of these are blocking, though.

Also worth nothing: in the "software updates" settings, there is an "Always download updates" checkbox:

image

I was thinking that we could at least notify the user that their Docker Desktop installation is outdated if, e.g., it's been 6 months since the last release (docker version returns the build date of the software, for instance).

That would certainly be useful. I'm also thinking we could add a minimal supported version in the dangerzone code somewhere (potentially even one for Windows and one for MacOS), and warn the user if the installed version doesn't match this.

Because we're issuing a release every two months (approximately), it would allow to warn our users to upgrade quicker than the 6 month cap you're mentioning.

We could check the version returned by docker version:

$ docker version --format '{{.Server.Platform.Name}}'
"Docker Desktop 4.19.0 (106363)"

@apyrgio
Copy link
Contributor

apyrgio commented Sep 9, 2024

This is the case: Docker Desktop is displaying a warning to the users when they start the program, at least on OSX

Pretty awesome dig, and thanks a lot for the image. So, it seems that Docker does not urge the users to update, but it does inform them about it (kind of like our own update notifications).

That would certainly be useful. I'm also thinking we could add a minimal supported version in the dangerzone code somewhere (potentially even one for Windows and one for MacOS), and warn the user if the installed version doesn't match this.

That's actually a really good idea! Are you thinking of showing a warning notification to our users, or something more visible, like a pop-up? Note that for Dangerzone updates, we show just a notification bubble for the time being.

@almet
Copy link
Contributor

almet commented Sep 12, 2024

That's actually a really good idea! Are you thinking of showing a warning notification to our users, or something more visible, like a pop-up? Note that for Dangerzone updates, we show just a notification bubble for the time being.

That's a good question, and the answer depends on how we want this to be annoying for our users. If we don't want to be too annoying, reusing the notification bubble might be enough.

@almet almet moved this from Todo to In Progress in Dangerzone ✨ Nov 28, 2024
@almet almet assigned almet and unassigned apyrgio Nov 28, 2024
almet added a commit that referenced this issue Nov 28, 2024
This only happens on Windows and macOS.

Fixes #693
almet added a commit that referenced this issue Dec 18, 2024
This only happens on Windows and macOS.

Fixes #693
almet added a commit that referenced this issue Dec 18, 2024
This only happens on Windows and macOS.

Fixes #693
@almet almet moved this from In Progress to PR Review in Dangerzone ✨ Dec 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: PR Review
Development

Successfully merging a pull request may close this issue.

5 participants