fix(epic): keep archive symlinks from redirecting the desktop layer and icon

This commit is contained in:
maxjivi05 committed 2026-11-10 07:50:12 -05:00
1 parent bb1996c715
commit 73aed0d71e
2 files changed
+25 -1

No files matched your search

@@ -396,6 +396,8 @@ def extract_app(image, dest, desktop=()):
raise Failure("app-format")
extract_deb(image, staging)
layer = os.path.join(staging, DESKTOP)
if not inside(os.path.realpath(staging), layer):
raise Failure("app-extract")
os.makedirs(layer, exist_ok=True)
for package in desktop:
if not is_deb(package):
@@ -403,6 +405,7 @@ def extract_app(image, dest, desktop=()):
extract_deb(package, layer, lambda name: any(name.startswith(prefix) for prefix in DESKTOP_KEEP))
icon = os.path.join(staging, DEB_ICON)
if os.path.isfile(icon):
remove(os.path.join(staging, ICON))
shutil.copyfile(icon, os.path.join(staging, ICON))
if not app_complete(staging):
raise Failure("app-extract")
+22 -1
View File
@@ -217,7 +217,7 @@ def deb(path, entries, compression="gz"):
class LauncherDebTest(EpicTestCase):
def launcher(self):
def launcher(self, extra=()):
return deb(self.tmp / "EpicGamesLauncher-x86_64.deb", [
("./usr", {"kind": "dir"}),
("./usr/bin/EpicGamesLauncher", {"data": b"egl", "mode": 0o755}),
@@ -226,6 +226,7 @@ class LauncherDebTest(EpicTestCase):
("./usr/share/applications/epic-games-launcher.desktop", {"data": b"[Desktop Entry]\n"}),
("./usr/bin/egl", {"link": "/usr/bin/EpicGamesLauncher"}),
("../escape", {"data": b"x"}),
*extra,
])
def webkit(self):
@@ -258,6 +259,26 @@ class LauncherDebTest(EpicTestCase):
self.assertEqual(str(dest / "usr/bin/EpicGamesLauncher"), G["app_command"](str(dest)))
self.assertEqual(str(libs), G["desktop_libs"](str(dest)))
def test_archive_symlinks_cannot_redirect_the_desktop_layer_or_icon(self):
outside = self.tmp / "outside"
outside.mkdir()
dest = self.state / "app/0.113.0+g1"
escape = os.path.relpath(outside, Path(str(dest) + ".staging"))
launcher = self.launcher([("./desktop", {"link": escape}),
("./epic-games-launcher.png", {"link": escape + "/target"})])
with self.assertRaises(G["Failure"]) as caught:
G["extract_app"](str(launcher), str(dest), [str(self.webkit())])
self.assertEqual("app-extract", str(caught.exception))
self.assertFalse((outside / "usr").exists())
self.assertFalse((outside / "target").exists())
icon_dest = self.state / "app/0.113.0+g2"
icon_escape = os.path.relpath(outside / "target", Path(str(icon_dest) + ".staging"))
G["extract_app"](str(self.launcher([("./epic-games-launcher.png", {"link": icon_escape})])),
str(icon_dest), [str(self.webkit())])
self.assertEqual(b"png", (icon_dest / "epic-games-launcher.png").read_bytes())
self.assertFalse((outside / "target").exists())
def test_a_launcher_without_its_desktop_layer_is_refused(self):
dest = self.state / "app/0.113.0+g1"
with self.assertRaises(G["Failure"]) as caught: