1

I've written a program in Python which is often modified. I have about a dozen testers (hopefully, that number will increase) and they use the program in a portable version, which doesn't require them to install anything. I've tried recently to provide an auto-updater in the program, so they could benefit from the last updates without losing their configuration, or needing to manually download the new build.

I would like to do it as securely as possible, however, considering the possible security risks such an updater can present. Here's what I've come up with.

  1. When the program starts, it checks it's build version (hard-coded).
  2. It compares this build version with the most recent build version available on the server. This check is done through https, and doesn't do much, except getting the information on the server and comparing it.
  3. If a newer build is available, the user is asked whether he/she wants to download and install it. If yes, the program closes after launching the updater (a different program).
  4. The updater downloads the new build from the server. It's a zip archive at this point.
  5. The updater extracts the zip archive in a temporary directory created for this purpose. Then it calls a batch file. The updater is closed before the batch file is launched.
  6. The batch file copies everything in the temporary directory to the current directory, except for the settings that are kept as they are. Then, when it's about to close, it calls the client again.
  7. Which starts again, updated.

The batch file is used because the updater cannot replace itself (the operating system doesn't seem to like that very much, and I can't blame it).

This works pretty well. Some users have told me the initial connection in https doesn't work, which is quite puzzling, but I don't think doing the same thing by http is a good idea, too easy to alter the zip file. Is it, though?

Perhaps my list of step is really wrong for security. I'd like to have your ideas and comments, on what should be dropped and what could be strengthened.

Thank you in advance,

vincent-lg
  • 539
  • 7
  • 15
  • Batch files are Windows-specific, so you're already losing many potential customers that use Linux or macOS. – ForceBru Oct 24 '16 at 18:09
  • @ForceBru Though there are versions of bash and the like for Windows (in fact, recent versions of Windows 10 include a bash shell built in, though you have to enable it in system options), so a shell script instead may be useful. OP could just write the script in Python itself as an additional file, though. This all assumes that user1315400 is even looking for non-Windows customers or didn't just use the wrong terminology by accident, of course. – JAB Oct 24 '16 at 18:24
  • Sorry, I hadn't mentioned, for the time being all my testers are using Windows, but in the end I'd like to move to platform-independent. In that case, of course, the batch step would need to offer alternatives in bash (that sounds the most portable alternative). I personally have Cygwin on my computer, and a direct access to bash, but that may not be the case of all users. Still, it's possible to create different alternatives based on the OS being used. – vincent-lg Oct 24 '16 at 18:39

1 Answers1

0

Hi I have previously answered a question similar to this here is the link Answer

But it is different from your needs but I think it is better.

here is the code

import tkinter as tk #for you it is pyqt5
from tkinter import * #MessageBox and Button
import requests #pip install requests
import os #part of standard library
import sys #part of standard library

VERSION = 4

b1 = Button(frame, text = "Back", command = homepage)
b1.pack(ipadx= 10, ipady = 10, fill = X, expand = False, side = TOP)

checkupdate = Label(frame, text = "Looking for updates", font = ("Arial", 14))
checkupdate.pack()

try:
    link = "https://raw.githubusercontent.com/SomeUser/SomeRepo/main/SomeFolder/version.txt"
    check = requests.get(link)
    
    if float(VERSION) < float(check.text):
        mb1 = messagebox.askyesno('Update Available', 'There is an update available. Click yes to update.')
        if mb1 is True:
            filename = os.path.basename(sys.argv[0])

            for file in os.listdir():
                if file == filename:
                    pass

                else:
                    os.remove(file)

            exename = f'NameOfYourApp{float(check.text)}.exe'
            code = requests.get("https://raw.githubusercontent.com/SomeUser/SomeRepo/main/SomeFolder/NewUpdate.exe", allow_redirects = True)
            open(exename, 'wb').write(code.content)

            root.destroy()
            os.remove(sys.argv[0])
            sys.exit()
            
        elif mb1 == 'No':
            pass
        
    else:
        messagebox.showinfo('Updates Not Available', 'No updates are available')

except Exception as e:
    pass
Dodu
  • 109
  • 2
  • 8
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/late-answers/31451973) – Muhammad Mohsin Khan Apr 05 '22 at 09:38