From 3df97be56e21bb08323a8a0a4793f130593a2745 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Mon, 28 Sep 2026 12:03:19 +0100 Subject: [PATCH] bitbake: toastergui/views: Replace os.system call with improved parameter handling Using bash to handle execution parameters isn't a great idea, particularly using os.system. In theory this could be exploited by injecting shell code through the placeholders although whether this can be done without security tokens is unclear. Regardless, we have been cleaning up shell=True and similar calls in the codebase. Instead use shlex to parse the callback command, then we can iterate the parameters to perform any expansions needed and avoid the need to call any shell expansion. Any invalid data will then just become an invalid image target to bitbake. Reported-by: Lei Zhang <18792670849@163.com> (Bitbake rev: d3b32587c2314febf96897f97e0172790b4fc1cf) Signed-off-by: Richard Purdie Signed-off-by: Paul Barker --- bitbake/lib/toaster/toastergui/views.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py index 40aed265dc..7ea3cb0bfe 100644 --- a/bitbake/lib/toaster/toastergui/views.py +++ b/bitbake/lib/toaster/toastergui/views.py @@ -8,6 +8,7 @@ import ast import re +import shlex import subprocess import sys @@ -1558,7 +1559,7 @@ if True: # perform the final actions for the project specific page def project_specific_finalize(cmnd, pid): project = Project.objects.get(pk=pid) - callback = project.get_variable(Project.PROJECT_SPECIFIC_CALLBACK) + callback = shlex.split(project.get_variable(Project.PROJECT_SPECIFIC_CALLBACK) or "") if "update" == cmnd: # Delete all '_PROJECT_PREPARE_' builds for b in Build.objects.all().filter(project=project): @@ -1571,16 +1572,15 @@ if True: management.call_command('builddelete', str(b.id), interactive=False) # perform callback at this last moment if defined, in case Toaster gets shutdown next default_target = project.get_variable(Project.PROJECT_SPECIFIC_DEFAULTIMAGE) - if callback: - callback = callback.replace("",default_target) + for i in range(len(callback)): + callback[i] = callback[i].replace("", default_target) if "cancel" == cmnd: - if callback: - callback = callback.replace("","none") - callback = callback.replace("--update","--cancel") + for i in range(len(callback)): + callback[i] = callback[i].replace("", "none") + callback[i] = callback[i].replace("--update", "--cancel") # perform callback at this last moment if defined, in case this Toaster gets shutdown next - ret = '' if callback: - ret = os.system('bash -c "%s"' % callback) + subprocess.run(callback, shell=False) project.set_variable(Project.PROJECT_SPECIFIC_CALLBACK,'') # Delete the temp project specific variables project.set_variable(Project.PROJECT_SPECIFIC_ISNEW,'')